diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..481fcfd --- /dev/null +++ b/.drone.yml @@ -0,0 +1,141 @@ +--- +kind: pipeline +name: compliance + +platform: + os: linux + arch: arm64 + +trigger: + event: + - pull_request + +steps: +- name: build + pull: always + image: golang:1.20 + environment: + GOPROXY: https://goproxy.io,direct + commands: + - go test -race ./... + - go build + +- name: check + pull: always + image: golang:1.20 + environment: + GOPROXY: https://goproxy.io,direct + commands: + - make lint + +- name: discord + pull: always + image: appleboy/drone-discord:1 + environment: + DISCORD_WEBHOOK_ID: + from_secret: discord_webhook_id + DISCORD_WEBHOOK_TOKEN: + from_secret: discord_webhook_token + when: + event: + - push + - tag + status: + - changed + - failure + +--- +kind: pipeline +name: release + +platform: + os: linux + arch: amd64 + +trigger: + branch: + - main + event: + - push + - tag + +steps: + - name: fetch-tags + pull: always + image: docker:git + commands: + - git fetch --tags --force + + - name: release + pull: always + image: techknowlogick/xgo:latest + environment: + GOPROXY: https://goproxy.io,direct + commands: + - export PATH=$PATH:$GOPATH/bin + - make release + + - name: bucket-main + pull: always + image: woodpeckerci/plugin-s3:latest + settings: + acl: + from_secret: aws_s3_acl + region: + from_secret: aws_s3_region + bucket: + from_secret: aws_s3_bucket + endpoint: + from_secret: aws_s3_endpoint + path_style: + from_secret: aws_s3_path_style + source: "dist/release/*" + strip_prefix: dist/release/ + target: /changelog-tool/main + environment: + AWS_ACCESS_KEY_ID: + from_secret: aws_access_key_id + AWS_SECRET_ACCESS_KEY: + from_secret: aws_secret_access_key + when: + event: + - push + + - name: bucket-tag + pull: always + image: woodpeckerci/plugin-s3:latest + settings: + acl: + from_secret: aws_s3_acl + region: + from_secret: aws_s3_region + bucket: + from_secret: aws_s3_bucket + endpoint: + from_secret: aws_s3_endpoint + path_style: + from_secret: aws_s3_path_style + source: "dist/release/*" + strip_prefix: dist/release/ + target: "/changelog-tool/${DRONE_TAG##v}" + environment: + AWS_ACCESS_KEY_ID: + from_secret: aws_access_key_id + AWS_SECRET_ACCESS_KEY: + from_secret: aws_secret_access_key + when: + event: + - tag + + - name: gitea + pull: always + image: plugins/gitea-release:1 + settings: + api_key: + from_secret: gitea_token + base_url: https://gitea.com + files: + - "dist/release/*" + when: + event: + - tag \ No newline at end of file diff --git a/.gitea/workflows/release-nightly.yml b/.gitea/workflows/release-nightly.yml deleted file mode 100644 index f521dcc..0000000 --- a/.gitea/workflows/release-nightly.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: goreleaser - -on: - push: - branches: [ main ] - -jobs: - goreleaser: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - run: git fetch --force --tags - - uses: actions/setup-go@v5 - with: - go-version-file: 'go.mod' - - name: goreleaser - uses: goreleaser/goreleaser-action@v4 - with: - distribution: goreleaser-pro - version: latest - args: release --nightly - env: - GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} - AWS_REGION: ${{ secrets.AWS_REGION }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - S3_REGION: ${{ secrets.AWS_REGION }} - S3_BUCKET: ${{ secrets.AWS_BUCKET }} - GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitea/workflows/release-tag.yml b/.gitea/workflows/release-tag.yml deleted file mode 100644 index f20d132..0000000 --- a/.gitea/workflows/release-tag.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: goreleaser - -on: - push: - tags: - - '*' - -jobs: - goreleaser: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - run: git fetch --force --tags - - uses: actions/setup-go@v5 - with: - go-version-file: 'go.mod' - - name: Import GPG key - id: import_gpg - uses: https://github.com/crazy-max/ghaction-import-gpg@v5 - with: - gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.PASSPHRASE }} - fingerprint: CC64B1DB67ABBEECAB24B6455FC346329753F4B0 - - name: goreleaser - uses: https://github.com/goreleaser/goreleaser-action@v4 - with: - distribution: goreleaser-pro - version: latest - args: release - env: - GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} - AWS_REGION: ${{ secrets.AWS_REGION }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - S3_REGION: ${{ secrets.AWS_REGION }} - S3_BUCKET: ${{ secrets.AWS_BUCKET }} - GORELEASER_FORCE_TOKEN: 'gitea' - GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} diff --git a/.gitea/workflows/test-pr.yml b/.gitea/workflows/test-pr.yml deleted file mode 100644 index 00e7e1b..0000000 --- a/.gitea/workflows/test-pr.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: check-and-test - -on: [pull_request] - -jobs: - check-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version-file: 'go.mod' - - name: check-and-test - run: | - go test -race ./... - go build - make lint - env: - GOPROXY: https://goproxy.io,direct diff --git a/.gitignore b/.gitignore index 6bea5b4..dfbe66a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,3 @@ # Go /vendor/ - -dist/ diff --git a/.goreleaser.checksum.sh b/.goreleaser.checksum.sh deleted file mode 100755 index a11b71d..0000000 --- a/.goreleaser.checksum.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -e - -if [ -z "$1" ]; then - echo "usage: $0 " - exit 1 -fi - -SUM=$(shasum -a 256 "$1" | cut -d' ' -f1) -BASENAME=$(basename "$1") -echo -n "${SUM} ${BASENAME}" > "$1".sha256 \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml deleted file mode 100644 index 908be06..0000000 --- a/.goreleaser.yaml +++ /dev/null @@ -1,109 +0,0 @@ -before: - hooks: - - go mod tidy - -builds: -- env: - - CGO_ENABLED=0 - goos: - - darwin - - linux - - windows - - freebsd - goarch: - - amd64 - - arm - - arm64 - goarm: - - "5" - - "6" - - "7" - ignore: - - goos: darwin - goarch: arm - - goos: darwin - goarch: ppc64le - - goos: darwin - goarch: s390x - - goos: windows - goarch: ppc64le - - goos: windows - goarch: s390x - - goos: windows - goarch: arm - goarm: "5" - - goos: windows - goarch: arm - goarm: "6" - - goos: windows - goarch: arm - goarm: "7" - - goos: freebsd - goarch: ppc64le - - goos: freebsd - goarch: s390x - - goos: freebsd - goarch: arm - goarm: "5" - - goos: freebsd - goarch: arm - goarm: "6" - - goos: freebsd - goarch: arm - goarm: "7" - flags: - - -trimpath - ldflags: - - -s -w -X code.gitea.io/changelog/cmd.Version={{ .Summary }} - binary: >- - {{ .ProjectName }}- - {{- .Version }}- - {{- .Os }}- - {{- if eq .Arch "amd64" }}amd64 - {{- else if eq .Arch "amd64_v1" }}amd64 - {{- else if eq .Arch "386" }}386 - {{- else }}{{ .Arch }}{{ end }} - {{- if .Arm }}-{{ .Arm }}{{ end }} - no_unique_dist_dir: true - hooks: - post: - - cmd: tar -cJf {{ .Path }}.xz {{ .Path }} - env: - - XZ_OPT=-9 - - cmd: sh .goreleaser.checksum.sh {{ .Path }} - - cmd: sh .goreleaser.checksum.sh {{ .Path }}.xz - -blobs: - - - provider: s3 - bucket: "{{ .Env.S3_BUCKET }}" - region: "{{ .Env.S3_REGION }}" - folder: "changelog-tool/{{.Version}}" - extra_files: - - glob: ./**.xz - - glob: ./**.sha256 - -archives: - - format: binary - name_template: "{{ .Binary }}" - allow_different_binary_count: true - -checksum: - name_template: 'checksums.txt' - extra_files: - - glob: ./**.xz - -snapshot: - name_template: "{{ .Branch }}-devel" - -nightly: - name_template: "{{ .Branch }}" - -force_token: gitea - -gitea_urls: - api: https://gitea.com/api/v1 - download: https://gitea.com - -# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json -# vim: set ts=2 sw=2 tw=0 fo=cnqoj diff --git a/README.md b/README.md index e0f2cb7..1e9ad83 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ A changelog generator for Gitea +[![Build Status](https://drone.gitea.com/api/badges/gitea/changelog/status.svg)](https://drone.gitea.com/gitea/changelog) + ## Purpose This repo is currently part of Gitea. The purpose of it is to generate a changelog when writing release notes. @@ -10,7 +12,7 @@ This tool generates a changelog from PRs based on their milestone and labels. ## Installation -Download a pre-built binary from our [downloads page](https://dl.gitea.com/changelog-tool/) or clone the source and follow the [building instructions](#building). +Download a pre-built binary from our [downloads page](https://dl.gitea.io/changelog-tool/) or clone the source and follow the [building instructions](#building). ## Configuration @@ -43,7 +45,7 @@ Fork -> Patch -> Push -> Pull Request ## Authors * [Maintainers](https://gitea.com/org/gitea/members) -* [Contributors](https://gitea.com/gitea/changelog/commits/branch/main) +* [Contributors](https://gitea.com/gitea/changelog/commits/branch/master) ## License diff --git a/cmd/cmd.go b/cmd/cmd.go index 3ddaf64..77e869b 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -8,7 +8,7 @@ import ( "os" "path/filepath" - "github.com/urfave/cli/v3" + "github.com/urfave/cli/v2" ) var ( @@ -24,8 +24,6 @@ var ( ) // New returns a new changelog App -// -//nolint:funlen func New() *cli.App { app := &cli.App{ Name: "changelog", @@ -37,14 +35,12 @@ func New() *cli.App { Aliases: []string{"m"}, Usage: "Targeted milestone", Destination: &milestoneFlag, - Persistent: true, }, &cli.StringFlag{ Name: "tag", Aliases: []string{"T"}, Usage: "Git tag for milestone url, if not set milestone is used", Destination: &tagFlag, - Persistent: true, }, &cli.StringFlag{ Name: "config", @@ -52,35 +48,30 @@ func New() *cli.App { Usage: "Specify a config file", Value: getDefaultConfigFile(), Destination: &configPathFlag, - Persistent: true, }, &cli.StringFlag{ Name: "token", Aliases: []string{"t"}, Usage: "Access token for private repositories/instances", Destination: &tokenFlag, - Persistent: true, }, &cli.BoolFlag{ Name: "details", Aliases: []string{"d"}, Usage: "Generate detail lists instead of long lists", Destination: &detailsFlag, - Persistent: true, }, &cli.Int64Flag{ Name: "after", Aliases: []string{"a"}, Usage: "Only select PRs after a given index (continuing a previous changelog)", Destination: &afterFlag, - Persistent: true, }, &cli.BoolFlag{ Name: "issues", Aliases: []string{"i"}, Usage: "Generate changelog from issues (otherwise from pulls)", Destination: &issuesFlag, - Persistent: true, }, }, Commands: []*cli.Command{ @@ -89,6 +80,7 @@ func New() *cli.App { Init, }, } + copyGlobalFlags(app) return app } @@ -104,3 +96,28 @@ func getDefaultConfigFile() string { } return "" } + +func copyGlobalFlags(app *cli.App) { + for _, command := range app.Commands { + originalFlagNames := make([]string, 0, len(command.Flags)) + for _, flag := range command.Flags { + originalFlagNames = append(originalFlagNames, flag.Names()...) + } + + for _, flag := range app.Flags { + found := false + flagNameLoop: + for _, name := range flag.Names() { + for _, originalName := range originalFlagNames { + if name == originalName { + found = true + break flagNameLoop + } + } + } + if !found { + command.Flags = append(command.Flags, flag) + } + } + } +} diff --git a/cmd/contributors.go b/cmd/contributors.go index 2a06001..fbed4d9 100644 --- a/cmd/contributors.go +++ b/cmd/contributors.go @@ -11,7 +11,7 @@ import ( "code.gitea.io/changelog/config" "code.gitea.io/changelog/service" - "github.com/urfave/cli/v3" + "github.com/urfave/cli/v2" ) var Contributors = &cli.Command{ diff --git a/cmd/generate.go b/cmd/generate.go index bb4ebbe..9da8178 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -12,7 +12,7 @@ import ( "code.gitea.io/changelog/config" "code.gitea.io/changelog/service" - "github.com/urfave/cli/v3" + "github.com/urfave/cli/v2" ) var Generate = &cli.Command{ @@ -21,7 +21,7 @@ var Generate = &cli.Command{ Action: runGenerate, } -func runGenerate(ctx *cli.Context) error { +func runGenerate(_ *cli.Context) error { cfg, err := config.New(configPathFlag) if err != nil { return err @@ -32,7 +32,7 @@ func runGenerate(ctx *cli.Context) error { return err } - title, prs, err := s.Generate(ctx.Context) + title, prs, err := s.Generate() if err != nil { return err } diff --git a/cmd/init.go b/cmd/init.go index 5ecca0b..629a155 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -6,11 +6,12 @@ package cmd import ( "fmt" + "io/ioutil" "os" "code.gitea.io/changelog/config" - "github.com/urfave/cli/v3" + "github.com/urfave/cli/v2" ) var ( @@ -36,7 +37,7 @@ func runInit(_ *cli.Context) error { return fmt.Errorf("file '%s' already exists", nameFlag) } - if err := os.WriteFile(nameFlag, config.DefaultConfig, os.ModePerm); err != nil { + if err := ioutil.WriteFile(nameFlag, config.DefaultConfig, os.ModePerm); err != nil { return err } diff --git a/config/changelog.example.yml b/config/changelog.example.yml index e4eef9e..d092155 100644 --- a/config/changelog.example.yml +++ b/config/changelog.example.yml @@ -10,53 +10,46 @@ base-url: # Changelog groups and which labeled PRs to add to each group groups: - - + - name: BREAKING labels: - - pr/breaking - - + - kind/breaking + - name: FEATURES labels: - - type/feature - - - name: API - labels: - - modifies/api + - kind/feature - name: BUGFIXES labels: - - type/bug - - + - kind/bug + - name: ENHANCEMENTS labels: - - type/enhancement - - type/refactoring - - topic/ui - - topic/ui-interaction - - performance/speed + - kind/enhancement + - kind/refactor + - kind/ui - name: SECURITY labels: - - topic/security - - + - kind/security + - name: TESTING labels: - - type/testing - - + - kind/testing + - name: TRANSLATION labels: - - modifies/translation - - + - kind/translation + - name: BUILD labels: - - topic/build - - topic/code-linting - - + - kind/build + - kind/lint + - name: DOCS labels: - - type/docs - - modifies/docs - - + - kind/docs + - name: MISC default: true diff --git a/config/config.go b/config/config.go index 506cfb8..08a32ae 100644 --- a/config/config.go +++ b/config/config.go @@ -6,7 +6,7 @@ package config import ( _ "embed" - "os" + "io/ioutil" "regexp" "gopkg.in/yaml.v2" @@ -64,7 +64,7 @@ func New(configPath string) (*Config, error) { var err error configContent := DefaultConfig if len(configPath) != 0 { - configContent, err = os.ReadFile(configPath) + configContent, err = ioutil.ReadFile(configPath) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index 00e3457..2705659 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,19 @@ module code.gitea.io/changelog -go 1.22 +go 1.18 require ( code.gitea.io/sdk/gitea v0.14.0 - github.com/google/go-github/v61 v61.0.0 - github.com/urfave/cli/v3 v3.0.0-alpha2 - golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be + github.com/google/go-github/v32 v32.1.0 + github.com/urfave/cli/v2 v2.2.0 gopkg.in/yaml.v2 v2.3.0 ) require ( - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/golang/protobuf v1.3.2 // indirect - github.com/google/go-querystring v1.1.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/google/go-querystring v1.0.0 // indirect github.com/hashicorp/go-version v1.2.1 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect - google.golang.org/appengine v1.6.7 // indirect + github.com/russross/blackfriday/v2 v2.0.1 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect ) diff --git a/go.sum b/go.sum index 931fd86..83e07fd 100644 --- a/go.sum +++ b/go.sum @@ -1,48 +1,39 @@ code.gitea.io/sdk/gitea v0.14.0 h1:m4J352I3p9+bmJUfS+g0odeQzBY/5OXP91Gv6D4fnJ0= code.gitea.io/sdk/gitea v0.14.0/go.mod h1:89WiyOX1KEcvjP66sRHdu0RafojGo60bT9UqW17VbWs= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -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/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5pNlu1go= -github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II= +github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/urfave/cli/v3 v3.0.0-alpha2 h1:JKkuTewMlS2leTQeAcsPGL7WmBVa2uoBLy89As4Jauc= -github.com/urfave/cli/v3 v3.0.0-alpha2/go.mod h1:gHI/xEYplFhOa3Y90xJleh3kqqsSanBj/19hVFxiVZ4= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/service/gitea.go b/service/gitea.go index e8160ea..874f858 100644 --- a/service/gitea.go +++ b/service/gitea.go @@ -5,7 +5,6 @@ package service import ( - "context" "fmt" "time" @@ -24,7 +23,7 @@ type Gitea struct { } // Generate returns a Gitea changelog -func (ge *Gitea) Generate(_ context.Context) (string, []Entry, error) { +func (ge *Gitea) Generate() (string, []Entry, error) { client, err := gitea.NewClient(ge.BaseURL, gitea.SetToken(ge.Token)) if err != nil { return "", nil, err @@ -93,7 +92,7 @@ func getGiteaTagURL(c *gitea.Client, baseURL, owner, repo, mileName, gitTag, fro func convertToEntry(issue gitea.Issue) Entry { entry := Entry{ Index: issue.Index, - Title: CleanTitle(issue.Title), + Title: issue.Title, } labels := make([]Label, len(issue.Labels)) diff --git a/service/github.go b/service/github.go index 4f943c5..38654ac 100644 --- a/service/github.go +++ b/service/github.go @@ -6,17 +6,10 @@ package service import ( "context" - "errors" "fmt" - log "log/slog" - "net/http" - "os" - "strconv" - "strings" "time" - "github.com/google/go-github/v61/github" - "golang.org/x/oauth2" + "github.com/google/go-github/v32/github" ) // GitHub defines a GitHub service @@ -26,77 +19,27 @@ type GitHub struct { Token string Repo string Issues bool - ctx context.Context - client *github.Client - rate *github.Rate -} - -func (gh *GitHub) setRate(rate *github.Rate) { - gh.rate = rate -} - -func (gh *GitHub) RefreshRate() error { - rates, _, err := gh.client.RateLimit.Get(gh.ctx) - if err != nil { - // if rate limit is not enabled, ignore it - if strings.Contains(err.Error(), "404") { - gh.setRate(nil) - return nil - } - return err - } - - gh.setRate(rates.GetCore()) - return nil -} - -func (gh *GitHub) waitAndPickClient() { - for gh.rate != nil && gh.rate.Remaining <= 0 { - timer := time.NewTimer(time.Until(gh.rate.Reset.Time)) - select { - case <-gh.ctx.Done(): - timer.Stop() - return - case <-timer.C: - } - - err := gh.RefreshRate() - if err != nil { - log.Error("g.getClient().RateLimit.Get: %s", err) - } - } -} - -// OwnerRepo splits owner/repo -func (gh *GitHub) OwnerRepo() (string, string) { - parts := strings.Split(gh.Repo, "/") - if len(parts) < 2 { - return parts[0], "" - } - return parts[0], parts[1] } // Generate returns a GitHub changelog -func (gh *GitHub) Generate(ctx context.Context) (string, []Entry, error) { - owner, repo := gh.OwnerRepo() - gh.initClient(ctx) +func (gh *GitHub) Generate() (string, []Entry, error) { + tagURL := fmt.Sprintf("## [%s](https://github.com/%s/releases/tag/%s) - %s", gh.Milestone, gh.Repo, gh.GitTag, time.Now().Format("2006-01-02")) - tagURL := fmt.Sprintf("## [%s](https://github.com/%s/releases/tag/v%s) - %s", gh.Milestone, gh.Repo, gh.GitTag, time.Now().Format("2006-01-02")) + client := github.NewClient(nil) + ctx := context.Background() prs := make([]Entry, 0) - milestoneNum, err := gh.milestoneNum(ctx) - if err != nil { - return "", nil, err + state := "merged" + if gh.Issues { + state = "closed" } + query := fmt.Sprintf(`repo:%s is:%s milestone:"%s"`, gh.Repo, state, gh.Milestone) p := 1 perPage := 100 for { - gh.waitAndPickClient() - result, resp, err := gh.client.Issues.ListByRepo(ctx, owner, repo, &github.IssueListByRepoOptions{ - Milestone: strconv.Itoa(milestoneNum), - State: "closed", + result, _, err := client.Search.Issues(ctx, query, &github.SearchOptions{ ListOptions: github.ListOptions{ Page: p, PerPage: perPage, @@ -105,15 +48,14 @@ func (gh *GitHub) Generate(ctx context.Context) (string, []Entry, error) { if err != nil { return "", nil, err } - gh.setRate(&resp.Rate) p++ isPull := !(gh.Issues) - for _, pr := range result { + for _, pr := range result.Issues { if pr.IsPullRequest() == isPull { p := Entry{ - Title: CleanTitle(pr.GetTitle()), + Title: pr.GetTitle(), Index: int64(pr.GetNumber()), } @@ -129,7 +71,7 @@ func (gh *GitHub) Generate(ctx context.Context) (string, []Entry, error) { } } - if len(result) != perPage { + if len(result.Issues) != perPage { break } } @@ -139,22 +81,15 @@ func (gh *GitHub) Generate(ctx context.Context) (string, []Entry, error) { // Contributors returns a list of contributors from GitHub func (gh *GitHub) Contributors() (ContributorList, error) { + client := github.NewClient(nil) ctx := context.Background() - owner, repo := gh.OwnerRepo() - gh.initClient(ctx) contributorsMap := make(map[string]bool) - milestoneNum, err := gh.milestoneNum(ctx) - if err != nil { - return nil, err - } + query := fmt.Sprintf(`repo:%s is:merged milestone:"%s"`, gh.Repo, gh.Milestone) p := 1 perPage := 100 for { - gh.waitAndPickClient() - result, resp, err := gh.client.Issues.ListByRepo(ctx, owner, repo, &github.IssueListByRepoOptions{ - Milestone: strconv.Itoa(milestoneNum), - State: "closed", + result, _, err := client.Search.Issues(ctx, query, &github.SearchOptions{ ListOptions: github.ListOptions{ Page: p, PerPage: perPage, @@ -163,14 +98,13 @@ func (gh *GitHub) Contributors() (ContributorList, error) { if err != nil { return nil, err } - gh.setRate(&resp.Rate) p++ - for _, pr := range result { + for _, pr := range result.Issues { contributorsMap[pr.GetUser().GetLogin()] = true } - if len(result) != perPage { + if len(result.Issues) != perPage { break } } @@ -185,55 +119,3 @@ func (gh *GitHub) Contributors() (ContributorList, error) { return contributors, nil } - -func (gh *GitHub) initClient(ctx context.Context) { - token := gh.Token - if envToken, ok := os.LookupEnv("CHANGELOG_GITHUB_TOKEN"); ok && token == "" { - token = envToken - } - cl := http.DefaultClient - if token != "" { - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: token}, - ) - cl = oauth2.NewClient(ctx, ts) - } - - gh.client = github.NewClient(cl) - gh.ctx = ctx -} - -func (gh *GitHub) milestoneNum(ctx context.Context) (int, error) { - owner, repo := gh.OwnerRepo() - p := 1 - perPage := 100 - for { - gh.waitAndPickClient() - milestones, resp, err := gh.client.Issues.ListMilestones(ctx, owner, repo, &github.MilestoneListOptions{ - State: "all", - ListOptions: github.ListOptions{ - Page: p, - PerPage: perPage, - }, - Sort: "due_on", - Direction: "desc", - }) - if err != nil { - return 0, err - } - gh.setRate(&resp.Rate) - p++ - - for _, milestone := range milestones { - if strings.EqualFold(milestone.GetTitle(), gh.Milestone) { - return milestone.GetNumber(), nil - } - } - - if len(milestones) != perPage { - break - } - } - - return 0, errors.New("no milestone found") -} diff --git a/service/github_test.go b/service/github_test.go index 2cc4f17..562216d 100644 --- a/service/github_test.go +++ b/service/github_test.go @@ -4,10 +4,7 @@ package service -import ( - "context" - "testing" -) +import "testing" var gh = &GitHub{ Milestone: "1.1.0", // https://github.com/go-gitea/test_repo/milestone/2?closed=1 @@ -15,7 +12,7 @@ var gh = &GitHub{ } func TestGitHubGenerate(t *testing.T) { - _, entries, err := gh.Generate(context.Background()) + _, entries, err := gh.Generate() if err != nil { t.Log(err) t.FailNow() diff --git a/service/service.go b/service/service.go index 58f29d7..de7e76a 100644 --- a/service/service.go +++ b/service/service.go @@ -5,10 +5,8 @@ package service import ( - "context" "fmt" "strings" - "unicode" ) const defaultGitea = "https://gitea.com" @@ -49,7 +47,7 @@ func New(serviceType, repo, baseURL, milestone, tag, token string, issues bool) // Service defines how a struct can be a Changelog Service type Service interface { - Generate(ctx context.Context) (string, []Entry, error) + Generate() (string, []Entry, error) Contributors() (ContributorList, error) } @@ -88,14 +86,3 @@ func (cl ContributorList) Less(i, j int) bool { func (cl ContributorList) Swap(i, j int) { cl[i], cl[j] = cl[j], cl[i] } - -// CleanTitle returns the string with spaces trimmed and the first rune title-cased -func CleanTitle(s string) string { - s = strings.TrimSpace(s) - - r := []rune(s) - r[0] = unicode.ToUpper(r[0]) - s = string(r) - - return s -} diff --git a/service/service_test.go b/service/service_test.go index 47c57cb..045e70f 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -12,27 +12,3 @@ import ( func TestMain(m *testing.M) { os.Exit(m.Run()) } - -func TestCleanTitle(t *testing.T) { - tt := []struct { - Title string - Expected string - }{ - {Title: "foo", Expected: "Foo"}, - {Title: " foo", Expected: "Foo"}, - {Title: "foo bar", Expected: "Foo bar"}, - {Title: "Foo bar", Expected: "Foo bar"}, - {Title: " Foo bar ", Expected: "Foo bar"}, - {Title: "1234", Expected: "1234"}, - } - - for _, tc := range tt { - t.Run(tc.Title, func(t *testing.T) { - s := CleanTitle(tc.Title) - if s != tc.Expected { - t.Logf("got %q | expected %q", s, tc.Expected) - t.Fail() - } - }) - } -}