diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..4172c02 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" # Location of package manifests + schedule: + interval: "daily" + groups: + "fortio": + patterns: + - "fortio.org/*" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + interval: "weekly" diff --git a/.github/workflows/gochecks.yml b/.github/workflows/gochecks.yml new file mode 100644 index 0000000..bee59a1 --- /dev/null +++ b/.github/workflows/gochecks.yml @@ -0,0 +1,40 @@ +name: go-checks + +on: + workflow_call: + push: + branches: [ main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] + +jobs: + check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # pin@v4 + - name: Setup Go environment + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # pin@v5 + with: + go-version: '1.22' + check-latest: true + - name: Run Vulncheck + run: | + go install golang.org/x/vuln/cmd/govulncheck@latest + govulncheck ./... + - name: Download linter config + run: curl -fsS -o .golangci.yml https://raw.githubusercontent.com/fortio/workflows/main/golangci.yml + - name: Run golangci-lint + uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # pin@v6 + - name: Run tests + run: | + go version + go run . buildinfo || true # to also confirm go toolchain version used + if make -n test &>/dev/null; then + echo "Running tests with make test" + make test + else + echo "No Makefile test target, running tests with race detection as default behavior" + go test -race ./... + fi diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml new file mode 100644 index 0000000..a066397 --- /dev/null +++ b/.github/workflows/releaser.yml @@ -0,0 +1,43 @@ +name: Release + +on: + push: + tags: + # so a vX.Y.Z-test1 doesn't trigger build + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+-pre*' + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + permissions: write-all + steps: + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # pin@v3 + with: + fetch-depth: 0 + - uses: docker/setup-qemu-action@5927c834f5b4fdf503fca6f4c7eccda82949e1ee # pin@v1 + - uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4 # pin@v1 + - name: Set up Go + uses: actions/setup-go@v5 # pin@v3 + with: + go-version: '1.22' + check-latest: true + - name: Log in to Docker + uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # pin@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GH_PAT }} + - name: "GoReleaser Action" + uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # pin@v6.0.0 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GH_PAT }} + TAP_DESCRIPTION: "Go Repl Open Language: simple, small but powerful interpreted language in Go" diff --git a/.gitignore b/.gitignore index 905664e..00478c8 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ go.work.sum grol-discord-bot .DS_Store +.golangci.yml diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 8342a4a..0000000 --- a/.golangci.yml +++ /dev/null @@ -1,161 +0,0 @@ -# Config for golangci-lint - shared across fortio org projects (included by gochecks workflow step) - -# output configuration options - -# all available settings of specific linters -linters-settings: - dupl: - # tokens count to trigger issue, 150 by default - threshold: 100 - exhaustive: - # indicates that switch statements are to be considered exhaustive if a - # 'default' case is present, even if all enum members aren't listed in the - # switch - default-signifies-exhaustive: false - funlen: - lines: 140 - statements: 70 - gocognit: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 42 - nestif: - # minimal complexity of if statements to report, 5 by default - min-complexity: 4 - gocyclo: - # minimal code complexity to report, 30 by default (but we recommend 10-20) - min-complexity: 30 - godot: - # check all top-level comments, not only declarations - check-all: false - govet: - # settings per analyzer - settings: - printf: # analyzer name, run `go tool vet help` to see all analyzers - funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Printf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).FErrf - enable-all: true - disable-all: false - lll: - # max line length, lines longer will be reported. Default is 120. - # '\t' is counted as 1 character by default, and can be changed with the tab-width option - line-length: 132 - # tab width in spaces. Default to 1. - tab-width: 1 - misspell: - # Correct spellings using locale preferences for US or UK. - # Default is to use a neutral variety of English. - # Setting locale to US will correct the British spelling of 'colour' to 'color'. - locale: US - ignore-words: - - fortio - nakedret: - # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 - max-func-lines: 30 - nolintlint: - require-specific: true - # require-explanation: true # add this when we fix it/review nolints in fortio/fortio - whitespace: - multi-if: false # Enforces newlines (or comments) after every multi-line if statement - multi-func: false # Enforces newlines (or comments) after every multi-line function signature - gofumpt: - # Choose whether or not to use the extra rules that are disabled - # by default - extra-rules: false - - -linters: - disable: - # bad ones: - - musttag - # Deprecated ones: - - gomnd - - execinquery - # Redundant ones: - - gofmt # we use gofumpt - # Weird/bad ones: - - wsl - - nlreturn - - gochecknoinits - - gochecknoglobals - - mnd - - testpackage - - wrapcheck - - tagliatelle - - nonamedreturns - - varnamelen - - exhaustruct # seems like a good idea at first but actually a pain and go does have zero values for a reason. -# TODO consider putting these back, when they stop being bugged (ifshort, wastedassign,...) - - paralleltest - - thelper - - forbidigo - - wastedassign - - cyclop - - forcetypeassert - - ireturn - - depguard - enable-all: true - disable-all: false - # Must not use fast: true in newer golangci-lint or it'll just skip a bunch of linter instead of doing caching like before (!) - fast: false - - -issues: - # Excluding configuration per-path, per-linter, per-text and per-source - exclude-rules: - # Exclude some linters from running on tests files. - - path: _test\.go - linters: - - gocyclo - - errcheck - - dupl - - gosec - - gochecknoinits - - gochecknoglobals - - forcetypeassert - - nosnakecase - - noctx - - goconst - - err113 - - # Exclude lll issues for long lines with go:generate - - linters: - - lll - source: "^//go:generate " - - linters: - - err113 - text: "do not define dynamic errors" - - linters: - - govet - text: "fieldalignment:" - - linters: - - godox - text: "TODO" - - linters: - - nosnakecase - text: "grpc_|_SERVING|O_" - - # Maximum issues count per one linter. Set to 0 to disable. Default is 50. - max-issues-per-linter: 0 - - # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. - max-same-issues: 0 - -severity: - # Default value is empty string. - # Set the default severity for issues. If severity rules are defined and the issues - # do not match or no severity is provided to the rule this will be the default - # severity applied. Severities should match the supported severity names of the - # selected out format. - # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity - # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity - # - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message - default-severity: error - - # The default value is false. - # If set to true severity-rules regular expressions become case sensitive. - case-sensitive: false diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d07fd0d --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +all: test lint + +test: + go test -race ./... + +lint: .golangci.yml + CGO_ENABLED=0 golangci-lint run + +.golangci.yml: Makefile + curl -fsS -o .golangci.yml https://raw.githubusercontent.com/fortio/workflows/main/golangci.yml + +.PHONY: all lint test diff --git a/bot.go b/bot.go index 1254fd5..9551458 100644 --- a/bot.go +++ b/bot.go @@ -14,8 +14,11 @@ import ( var BotToken string +// State for edit to replies. var msgSet *fixedmap.FixedMap[string, string] +const Unknown = "unknown" + func Run(maxHistoryLength int) { msgSet = fixedmap.NewFixedMap[string, string](maxHistoryLength) // create a session @@ -167,7 +170,7 @@ func handleMessage(session *discordgo.Session, message *discordgo.MessageCreate, var channelName string if err != nil { log.S(log.Error, "unable to get channel info", log.Any("err", err)) - channelName = "unknown" + channelName = Unknown } else { channelName = channel.Name } @@ -175,7 +178,7 @@ func handleMessage(session *discordgo.Session, message *discordgo.MessageCreate, var serverName string if err != nil { log.S(log.Error, "unable to get server info", log.Any("err", err)) - serverName = "unknown" + serverName = Unknown } else { serverName = server.Name } @@ -272,14 +275,14 @@ func interactionCreate(session *discordgo.Session, interaction *discordgo.Intera channel, err := session.State.Channel(interaction.ChannelID) if err != nil { log.S(log.Error, "unable to get channel info", log.Any("err", err)) - channelName = "unknown" + channelName = Unknown } else { channelName = channel.Name } svr, err := session.State.Guild(interaction.GuildID) if err != nil { log.S(log.Error, "unable to get server info", log.Any("err", err)) - serverName = "unknown" + serverName = Unknown } else { serverName = svr.Name }