Compare commits

...

2 commits
v1 ... main

Author SHA1 Message Date
97879670c1
fix gosec issues
All checks were successful
GoSec Scan / Gosec Check (push) Successful in 10s
2024-09-13 17:10:47 -04:00
03e9e6bc40
add basic bot
All checks were successful
GoSec Scan / Gosec Check (push) Successful in 7s
2024-09-13 16:56:18 -04:00
17 changed files with 945 additions and 206 deletions

3
.example.env Normal file
View file

@ -0,0 +1,3 @@
GOSCAN__forgejo__URL=
GOSCAN__forgejo__BOT_TOKEN=
GOSCAN__forgejo__SECRET=

155
.gitignore vendored
View file

@ -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

View file

@ -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
View 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

View file

@ -1,3 +0,0 @@
#!/bin/sh
docker buildx build --platform=linux/amd64,linux/arm64/v8 --push -t git.shadowhosting.xyz/actions/goscan .

450
cmd/daemon.go Normal file
View file

@ -0,0 +1,450 @@
/*
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
`
// 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 *openpgp.Entity
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 func(publicKeyEncoder io.WriteCloser) {
err := publicKeyEncoder.Close()
if err != nil {
panic(err)
}
}(publicKeyEncoder)
err = entity.Serialize(publicKeyEncoder)
if err != nil {
log.Fatal(err)
}
err = publicKeyEncoder.Close()
if err != nil {
log.Fatal(err)
}
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)
err = file.Close()
if err != nil {
log.Fatal(err)
}
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 func(signatureEncoder io.WriteCloser) {
err := signatureEncoder.Close()
if err != nil {
panic(err)
}
}(signatureEncoder)
if _, err := signatureEncoder.Write(signatureBuffer.Bytes()); err != nil {
log.Fatal(err)
}
err = signatureEncoder.Close()
if err != nil {
log.Fatal(err)
}
if _, _, err := forgeClient.CreateGPGKey(forgejo.CreateGPGKeyOption{
ArmoredKey: publicKeyArmor,
ArmoredSignature: encodedSignatureBuffer.String(),
}); err != nil {
log.Fatal(err)
}
pgpEntity = 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 = 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 *openpgp.Entity, 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); /* #nosec G301 */ 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); /* #nosec G306 */ 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,
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)
}

View file

@ -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("./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
View 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)
}

View file

@ -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
View 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
View 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

View file

@ -0,0 +1,3 @@
#!/bin/sh
/goscan daemon

8
example.config.yml Normal file
View 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
View file

@ -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
View file

@ -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
View 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"`
}