From 66dd629d0ad1d47ded5dc4cbc09f9b3fafbbc08b Mon Sep 17 00:00:00 2001 From: Vadim Bauer Date: Sat, 26 Oct 2024 23:55:15 +0200 Subject: [PATCH] Optimise pipeline for release and daily operation (#222) refactor gh-action, optimize pipeline for release and daily operation, refactor linter --- .github/workflows/default.yaml | 83 ++++++++++++++++++++ .github/workflows/docker_publish.yml | 35 --------- .github/workflows/publish_release.yml | 29 ------- .github/workflows/pull-request.yml | 59 -------------- .github/workflows/release.yaml | 69 ++++++++++++++++ .golangci.yaml | 22 +++--- .goreleaser.yaml | 7 +- README.md | 8 +- dagger.json | 5 +- dagger/go.mod | 11 ++- dagger/go.sum | 18 +++-- dagger/main.go | 108 ++++++++++++++------------ doc/doc.go | 2 +- pkg/constants/constants.go | 6 -- test/e2e/login_test.go | 6 +- 15 files changed, 260 insertions(+), 208 deletions(-) create mode 100644 .github/workflows/default.yaml delete mode 100644 .github/workflows/docker_publish.yml delete mode 100644 .github/workflows/publish_release.yml delete mode 100644 .github/workflows/pull-request.yml create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/default.yaml b/.github/workflows/default.yaml new file mode 100644 index 00000000..2c5d172b --- /dev/null +++ b/.github/workflows/default.yaml @@ -0,0 +1,83 @@ +name: Main and Pull Request Pipeline + +on: + push: + branches: [main] + pull_request: + paths-ignore: + - '*.md' + - 'assets/**' + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Dagger Version + uses: sagikazarmark/dagger-version-action@v0.0.1 + + - name: Run Dagger golangci-lint + uses: dagger/dagger-for-github@v6 + with: + version: ${{ steps.dagger_version.outputs.version }} + verb: call + args: lint-report export --path=golangci-lint-report.sarif + + - uses: reviewdog/action-setup@v1 + - name: Run Reviewdog + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + reviewdog -f=sarif -name="Golang Linter Report" -reporter=github-check -filter-mode nofilter -fail-level any -tee < golangci-lint-report.sarif + + test-code: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run Tests + uses: dagger/dagger-for-github@v6 + with: + version: ${{ steps.dagger_version.outputs.version }} + verb: call + args: test + + - name: Build Binary + uses: dagger/dagger-for-github@v6 + with: + version: ${{ steps.dagger_version.outputs.version }} + verb: call + args: build-dev --platform linux/amd64 + + push-snapshop-release: + permissions: + contents: write + packages: write + + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + needs: + - lint + - test-code + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Dagger Version + uses: sagikazarmark/dagger-version-action@v0.0.1 + + - name: Push Release + uses: dagger/dagger-for-github@v6 + with: + version: ${{ steps.dagger_version.outputs.version }} + verb: call + args: snapshot-release --github-token=${{ env.GITHUB_TOKEN }} diff --git a/.github/workflows/docker_publish.yml b/.github/workflows/docker_publish.yml deleted file mode 100644 index 5fa4b52c..00000000 --- a/.github/workflows/docker_publish.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Docker Publish - -on: - push: - tags: - - "v*" - -jobs: - docker-publish: - runs-on: ubuntu-latest - permissions: - contents: write - packages: write - environment: production - env: - COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} - COSIGN_KEY: ${{ secrets.COSIGN_KEY }} - REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} - REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} - REGISTRY_ADDRESS: ${{ vars.REGISTRY_ADDRESS }} - PUBLISH_ADDRESS: ${{ vars.PUBLISH_ADDRESS }} - TAG: ${{ github.ref_name }} - - steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Call Docker-Publish Function - uses: dagger/dagger-for-github@v6.13.0 - with: - version: "latest" - verb: call - args: "publish-image --cosign-password='env:${{ env.COSIGN_PASSWORD }}' --cosign-key='env:${{ env.COSIGN_KEY }}' --reg-username='${{ env.REGISTRY_USERNAME }}' --reg-password='env:${{ env.REGISTRY_PASSWORD }}' --reg-address='${{ env.REGISTRY_ADDRESS }}' --publish-address='${{ env.PUBLISH_ADDRESS }}' --tag='${{ env.TAG }}'" diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml deleted file mode 100644 index f2d1fef9..00000000 --- a/.github/workflows/publish_release.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Dagger Release Pipeline - -on: - push: - tags: - - "v*" - branches: [main] - -permissions: - contents: write - packages: write - -jobs: - publish-release: - if: startsWith(github.ref, 'refs/tags/') - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Call Dagger Function - uses: dagger/dagger-for-github@v6.13.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - version: "latest" - verb: call - args: release --github-token='env:${{ env.GITHUB_TOKEN }}' \ No newline at end of file diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml deleted file mode 100644 index 82cd90da..00000000 --- a/.github/workflows/pull-request.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Dagger Pull Request Pipeline - -on: - push: - branches: [main] - pull_request: - paths-ignore: - - '*.md' - - 'assets/**' - -permissions: - contents: write # This is required for actions/checkout - packages: write # This is required for publishing the package - -jobs: - test-code: - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: "1.22.5" - cache: true - - - name: Install dependencies - run: go mod download - - - name: Test with the Go CLI - run: go test -v ./... - - - name: Call Linting Function - uses: dagger/dagger-for-github@v6.13.0 - with: - version: "latest" - verb: call - args: lint --source=. - - - name: Call Build Function - uses: dagger/dagger-for-github@v6.1.0 - with: - version: "latest" - verb: call - args: build --source=. - - - name: Call Pull-Request Function - uses: dagger/dagger-for-github@v6.13.0 - if: always() - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - version: "latest" - verb: call - args: pull-request --source=. --github-token=${{ env.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..ad837985 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,69 @@ +name: Release Artifacts and Container Images + +on: + push: + tags: + - "v*" + branches: [main] + +permissions: + contents: write + packages: write + +jobs: + publish-release: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Call Dagger Function + uses: dagger/dagger-for-github@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + version: "latest" + verb: call + args: release --github-token='env:${{ env.GITHUB_TOKEN }}' + + publish-images: + runs-on: ubuntu-latest + environment: PROD + env: + COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} + COSIGN_KEY: ${{ secrets.COSIGN_KEY }} + REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} + REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} + REGISTRY_ADDRESS: ${{ vars.REGISTRY_ADDRESS }} + PUBLISH_ADDRESS: ${{ vars.PUBLISH_ADDRESS }} + TAG: ${{ github.ref_name }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Call Docker-Publish Function + uses: dagger/dagger-for-github@v6 + with: + version: "latest" + verb: call + args: "publish-image --cosign-password='env:${{ env.COSIGN_PASSWORD }}' --cosign-key='env:${{ env.COSIGN_KEY }}' --reg-username='${{ env.REGISTRY_USERNAME }}' --reg-password='env:${{ env.REGISTRY_PASSWORD }}' --reg-address='${{ env.REGISTRY_ADDRESS }}' --publish-address='${{ env.PUBLISH_ADDRESS }}' --tag='${{ env.TAG }}'" + - name: Notify on success + if: success() + uses: actions/github-script@v6 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + body: "Container image published successfully! 🎉" + }) + - name: Notify on failure + if: failure() + uses: actions/github-script@v6 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + body: "Failed to publish Container image. ❌" + }) diff --git a/.golangci.yaml b/.golangci.yaml index 1ed0475f..b9a4d4f2 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,13 +1,17 @@ - +run: + timeout: 3m linters: enable: - # default linters - - errcheck - - gosimple - - govet - - ineffassign - - staticcheck + # Default linters are already enabled, these are the additional ones - typecheck - - unused - - gofmt + - gosec + - nilnil + # - wrapcheck + # - gocritic + # - revive #, enable once current issues are resolved +issues: + exclude-dirs: + - dagger/internal + exclude-files: + - ^.*\\.gen\\.go$ diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 3db04509..91b7003a 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,5 +1,5 @@ version: 2 -project_name: harbor +project_name: harbor-cli before: hooks: @@ -47,8 +47,11 @@ sboms: checksum: name_template: 'checksums.txt' + snapshot: - version_template: "{{ .Tag }}-next" + name_template: "HarborCLI Snapshot {{.Commit}}" + publish: true + release: name_template: "HarborCLI {{.Tag}}" draft: false # Set to false to ensure that releases are published, not kept as drafts diff --git a/README.md b/README.md index 69b82f40..f16e0e8c 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Use "harbor [command] --help" for more information about a command. #### Log in to Harbor Registry ```bash -harbor login demo.goharbor.io -u admin -p Harbor12345 +harbor login demo.goharbor.io -u harbor-cli -p Harbor12345 ``` #### Create a New Project @@ -123,13 +123,15 @@ Make sure you have latest [Dagger](https://docs.dagger.io/) installed in your sy #### Using Dagger ```bash git clone https://github.com/goharbor/harbor-cli.git && cd harbor-cli -dagger call build-dev --platform darwin/arm64 export --path=./harbor-dev +dagger call build-dev --platform darwin/arm64 export --path=./harbor-cli ./harbor-dev --help ``` +If golang is installed in your system, you can also build the project using the following commands: + ```bash git clone https://github.com/goharbor/harbor-cli.git -dagger call build +go build -o harbor-cli cmd/harbor/main.go ``` diff --git a/dagger.json b/dagger.json index a9612e6c..87feeb60 100644 --- a/dagger.json +++ b/dagger.json @@ -4,9 +4,10 @@ "dependencies": [ { "name": "cosign", - "source": "github.com/scottames/daggerverse/cosign@8359122a7b90f2c8c6f3165570fdcbec6e923023" + "source": "github.com/scottames/daggerverse/cosign@8359122a7b90f2c8c6f3165570fdcbec6e923023", + "pin": "8359122a7b90f2c8c6f3165570fdcbec6e923023" } ], "source": "dagger", - "engineVersion": "v0.13.5" + "engineVersion": "v0.13.6" } diff --git a/dagger/go.mod b/dagger/go.mod index 6253d918..d52dfa4e 100644 --- a/dagger/go.mod +++ b/dagger/go.mod @@ -3,9 +3,9 @@ module dagger/harbor-cli go 1.23.1 require ( - github.com/99designs/gqlgen v0.17.49 + github.com/99designs/gqlgen v0.17.55 github.com/Khan/genqlient v0.7.0 - github.com/vektah/gqlparser/v2 v2.5.16 + github.com/vektah/gqlparser/v2 v2.5.17 go.opentelemetry.io/otel v1.27.0 go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88 go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.3.0 @@ -28,10 +28,13 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/sosodev/duration v1.3.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.27.0 + go.opentelemetry.io/otel/sdk/metric v1.27.0 golang.org/x/net v0.29.0 // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.18.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect diff --git a/dagger/go.sum b/dagger/go.sum index f6bb5391..c52dd24b 100644 --- a/dagger/go.sum +++ b/dagger/go.sum @@ -1,5 +1,5 @@ -github.com/99designs/gqlgen v0.17.49 h1:b3hNGexHd33fBSAd4NDT/c3NCcQzcAVkknhN9ym36YQ= -github.com/99designs/gqlgen v0.17.49/go.mod h1:tC8YFVZMed81x7UJ7ORUwXF4Kn6SXuucFqQBhN8+BU0= +github.com/99designs/gqlgen v0.17.55 h1:3vzrNWYyzSZjGDFo68e5j9sSauLxfKvLp+6ioRokVtM= +github.com/99designs/gqlgen v0.17.55/go.mod h1:3Bq768f8hgVPGZxL8aY9MaYmbxa6llPM/qu1IGH1EJo= github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= github.com/Khan/genqlient v0.7.0/go.mod h1:HNyy3wZvuYwmW3Y7mkoQLZsa/R5n5yIRajS1kPBvSFM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= @@ -27,14 +27,18 @@ github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= 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/vektah/gqlparser/v2 v2.5.16 h1:1gcmLTvs3JLKXckwCwlUagVn/IlV2bwqle0vJ0vy5p8= -github.com/vektah/gqlparser/v2 v2.5.16/go.mod h1:1lz1OeCqgQbQepsGxPVywrjdBHW2T08PUS3pJqepRww= +github.com/vektah/gqlparser/v2 v2.5.17 h1:9At7WblLV7/36nulgekUgIaqHZWn5hxqluxrxGUhOmI= +github.com/vektah/gqlparser/v2 v2.5.17/go.mod h1:1lz1OeCqgQbQepsGxPVywrjdBHW2T08PUS3pJqepRww= go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88 h1:oM0GTNKGlc5qHctWeIGTVyda4iFFalOzMZ3Ehj5rwB4= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88/go.mod h1:JGG8ebaMO5nXOPnvKEl+DiA4MGwFjCbjsxT1WHIEBPY= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.3.0 h1:ccBrA8nCY5mM0y5uO7FT0ze4S0TuFcWdDB2FxGMTjkI= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.3.0/go.mod h1:/9pb6634zi2Lk8LYg9Q0X8Ar6jka4dkFOylBLbVQPCE= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 h1:bFgvUr3/O4PHj3VQcFEuYKvRZJX1SJDQ+11JXuSB3/w= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0/go.mod h1:xJntEd2KL6Qdg5lwp97HMLQDVeAhrYxmzFseAMDPQ8I= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= @@ -49,6 +53,8 @@ go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kT go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= go.opentelemetry.io/otel/sdk/log v0.3.0 h1:GEjJ8iftz2l+XO1GF2856r7yYVh74URiF9JMcAacr5U= go.opentelemetry.io/otel/sdk/log v0.3.0/go.mod h1:BwCxtmux6ACLuys1wlbc0+vGBd+xytjmjajwqqIul2g= +go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= +go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= @@ -61,8 +67,8 @@ golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= 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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= diff --git a/dagger/main.go b/dagger/main.go index 3bdf28fc..ca5f6874 100644 --- a/dagger/main.go +++ b/dagger/main.go @@ -29,33 +29,31 @@ type HarborCli struct { Source *dagger.Directory } -// Dev Build of Harbor CLI for local testing and development +// Create build of Harbor CLI for local testing and development func (m *HarborCli) BuildDev( ctx context.Context, - // platform to build for platform string, ) *dagger.File { fmt.Println("🛠️ Building Harbor-Cli with Dagger...") // Define the path for the binary output os, arch, err := parsePlatform(platform) + if err != nil { log.Fatalf("Error parsing platform: %v", err) } - builder := dag.Container(). - From("golang:latest"). - WithMountedDirectory("/src", m.Source). // Ensure the source directory with go.mod is mounted - WithWorkdir("/src"). - WithMountedCache("/go/pkg/mod", dag.CacheVolume("dev-go-mod-"+GO_VERSION)). + From("golang:"+GO_VERSION+"-alpine"). + WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-"+GO_VERSION)). WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). - WithMountedCache("/go/build-cache", dag.CacheVolume("dev-go-build-"+GO_VERSION)). + WithMountedCache("/go/build-cache", dag.CacheVolume("go-build-"+GO_VERSION)). WithEnvVariable("GOCACHE", "/go/build-cache"). + WithMountedDirectory("/src", m.Source). // Ensure the source directory with go.mod is mounted + WithWorkdir("/src"). WithEnvVariable("GOOS", os). WithEnvVariable("GOARCH", arch). - WithExec([]string{"go", "build", "-o", "/src/bin/harbor-dev", "/src/cmd/harbor/main.go"}) - - return builder.File("/src/bin/harbor-dev") + WithExec([]string{"go", "build", "-o", "bin/harbor-cli", "cmd/harbor/main.go"}) + return builder.File("bin/harbor-cli") } // Return list of containers for list of oses and arches @@ -77,12 +75,12 @@ func (m *HarborCli) build( bin_path := fmt.Sprintf("build/%s/%s/", goos, goarch) builder := dag.Container(). From("golang:"+GO_VERSION+"-alpine"). - WithMountedDirectory("/src", m.Source). - WithWorkdir("/src"). WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-"+GO_VERSION)). WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). WithMountedCache("/go/build-cache", dag.CacheVolume("go-build-"+GO_VERSION)). WithEnvVariable("GOCACHE", "/go/build-cache"). + WithMountedDirectory("/src", m.Source). + WithWorkdir("/src"). WithEnvVariable("GOOS", goos). WithEnvVariable("GOARCH", goarch). WithExec([]string{"go", "build", "-o", bin_path + "harbor", "/src/cmd/harbor/main.go"}). @@ -96,26 +94,33 @@ func (m *HarborCli) build( return builds } -// Return container with source mounted and execute golangci-lint -func (m *HarborCli) Lint( - ctx context.Context, -) *dagger.Container { - fmt.Println("👀 Running linter with Dagger...") - return dag.Container(). +// Run linter golangci-lint and write the linting results to a file golangci-lint-report.txt +func (m *HarborCli) LintReport(ctx context.Context) *dagger.File { + report := "golangci-lint-report.sarif" + return m.lint(ctx).WithExec([]string{"golangci-lint", "run", + "--out-format", "sarif:" + report, + "--issues-exit-code", "0"}).File(report) +} + +// Run linter golangci-lint +func (m *HarborCli) Lint(ctx context.Context) (string, error) { + return m.lint(ctx).WithExec([]string{"golangci-lint", "run"}).Stderr(ctx) +} + +func (m *HarborCli) lint(ctx context.Context) *dagger.Container { + fmt.Println("👀 Running linter and printing results to file golangci-lint.txt.") + linter := dag.Container(). From("golangci/golangci-lint:"+GOLANGCILINT_VERSION+"-alpine"). - WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-"+GO_VERSION)). - WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). - WithMountedCache("/go/build-cache", dag.CacheVolume("go-build-"+GO_VERSION)). - WithEnvVariable("GOCACHE", "/go/build-cache"). + WithMountedCache("/lint-cache", dag.CacheVolume("/lint-cache")). + WithEnvVariable("GOLANGCI_LINT_CACHE", "/lint-cache"). WithMountedDirectory("/src", m.Source). - WithWorkdir("/src"). - WithExec([]string{"golangci-lint", "run", "--timeout", "5m"}) + WithWorkdir("/src") + return linter } // Create snapshot release with goreleaser -func (m *HarborCli) PullRequest( +func (m *HarborCli) SnapshotRelease( ctx context.Context, - // Github API token githubToken *dagger.Secret, ) { _, err := m. @@ -147,22 +152,15 @@ func (m *HarborCli) Release( log.Println("Release tasks completed successfully 🎉") } -// PublishImage publishes a Docker image to a registry with a specific tag and signs it using Cosign. +// PublishImage publishes a container image to a registry with a specific tag and signs it using Cosign. func (m *HarborCli) PublishImage( ctx context.Context, - // the secret used for signing the image cosignKey *dagger.Secret, - // the password for the cosign secret cosignPassword *dagger.Secret, - // the username for the registry regUsername string, - // the password for the registry regPassword *dagger.Secret, - // the address of the registry to publish the image regAddress string, - // the address of the registry to publish the image publishAddress string, - // the version tag for the image tag string, ) string { var container *dagger.Container @@ -216,11 +214,7 @@ func (m *HarborCli) PublishImage( } // Return the platform of the container -func buildPlatform( - ctx context.Context, - // container to check - container *dagger.Container, -) string { +func buildPlatform(ctx context.Context, container *dagger.Container) string { platform, err := container.Platform(ctx) if err != nil { log.Fatalf("error getting platform", err) @@ -241,7 +235,10 @@ func (m *HarborCli) goreleaserContainer( return dag.Container(). From(fmt.Sprintf("goreleaser/goreleaser:%s", GORELEASER_VERSION)). - WithMountedCache("/go/pkg/mod", dag.CacheVolume("goreleaser-gomod")). + WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-"+GO_VERSION)). + WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). + WithMountedCache("/go/build-cache", dag.CacheVolume("go-build-"+GO_VERSION)). + WithEnvVariable("GOCACHE", "/go/build-cache"). WithFile("/bin/syft", syft). WithMountedDirectory("/src", m.Source). WithWorkdir("/src"). @@ -250,14 +247,12 @@ func (m *HarborCli) goreleaserContainer( } // Generate CLI Documentation with doc.go and return the directory containing the generated files -func (m *HarborCli) RunDoc( - ctx context.Context, -) *dagger.Directory { - fmt.Println("Running doc.go file using Dagger...") +func (m *HarborCli) RunDoc(ctx context.Context) *dagger.Directory { return dag.Container(). - From("golang:latest"). - WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod")). - WithMountedCache("/go/build-cache", dag.CacheVolume("go-build")). + From("golang:"+GO_VERSION+"-alpine"). + WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-"+GO_VERSION)). + WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). + WithMountedCache("/go/build-cache", dag.CacheVolume("go-build-"+GO_VERSION)). WithEnvVariable("GOCACHE", "/go/build-cache"). WithMountedDirectory("/src", m.Source). WithWorkdir("/src/doc"). @@ -265,10 +260,25 @@ func (m *HarborCli) RunDoc( WithWorkdir("/src").Directory("/src/doc") } +// Executes Go tests and returns the directory containing the test results +func (m *HarborCli) Test(ctx context.Context) *dagger.Directory { + return dag.Container(). + From("golang:"+GO_VERSION+"-alpine"). + WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-"+GO_VERSION)). + WithEnvVariable("GOMODCACHE", "/go/pkg/mod"). + WithMountedCache("/go/build-cache", dag.CacheVolume("go-build-"+GO_VERSION)). + WithEnvVariable("GOCACHE", "/go/build-cache"). + WithMountedDirectory("/src", m.Source). + WithWorkdir("/src"). + WithExec([]string{"go", "test", "-v", "./..."}). + Directory("/src") +} + +// Parse the platform string into os and arch func parsePlatform(platform string) (string, string, error) { parts := strings.Split(platform, "/") if len(parts) != 2 { - return "", "", fmt.Errorf("Invalid platform format: %s. Should be os/arch. E.g. darwin/amd64", platform) + return "", "", fmt.Errorf("invalid platform format: %s. Should be os/arch. E.g. darwin/amd64", platform) } return parts[0], parts[1], nil } diff --git a/doc/doc.go b/doc/doc.go index 5cd42136..3f196208 100644 --- a/doc/doc.go +++ b/doc/doc.go @@ -48,7 +48,7 @@ func preblock(filename string) string { file := strings.Split(filename, markdownExtension) name := filepath.Base(file[0]) title := strings.ReplaceAll(name, "-", " ") - randomNumber := rand.Intn(20) + randomNumber := rand.Intn(20) //nolint:gosec weight := randomNumber * 5 return fmt.Sprintf(frontmdtemplate, title, weight) diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 28ec48f5..1255fc8b 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -1,7 +1 @@ package constants - -const ( - HarborCredentialName = "HARBORCREDENTIALNAME" - CredentialNameOption = "credential-name" - CredentialNameHelp = "Name of the credential to use for authentication (defaults to the current logged in session)" -) diff --git a/test/e2e/login_test.go b/test/e2e/login_test.go index 171223f6..23d5dd51 100644 --- a/test/e2e/login_test.go +++ b/test/e2e/login_test.go @@ -31,7 +31,7 @@ func Test_Login_Success(t *testing.T) { cmd.SetArgs(args) assert.NoError(t, cmd.Flags().Set("name", "test")) - assert.NoError(t, cmd.Flags().Set("username", "admin")) + assert.NoError(t, cmd.Flags().Set("username", "harbor-cli")) assert.NoError(t, cmd.Flags().Set("password", "Harbor12345")) err := cmd.Execute() @@ -46,7 +46,7 @@ func Test_Login_Failure_WrongServer(t *testing.T) { cmd.SetArgs(args) assert.NoError(t, cmd.Flags().Set("name", "test")) - assert.NoError(t, cmd.Flags().Set("username", "admin")) + assert.NoError(t, cmd.Flags().Set("username", "harbor-cli")) assert.NoError(t, cmd.Flags().Set("password", "Harbor12345")) err := cmd.Execute() @@ -59,7 +59,7 @@ func Test_Login_Failure_WrongUsername(t *testing.T) { cmd.SetArgs(args) assert.NoError(t, cmd.Flags().Set("name", "test")) - assert.NoError(t, cmd.Flags().Set("username", "wrong")) + assert.NoError(t, cmd.Flags().Set("username", "does-not-exist")) assert.NoError(t, cmd.Flags().Set("password", "Harbor12345")) err := cmd.Execute()