This commit is contained in:
parent
f1d683e7cd
commit
03e9e6bc40
17 changed files with 942 additions and 206 deletions
3
.example.env
Normal file
3
.example.env
Normal file
|
@ -0,0 +1,3 @@
|
|||
GOSCAN__forgejo__URL=
|
||||
GOSCAN__forgejo__BOT_TOKEN=
|
||||
GOSCAN__forgejo__SECRET=
|
155
.gitignore
vendored
155
.gitignore
vendored
|
@ -9,167 +9,14 @@
|
|||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
.idea
|
||||
.fleet
|
||||
# ---> Go
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
go.work.sum
|
||||
|
||||
# env file
|
||||
.env
|
||||
|
||||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
config.yml
|
|
@ -7,7 +7,7 @@ Gosec with some stuff with actions.
|
|||
name: GoSec Scan
|
||||
on:
|
||||
schedule:
|
||||
- cron: "@daily"
|
||||
- cron: "@weekly"
|
||||
push:
|
||||
branches: ["main"]
|
||||
workflow_dispatch:
|
||||
|
@ -19,10 +19,6 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout
|
||||
uses: https://git.shadowhosting.xyz/actions/checkout@v4
|
||||
- uses: https://git.shadowhosting.xyz/actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
- run: go mod download
|
||||
- name: Run Gosec Security Scanner
|
||||
uses: https://git.shadowhosting.xyz/actions/goscan@main
|
||||
```
|
23
Taskfile.yml
Normal file
23
Taskfile.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
version: '3'
|
||||
|
||||
tasks:
|
||||
build-daemon:
|
||||
cmds:
|
||||
- docker buildx build --platform=linux/amd64,linux/arm64/v8 --push -t git.shadowhosting.xyz/actions/goscan-daemon -f docker/Daemon.Dockerfile .
|
||||
build-action:
|
||||
cmds:
|
||||
- docker buildx build --platform=linux/amd64,linux/arm64/v8 --push -t git.shadowhosting.xyz/actions/goscan -f docker/Action.Dockerfile .
|
||||
build:
|
||||
cmds:
|
||||
- task: build-daemon
|
||||
- task: build-action
|
||||
build-dev-daemon:
|
||||
cmds:
|
||||
- docker build -t goscan-dev-daemon -f docker/Daemon.Dockerfile .
|
||||
build-dev-action:
|
||||
cmds:
|
||||
- docker build -t goscan-dev-action -f docker/Action.Dockerfile .
|
||||
build-dev:
|
||||
cmds:
|
||||
- task: build-dev-daemon
|
||||
- task: build-dev-action
|
3
build.sh
3
build.sh
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
docker buildx build --platform=linux/amd64,linux/arm64/v8 --push -t git.shadowhosting.xyz/actions/goscan .
|
447
cmd/daemon.go
Normal file
447
cmd/daemon.go
Normal file
|
@ -0,0 +1,447 @@
|
|||
/*
|
||||
Package cmd
|
||||
Copyright © 2024 Shane C. <shane@scaffoe.com>
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.shadowhosting.xyz/actions/goscan/interfaces"
|
||||
"git.shadowhosting.xyz/shanec/forgejo-sdk/forgejo"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
gitHttp "github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/log"
|
||||
"github.com/gofiber/fiber/v2/middleware/healthcheck"
|
||||
"github.com/gofiber/fiber/v2/middleware/limiter"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ActionTemplate struct {
|
||||
DefaultBranch string
|
||||
ServerURL string
|
||||
}
|
||||
|
||||
const actionTemplate = `name: GoSec Scan
|
||||
on:
|
||||
schedule:
|
||||
- cron: "@weekly"
|
||||
push:
|
||||
branches: ["{{.DefaultBranch}}"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
gosec:
|
||||
name: Gosec Check
|
||||
runs-on: node20-bookworm
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: {{.ServerURL}}/actions/checkout@v4
|
||||
- name: Run Gosec Security Scanner
|
||||
uses: {{.ServerURL}}/actions/goscan@main
|
||||
`
|
||||
|
||||
type OpenPGPEntity struct {
|
||||
*openpgp.Entity
|
||||
}
|
||||
|
||||
func (e *OpenPGPEntity) Sign(message io.Reader) ([]byte, error) {
|
||||
|
||||
signatureBuffer := bytes.NewBuffer(nil)
|
||||
if err := openpgp.DetachSignText(signatureBuffer, e.Entity, message, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signatureBuffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// Sign(message io.Reader) ([]byte, error)
|
||||
|
||||
// daemonCmd represents the daemon command
|
||||
var daemonCmd = &cobra.Command{
|
||||
Use: "daemon",
|
||||
Short: "A brief description of your command",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
forgeClient, err := forgejo.NewClient(viper.GetString("forgejo.url"), forgejo.SetToken(viper.GetString("forgejo.bot_token")))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
user, _, err := forgeClient.GetMyUserInfo()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
conf := &packet.Config{
|
||||
Algorithm: packet.PubKeyAlgoEdDSA,
|
||||
Curve: packet.Curve25519,
|
||||
DefaultCipher: packet.CipherAES256,
|
||||
}
|
||||
|
||||
var pgpEntity OpenPGPEntity
|
||||
|
||||
if _, err := os.Stat(os.Getenv("HOME") + "/keyring.pgp"); err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
entity, err := openpgp.NewEntity("GoSec Git Signing", "", "gosec@git.shadowhosting.xyz", conf)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
publicKeyBuffer := bytes.NewBuffer(nil)
|
||||
publicKeyEncoder, err := armor.Encode(publicKeyBuffer, openpgp.PublicKeyType, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer publicKeyEncoder.Close()
|
||||
|
||||
err = entity.Serialize(publicKeyEncoder)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
publicKeyEncoder.Close()
|
||||
publicKeyArmor := publicKeyBuffer.String()
|
||||
|
||||
file, err := os.OpenFile("keyring.pgp", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = entity.SerializePrivate(file, conf)
|
||||
file.Close()
|
||||
|
||||
token, _, err := forgeClient.GetGPGToken()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
signatureBuffer := bytes.NewBuffer(nil)
|
||||
if err := openpgp.DetachSignText(signatureBuffer, entity, strings.NewReader(token), conf); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
encodedSignatureBuffer := bytes.NewBuffer(nil)
|
||||
signatureEncoder, err := armor.Encode(encodedSignatureBuffer, openpgp.SignatureType, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer signatureEncoder.Close()
|
||||
signatureEncoder.Write(signatureBuffer.Bytes())
|
||||
signatureEncoder.Close()
|
||||
|
||||
if _, _, err := forgeClient.CreateGPGKey(forgejo.CreateGPGKeyOption{
|
||||
ArmoredKey: publicKeyArmor,
|
||||
ArmoredSignature: encodedSignatureBuffer.String(),
|
||||
}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pgpEntity = OpenPGPEntity{
|
||||
Entity: entity,
|
||||
}
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else if err == nil {
|
||||
publicKeyFile, err := os.ReadFile(os.Getenv("HOME") + "/keyring.pgp")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
el, err := openpgp.ReadKeyRing(bytes.NewReader(publicKeyFile))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if len(el) != 1 {
|
||||
log.Fatal("invalid keyring")
|
||||
}
|
||||
|
||||
pgpEntity = OpenPGPEntity{
|
||||
Entity: el[0],
|
||||
}
|
||||
}
|
||||
|
||||
appConfig := fiber.Config{
|
||||
AppName: "GoScan (GoSec & Forgejo)",
|
||||
Network: fiber.NetworkTCP,
|
||||
JSONDecoder: json.Unmarshal,
|
||||
JSONEncoder: json.Marshal,
|
||||
EnableIPValidation: true,
|
||||
}
|
||||
|
||||
if len(viper.GetString("webserver.proxy")) != 0 {
|
||||
switch strings.ToLower("webserver.proxy") {
|
||||
case "cloudflare":
|
||||
var trustedProxies []string
|
||||
v4Req, err := http.NewRequest("GET", "https://www.cloudflare.com/ips-v4/#", nil)
|
||||
if err != nil {
|
||||
log.Fatal("error creating request", err)
|
||||
}
|
||||
|
||||
v6Req, err := http.NewRequest("GET", "https://www.cloudflare.com/ips-v6/#", nil)
|
||||
if err != nil {
|
||||
log.Fatal("error creating request", err)
|
||||
}
|
||||
|
||||
client := &http.Client{}
|
||||
|
||||
v4Resp, err := client.Do(v4Req)
|
||||
if err != nil {
|
||||
log.Fatal("error doing request", err)
|
||||
}
|
||||
defer v4Resp.Body.Close()
|
||||
|
||||
v4Scanner := bufio.NewScanner(v4Resp.Body)
|
||||
v4Scanner.Split(bufio.ScanLines)
|
||||
|
||||
for v4Scanner.Scan() {
|
||||
trustedProxies = append(trustedProxies, v4Scanner.Text())
|
||||
}
|
||||
|
||||
v6Resp, err := client.Do(v6Req)
|
||||
if err != nil {
|
||||
log.Fatal("error doing request", err)
|
||||
}
|
||||
defer v6Resp.Body.Close()
|
||||
|
||||
v6Scanner := bufio.NewScanner(v6Resp.Body)
|
||||
v6Scanner.Split(bufio.ScanLines)
|
||||
|
||||
for v6Scanner.Scan() {
|
||||
trustedProxies = append(trustedProxies, v6Scanner.Text())
|
||||
}
|
||||
appConfig.TrustedProxies = trustedProxies
|
||||
appConfig.ProxyHeader = "Cf-Connecting-Ip"
|
||||
appConfig.EnableTrustedProxyCheck = true
|
||||
default:
|
||||
log.Warnf("Unknown proxy type: %s", viper.GetString("webserver.proxy"))
|
||||
}
|
||||
}
|
||||
|
||||
app := fiber.New(appConfig)
|
||||
|
||||
app.Use(healthcheck.New())
|
||||
app.Use(limiter.New(limiter.Config{
|
||||
Max: 175,
|
||||
Expiration: 25 * time.Second,
|
||||
LimiterMiddleware: limiter.SlidingWindow{},
|
||||
}))
|
||||
|
||||
app.Post("/webhook", func(c *fiber.Ctx) error {
|
||||
|
||||
event := c.Get("X-Forgejo-Event")
|
||||
signature := c.Get("X-Forgejo-Signature")
|
||||
bodyType := c.Get("Content-Type")
|
||||
|
||||
if len(event) == 0 || len(signature) == 0 || bodyType != "application/json" {
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
|
||||
mac := hmac.New(sha256.New, []byte(viper.GetString("forgejo.secret")))
|
||||
mac.Write(c.Body())
|
||||
bodyHash := hex.EncodeToString(mac.Sum(nil))
|
||||
if signature != bodyHash {
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
|
||||
switch event {
|
||||
case "push":
|
||||
pushEvBody := new(interfaces.ForgejoPushEvent)
|
||||
if err := c.BodyParser(pushEvBody); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
return handlePush(c, forgeClient, pushEvBody)
|
||||
case "issues":
|
||||
issueEvBody := new(interfaces.ForgejoIssueEvent)
|
||||
if err := c.BodyParser(issueEvBody); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
return handleIssues(c, forgeClient, issueEvBody, pgpEntity, user)
|
||||
default:
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if err := app.Listen("0.0.0.0:9000"); err != nil {
|
||||
log.Fatal("error running webserver", err)
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
func handlePush(c *fiber.Ctx, forgeClient *forgejo.Client, event *interfaces.ForgejoPushEvent) error {
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func handleIssues(c *fiber.Ctx, forgeClient *forgejo.Client, event *interfaces.ForgejoIssueEvent, entity OpenPGPEntity, user *forgejo.User) error {
|
||||
if event.Action == "opened" && event.Issue.Title == "setup:goscan" {
|
||||
if _, err := forgeClient.CreateRepoActionSecret(event.Issue.Repo.Owner, event.Issue.Repo.Name, forgejo.CreateSecretOption{
|
||||
Name: "goscan_token",
|
||||
Data: "hello!",
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
gitDir, err := os.MkdirTemp("", "goscan-*")
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
defer func(path string) {
|
||||
err := os.RemoveAll(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}(gitDir)
|
||||
|
||||
repo, err := git.PlainClone(gitDir, false, &git.CloneOptions{
|
||||
URL: event.Repo.CloneURL.String(),
|
||||
ReferenceName: plumbing.NewBranchReferenceName(event.Repo.DefaultBranch),
|
||||
Depth: 1,
|
||||
Auth: &gitHttp.BasicAuth{
|
||||
Username: "gosec",
|
||||
Password: viper.GetString("forgejo.bot_token"),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if err := repo.CreateBranch(&config.Branch{
|
||||
Name: plumbing.NewBranchReferenceName("goscan/setup").String(),
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
worktree, err := repo.Worktree()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(gitDir+"/.forgejo/workflows", 0775); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if err := worktree.Checkout(&git.CheckoutOptions{
|
||||
Branch: plumbing.NewBranchReferenceName("goscan/setup"),
|
||||
Create: true,
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
tmpl, err := template.New("action_tmpl").Parse(actionTemplate)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
var tmplBuffer bytes.Buffer
|
||||
err = tmpl.Execute(&tmplBuffer, ActionTemplate{
|
||||
DefaultBranch: event.Repo.DefaultBranch,
|
||||
ServerURL: viper.GetString("forgejo.url"),
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(gitDir+"/.forgejo/workflows/gosec.yml", []byte(tmplBuffer.String()), 0666); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if _, err := worktree.Add(".forgejo/workflows/gosec.yml"); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
signature := &object.Signature{
|
||||
Name: user.FullName,
|
||||
Email: user.Email,
|
||||
When: time.Now(),
|
||||
}
|
||||
|
||||
if _, err := worktree.Commit("Add GoScan action", &git.CommitOptions{
|
||||
SignKey: entity.Entity,
|
||||
Author: signature,
|
||||
Committer: signature,
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if err := repo.Push(&git.PushOptions{
|
||||
RemoteName: "origin",
|
||||
Auth: &gitHttp.BasicAuth{
|
||||
Username: "gosec",
|
||||
Password: viper.GetString("forgejo.bot_token"),
|
||||
},
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
pr, _, err := forgeClient.CreatePullRequest(event.Issue.Repo.Owner, event.Issue.Repo.Name, forgejo.CreatePullRequestOption{
|
||||
Base: event.Repo.DefaultBranch,
|
||||
Head: "goscan/setup",
|
||||
Assignees: []string{event.Issue.User.Username},
|
||||
Title: "Setup GoScan",
|
||||
Body: "Here is a default workflow configuration for gosec, feel free to edit it to your liking!",
|
||||
})
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if _, _, err := forgeClient.CreateIssueComment(event.Issue.Repo.Owner, event.Issue.Repo.Name, int64(event.Issue.Number), forgejo.CreateIssueCommentOption{
|
||||
Body: fmt.Sprintf("@%s\nCreated GoScan Secret and created a [Pull Request](%s)", event.Issue.User.Username, pr.HTMLURL),
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
stateClosed := forgejo.StateClosed
|
||||
if _, _, err := forgeClient.EditIssue(event.Issue.Repo.Owner, event.Issue.Repo.Name, int64(event.Issue.Number), forgejo.EditIssueOption{
|
||||
State: &stateClosed, //??
|
||||
}); err != nil {
|
||||
log.Error(err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
}
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(daemonCmd)
|
||||
}
|
77
cmd/root.go
77
cmd/root.go
|
@ -5,13 +5,14 @@ Copyright © 2024 Shane C. <shane@scaffoe.com>
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"codeberg.org/mvdkleijn/forgejo-sdk/forgejo"
|
||||
"fmt"
|
||||
"git.eggactyl.cloud/Eggactyl/shell/linux"
|
||||
"git.shadowhosting.xyz/shanec/forgejo-sdk/forgejo"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/nao1215/markdown"
|
||||
"github.com/owenrumney/go-sarif/sarif"
|
||||
"github.com/sethvargo/go-githubactions"
|
||||
"github.com/spf13/viper"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
|
@ -121,12 +122,7 @@ var rootCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
var linkToFile strings.Builder
|
||||
|
||||
if isGithub {
|
||||
linkToFile.WriteString("./blob/commit/")
|
||||
} else {
|
||||
linkToFile.WriteString("./src/commit/")
|
||||
}
|
||||
|
||||
linkToFile.WriteString(ref.Hash().String() + "/" + *location.PhysicalLocation.ArtifactLocation.URI + "#L" + strconv.Itoa(*location.PhysicalLocation.Region.StartLine))
|
||||
|
||||
|
@ -239,6 +235,73 @@ func Execute() {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.Flags().BoolVar(&isAction, "is-action", false, "If set, will run some things specific to git actions")
|
||||
rootCmd.Flags().BoolVar(&isGithub, "is-github", false, "If set, will change some outputs to support github")
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
viper.AddConfigPath("/opt/goscan")
|
||||
viper.SetConfigType("yaml")
|
||||
viper.SetConfigName("config")
|
||||
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
|
||||
for _, variable := range os.Environ() {
|
||||
|
||||
if strings.HasPrefix(variable, "GOSCAN__") {
|
||||
|
||||
sepEnv := strings.SplitN(variable, "=", 1)
|
||||
key := sepEnv[0]
|
||||
value := sepEnv[1]
|
||||
|
||||
key = strings.Replace(key, "GOSCAN__", "", 1)
|
||||
|
||||
if strings.HasPrefix(key, "database") {
|
||||
key = strings.Replace(key, "database", "", 1)
|
||||
switch strings.ToLower(key) {
|
||||
case "host":
|
||||
viper.Set("database.host", value)
|
||||
case "port":
|
||||
viper.Set("database.port", value)
|
||||
case "user":
|
||||
viper.Set("database.user", value)
|
||||
case "password":
|
||||
viper.Set("database.password", value)
|
||||
case "name":
|
||||
viper.Set("database.name", value)
|
||||
case "tz":
|
||||
viper.Set("database.tz", value)
|
||||
default:
|
||||
log.Fatalln("invalid config option")
|
||||
}
|
||||
} else if strings.HasPrefix(key, "forgejo") {
|
||||
key = strings.Replace(key, "forgejo", "", 1)
|
||||
switch strings.ToLower(key) {
|
||||
case "url":
|
||||
viper.Set("forgejo.url", value)
|
||||
case "bot_token":
|
||||
viper.Set("forgejo.bot_token", value)
|
||||
case "secret":
|
||||
viper.Set("forgejo.secret", value)
|
||||
default:
|
||||
log.Fatalln("invalid config option")
|
||||
}
|
||||
} else {
|
||||
log.Fatalln("invalid config option")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(viper.ConfigFileUsed()) != 0 {
|
||||
if err := viper.WriteConfig(); err != nil {
|
||||
log.Fatalln("error writing to file", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
17
cmd/root_dev.go
Normal file
17
cmd/root_dev.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
//go:build dev
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func init() {
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
viper.AddConfigPath(path)
|
||||
}
|
|
@ -7,12 +7,17 @@ RUN go mod download && go mod verify
|
|||
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -trimpath -o build/goscan
|
||||
|
||||
FROM alpine:3.20
|
||||
LABEL maintainer="shane@scaffoe.com" \
|
||||
org.opencontainers.image.authors="Shane C." \
|
||||
org.opencontainers.image.source="https://git.shadowhosting.xyz/shanec/goscan" \
|
||||
org.opencontainers.image.licenses="Unlicense" \
|
||||
org.opencontainers.image.title="GoScan (GoSec Scanner for Forgejo)"
|
||||
|
||||
RUN apk --no-cache update && apk --no-cache upgrade && apk add curl
|
||||
|
||||
COPY --from=builder /usr/local/go /usr/local/go
|
||||
COPY --from=builder /app/build/goscan /goscan
|
||||
COPY ./entrypoint.sh /entrypoint.sh
|
||||
COPY ./docker/action_entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /goscan && chmod +x /entrypoint.sh
|
||||
|
||||
ENV PATH="/usr/local/go/bin:${PATH}"
|
30
docker/Daemon.Dockerfile
Normal file
30
docker/Daemon.Dockerfile
Normal file
|
@ -0,0 +1,30 @@
|
|||
FROM golang:1.22-alpine3.20 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
|
||||
RUN go mod download && go mod verify
|
||||
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -trimpath -o build/goscan
|
||||
|
||||
FROM alpine:3.20
|
||||
LABEL maintainer="shane@scaffoe.com" \
|
||||
org.opencontainers.image.authors="Shane C." \
|
||||
org.opencontainers.image.source="https://git.shadowhosting.xyz/shanec/goscan" \
|
||||
org.opencontainers.image.licenses="Unlicense" \
|
||||
org.opencontainers.image.title="GoScan (GoSec Scanner for Forgejo)"
|
||||
|
||||
RUN apk --no-cache update && apk --no-cache upgrade && apk add curl dumb-init bash ca-certificates && rm -rf /var/cache/apk/*
|
||||
|
||||
COPY --from=builder /app/build/goscan /goscan
|
||||
COPY ./docker/daemon_entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
RUN addgroup -S -g 1000 goscan && adduser -S -H -D -h /var/lib/goscan -s /bin/bash -u 1000 -G goscan goscan
|
||||
RUN mkdir -p /var/lib/goscan && chown -R goscan:goscan /var/lib/goscan
|
||||
|
||||
USER 1000:1000
|
||||
ENV HOME="/var/lib/goscan"
|
||||
VOLUME ["/var/lib/goscan"]
|
||||
WORKDIR /var/lib/goscan
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||
CMD []
|
36
docker/compose.yml
Normal file
36
docker/compose.yml
Normal file
|
@ -0,0 +1,36 @@
|
|||
networks:
|
||||
goscan:
|
||||
external: false
|
||||
|
||||
volumes:
|
||||
goscan:
|
||||
driver: local
|
||||
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile
|
||||
env_file:
|
||||
- .env
|
||||
restart: always
|
||||
ports:
|
||||
- "${PORT:-9000}:9000"
|
||||
networks:
|
||||
- goscan
|
||||
volumes:
|
||||
- goscan:/var/lib/goscan
|
||||
- ./config.yml:/var/lib/goscan/config.yml
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:16-alpine3.20
|
||||
env_file:
|
||||
- .env
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-goscan}"
|
||||
POSTGRES_DB: "${POSTGRES_DB:-goscan}"
|
||||
networks:
|
||||
- goscan
|
3
docker/daemon_entrypoint.sh
Normal file
3
docker/daemon_entrypoint.sh
Normal file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
/goscan daemon
|
8
example.config.yml
Normal file
8
example.config.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
webserver:
|
||||
host: 0.0.0.0
|
||||
port: 9000
|
||||
proxy: 'cloudflare'
|
||||
forgejo:
|
||||
url: https://git.shadowhosting.xyz
|
||||
bot_token: ""
|
||||
secret: ""
|
36
go.mod
36
go.mod
|
@ -5,18 +5,23 @@ go 1.22.5
|
|||
require (
|
||||
codeberg.org/mvdkleijn/forgejo-sdk/forgejo v1.1.1
|
||||
git.eggactyl.cloud/Eggactyl/shell v0.0.0-20240824225129-2ced31effd66
|
||||
git.shadowhosting.xyz/shanec/forgejo-sdk/forgejo v1.1.3
|
||||
github.com/ProtonMail/go-crypto v1.0.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/goccy/go-json v0.10.3
|
||||
github.com/gofiber/fiber/v2 v2.52.5
|
||||
github.com/kr/pretty v0.3.1
|
||||
github.com/nao1215/markdown v0.6.0
|
||||
github.com/owenrumney/go-sarif v1.1.1
|
||||
github.com/sethvargo/go-githubactions v1.3.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
|
@ -26,20 +31,25 @@ require (
|
|||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/google/uuid v1.5.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/karrick/godirwalk v1.17.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/owenrumney/go-sarif/v2 v2.3.3 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/philhofer/fwd v1.1.2 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
|
@ -49,19 +59,23 @@ require (
|
|||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.19.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tinylib/msgp v1.1.8 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/zclconf/go-cty v1.10.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
|
105
go.sum
105
go.sum
|
@ -4,12 +4,22 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
|||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
git.eggactyl.cloud/Eggactyl/shell v0.0.0-20240824225129-2ced31effd66 h1:nKQ5M7/Ugn536WbH07f6NZGKy+4z04i7KoAwUU8Ibaw=
|
||||
git.eggactyl.cloud/Eggactyl/shell v0.0.0-20240824225129-2ced31effd66/go.mod h1:/QCc50YmA6jiIzIafuDiRJXhZyNu0wKLlgeUMPv5S68=
|
||||
git.shadowhosting.xyz/shanec/forgejo-sdk/forgejo v1.1.2 h1:JJbb+xcQ/NdKeH1J50LgHv3pctPHff2GJSUkYamunY4=
|
||||
git.shadowhosting.xyz/shanec/forgejo-sdk/forgejo v1.1.2/go.mod h1:se/RxoDkDZN5IPP0wCUscO+Z5ArOpDJsX6UilAqKEWw=
|
||||
git.shadowhosting.xyz/shanec/forgejo-sdk/forgejo v1.1.3 h1:sPB0qPctiPqkYJQUTLjnE+k49SsDqncCmNEydnwIbxQ=
|
||||
git.shadowhosting.xyz/shanec/forgejo-sdk/forgejo v1.1.3/go.mod h1:se/RxoDkDZN5IPP0wCUscO+Z5ArOpDJsX6UilAqKEWw=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
|
@ -20,27 +30,45 @@ github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53E
|
|||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
|
||||
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
|
@ -51,6 +79,8 @@ github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwS
|
|||
github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
|
@ -60,26 +90,38 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/nao1215/markdown v0.6.0 h1:kqhrC47K434YA1jMTUwJwSV/hla8ifN3NzehMEffI/E=
|
||||
github.com/nao1215/markdown v0.6.0/go.mod h1:ObBhnNduWwPN+bu4dtv4JoLRt57ONla7l//03iHIVhY=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/owenrumney/go-sarif v1.1.1 h1:QNObu6YX1igyFKhdzd7vgzmw7XsWN3/6NMGuDzBgXmE=
|
||||
github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=
|
||||
github.com/owenrumney/go-sarif/v2 v2.3.3 h1:ubWDJcF5i3L/EIOER+ZyQ03IfplbSU1BLOE26uKQIIU=
|
||||
github.com/owenrumney/go-sarif/v2 v2.3.3/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
|
||||
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
|
@ -118,9 +160,18 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
|
||||
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
|
@ -139,16 +190,15 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
@ -157,13 +207,16 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -174,21 +227,21 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -196,21 +249,25 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
|
|
190
interfaces/forgejo.go
Normal file
190
interfaces/forgejo.go
Normal file
|
@ -0,0 +1,190 @@
|
|||
package interfaces
|
||||
|
||||
import (
|
||||
"github.com/goccy/go-json"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type URL struct {
|
||||
url.URL
|
||||
}
|
||||
|
||||
func (u *URL) UnmarshalJSON(bytes []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(bytes, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.URL = *parsedURL
|
||||
return nil
|
||||
}
|
||||
|
||||
type ForgejoIssueEvent struct {
|
||||
Action string `json:"action"`
|
||||
Number int `json:"number"`
|
||||
Repo ForgejoRepo `json:"repository"`
|
||||
Sender ForgejoUser `json:"sender"`
|
||||
Issue ForgejoIssue `json:"issue"`
|
||||
}
|
||||
|
||||
type ForgejoPushEvent struct {
|
||||
Ref string `json:"ref"`
|
||||
Before string `json:"before"`
|
||||
After string `json:"after"`
|
||||
CompareURL URL `json:"compare_url"`
|
||||
Commits []ForgejoCommit `json:"commits"`
|
||||
TotalCommits int `json:"total_commits"`
|
||||
HeadCommit ForgejoCommit `json:"head_commit"`
|
||||
Repo ForgejoRepo `json:"repository"`
|
||||
Pusher ForgejoUser `json:"pusher"`
|
||||
Sender ForgejoUser `json:"sender"`
|
||||
}
|
||||
|
||||
type ForgejoCommit struct {
|
||||
ID string `json:"id"`
|
||||
Message string `json:"message"`
|
||||
URL URL `json:"url"`
|
||||
Author ForgejoPartialUser `json:"author"`
|
||||
Committer ForgejoPartialUser `json:"committer"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Added []string `json:"added"`
|
||||
Removed []string `json:"removed"`
|
||||
Modified []string `json:"modified"`
|
||||
}
|
||||
|
||||
type ForgejoPartialUser struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type ForgejoUser struct {
|
||||
ID int `json:"id"`
|
||||
Login string `json:"login"`
|
||||
LoginName string `json:"login_name"`
|
||||
SourceID int `json:"source_id"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
AvatarURL URL `json:"avatar_url"`
|
||||
HtmlURL URL `json:"html_url"`
|
||||
Language string `json:"language"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
LastLogin time.Time `json:"last_login"`
|
||||
Created time.Time `json:"created"`
|
||||
IsRestricted bool `json:"restricted"`
|
||||
IsActive bool `json:"active"`
|
||||
IsProhbitLogin bool `json:"prohbit_login"`
|
||||
Location string `json:"location"`
|
||||
Pronouns string `json:"pronouns"`
|
||||
Website string `json:"website"`
|
||||
Description string `json:"description"`
|
||||
Visibility string `json:"visibility"`
|
||||
FollowerCount int `json:"followers_count"`
|
||||
FollowingCount int `json:"following_count"`
|
||||
StarCount int `json:"starred_repos_count"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type ForgejoPartialRepo struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Owner string `json:"owner"`
|
||||
FullName string `json:"full_name"`
|
||||
}
|
||||
|
||||
type ForgejoRepo struct {
|
||||
ID int `json:"id"`
|
||||
Owner ForgejoUser `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
Description string `json:"description"`
|
||||
IsEmpty bool `json:"empty"`
|
||||
IsPrivate bool `json:"private"`
|
||||
IsFork bool `json:"fork"`
|
||||
IsTemplate bool `json:"template"`
|
||||
IsMirror bool `json:"mirror"`
|
||||
Parent *ForgejoRepo `json:"parent"`
|
||||
Size int `json:"size"`
|
||||
Language string `json:"language"`
|
||||
LanguagesURL URL `json:"languages_url"`
|
||||
HtmlURL URL `json:"html_url"`
|
||||
URL URL `json:"url"`
|
||||
Link URL `json:"link"`
|
||||
SshURL string `json:"ssh_url"`
|
||||
CloneURL URL `json:"clone_url"`
|
||||
OriginalURL URL `json:"original_url"`
|
||||
Website URL `json:"website"`
|
||||
StarCount int `json:"stars_count"`
|
||||
ForkCount int `json:"forks_count"`
|
||||
WatcherCount int `json:"watchers_count"`
|
||||
OpenIssueCount int `json:"open_issues_count"`
|
||||
OpenPrCount int `json:"open_pr_counter"`
|
||||
ReleaseCount int `json:"release_counter"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
IsArchived bool `json:"archived"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ArchivedAt time.Time `json:"archived_at"`
|
||||
Permissions map[string]bool `json:"permissions"`
|
||||
HasIssues bool `json:"has_issues"`
|
||||
InternalTracker ForgejoRepoInternalTracker `json:"internal_tracker"`
|
||||
HasWiki bool `json:"has_wiki"`
|
||||
WikiBranch string `json:"wiki_branch"`
|
||||
GloballyEditableWiki bool `json:"globally_editable_wiki"`
|
||||
HasPullRequests bool `json:"has_pull_requests"`
|
||||
HasProjects bool `json:"has_projects"`
|
||||
HasReleases bool `json:"has_releases"`
|
||||
HasPackages bool `json:"has_packages"`
|
||||
HasActions bool `json:"has_actions"`
|
||||
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
|
||||
AllowMergeCommits bool `json:"allow_merge_commits"`
|
||||
AllowRebase bool `json:"allow_rebase"`
|
||||
AllowExplicitRebase bool `json:"allow_rebase_explicit"`
|
||||
AllowSquashMerge bool `json:"allow_squash_merge"`
|
||||
AllowFastFowardOnlyMerge bool `json:"allow_fast_foward_only_merge"`
|
||||
AllowRebaseUpdate bool `json:"allow_rebase_update"`
|
||||
DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"`
|
||||
DefaultMergeStyle string `json:"default_merge_style"`
|
||||
DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"`
|
||||
AvatarURL URL `json:"avatar_url"`
|
||||
Internal bool `json:"internal"`
|
||||
MirrorInterval string `json:"mirror_interval"`
|
||||
ObjectFormatName string `json:"object_format_name"`
|
||||
MirrorUpdated time.Time `json:"mirror_updated"`
|
||||
}
|
||||
|
||||
type ForgejoRepoInternalTracker struct {
|
||||
TimeTracker bool `json:"time_tracker"`
|
||||
AllowContribTrackTime bool `json:"allow_only_contributors_to_track_time"`
|
||||
EnableIssueDependency bool `json:"enable_issue_dependencies"`
|
||||
}
|
||||
|
||||
type ForgejoIssue struct {
|
||||
ID int `json:"id"`
|
||||
URL URL `json:"url"`
|
||||
HtmlURL URL `json:"html_url"`
|
||||
Number int `json:"number"`
|
||||
User ForgejoUser `json:"user"`
|
||||
OriginalAuthor string `json:"original_author"`
|
||||
OriginalAuthorID int `json:"original_author_id"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Ref string `json:"ref"`
|
||||
Assets []string `json:"assets"`
|
||||
Labels []string `json:"labels"`
|
||||
State string `json:"state"`
|
||||
IsLocked bool `json:"is_locked"`
|
||||
Comments int `json:"comments"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ClosedAt time.Time `json:"closed_at"`
|
||||
DueDate time.Time `json:"due_date"`
|
||||
Repo ForgejoPartialRepo `json:"repository"`
|
||||
PinOrder int `json:"pin_order"`
|
||||
}
|
Loading…
Reference in a new issue