-
Notifications
You must be signed in to change notification settings - Fork 42
Goreleaser to manage release #55
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| name: goreleaser | ||
|
|
||
| on: | ||
| push: | ||
| branches-ignore: | ||
| - "**" | ||
| tags: | ||
| - "v*.*.*" | ||
|
|
||
| jobs: | ||
| goreleaser: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v2 | ||
| - uses: azure/docker-login@v1 | ||
| with: | ||
| username: ${{ secrets.DOCKER_USERNAME }} | ||
| password: ${{ secrets.DOCKER_PASSWORD }} | ||
| email: ${{ secrets.DOCKER_USERNAME }} | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v2 | ||
| with: | ||
| go-version: 1.13.x | ||
| - name: install kustomize | ||
| uses: imranismail/setup-kustomize@v1 | ||
| with: | ||
| kustomize-version: "3.5.4" | ||
| - name: Run GoReleaser | ||
| uses: goreleaser/goreleaser-action@v2.0.2 | ||
| with: | ||
| version: latest | ||
| args: release --rm-dist | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,3 +36,6 @@ config/default/manager_image_patch.yaml-e | |
|
|
||
| # test results | ||
| _artifacts | ||
|
|
||
| # Goreleaser | ||
| dist | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| before: | ||
| hooks: | ||
| - make manifest | ||
| builds: | ||
| - | ||
| id: capp | ||
| env: | ||
| - CGO_ENABLED=0 | ||
| binary: manager | ||
| goos: | ||
| - darwin | ||
| - linux | ||
| goarch: | ||
| - amd64 | ||
| - arm64 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this try to build also for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it is smart enough to build only what Go can build apparently 👍 in my test locally it built: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK |
||
| release: | ||
| extra_files: | ||
| - glob: "./out/release/infrastructure-packet/{{ .Tag }}/*" | ||
| dockers: | ||
| - image_templates: | ||
| - "packethost/cluster-api-provider-packet:latest-arm64" | ||
| - "packethost/cluster-api-provider-packet:{{ .Tag }}-arm64" | ||
| binaries: | ||
| - manager | ||
| builds: | ||
| - capp | ||
| dockerfile: Dockerfile.goreleaser | ||
| goos: linux | ||
| goarch: arm64 | ||
| # The idea here is to add a post hook that will use the manifest tool to | ||
| # merge all the images and push them properly | ||
| skip_push: true | ||
| - image_templates: | ||
| - "packethost/cluster-api-provider-packet:latest-amd64" | ||
| - "packethost/cluster-api-provider-packet:{{ .Tag }}-amd64" | ||
| dockerfile: Dockerfile.goreleaser | ||
| binaries: | ||
| - manager | ||
| builds: | ||
| - capp | ||
| goos: linux | ||
| goarch: amd64 | ||
| # The idea here is to add a post hook that will use the manifest tool to | ||
| # merge all the images and push them properly | ||
| skip_push: true | ||
| archives: | ||
| - replacements: | ||
| darwin: Darwin | ||
| linux: Linux | ||
| 386: i386 | ||
| amd64: x86_64 | ||
| checksum: | ||
| name_template: 'checksums.txt' | ||
| snapshot: | ||
| name_template: "{{ .Tag }}-next" | ||
| changelog: | ||
| sort: asc | ||
| filters: | ||
| exclude: | ||
| - '^docs:' | ||
| - '^test:' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| FROM scratch | ||
| COPY manager / | ||
| ENTRYPOINT ["/manager"] | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| # how release works | ||
|
|
||
| Prerequisite: | ||
|
|
||
| * docker installed | ||
| * How drone works | ||
| * How [goreleaser](https://goreleaser.com/intro/) works and you have to | ||
| [install](https://goreleaser.com/install/) it to try a release locally. | ||
| * multi arch TODO, don't know yet | ||
|
|
||
| ## Continuous Delivery | ||
|
|
||
| We use GitHub Action as continuous integration and continuous delivery pipeline. | ||
| Integration means: running tests, checking code quality. | ||
| Delivery means: make a release when a new tag get pushed. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might want to add something here about delivery vs release. Whenever something gets merged into master, we push a new image tagged with that hash, e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will do! Thanks, I didn't notice that |
||
|
|
||
| GoReleaser is used only when a new tag gets pushed. We also push a new image | ||
| every time master changes. I will document this workflow in its own chapter: | ||
| "push from master" at the end of this document but at the moment it does not use | ||
| GoReleaser. | ||
|
|
||
| ## goreleaser | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we use goreleaser only when cutting an actual tagged release, e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, we use what we already have in place There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So there are two different flows, then? One for cutting tagged releases (goreleaser) and one for non-tagged merges (existing)? And I assume the difference is handled in drone.yml where "if release then run goreleaser"? We should document that. |
||
|
|
||
| GoReleaser is a popular tool to release Go applications and library. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is goreleaser expected to be installed? What installs it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So how does it get installed? If I run this, then I will have a failure? I think if this is used for releases only (not normal builds) then it is OK not to have it verified and installed automatically (although it would be nice, but not necessary), but we need to make it clear that: it is a prerequisite for releases; here is the link to install it; it isn't needed except for releases, which are normally handled by drone. And, of course, we need to add it to drone.yml, but that can come later. |
||
|
|
||
| We use GoReleaser for the following features: | ||
|
|
||
| * Multi arch build. It uses Go cross compilation feature to build for Darwin and | ||
| Linux (arm and amd) | ||
| * Docker to build docker images for Linux container arm and amd. | ||
| * Changelog to generate a changelog that will be pushed in the GitHub release | ||
| page with the list of PR part of the release itself. | ||
| * Artifact (binaries) will be pushed as part of GitHub release page as well as | ||
| the other YAML file required by cluster-api like: metadata.yaml, | ||
| infrastructure-provider.yaml and so on. | ||
|
|
||
| First things you should check if the file `./goreleaser.yaml` in the project | ||
| root because it gives you an idea about what it does. | ||
|
|
||
| ## Directories and general workflow | ||
|
|
||
| The release life cycle touches two directories: | ||
|
|
||
| 1. `./dist` it is a temporary directory used by GoReleaser to bundle all the | ||
| required files and, binaries, changelog and so on. It is in gitignore. | ||
| 2. `./out` is ignored by git and it gets generated via `make release`. It is a | ||
| bundle that contains generated Kubernetes manifest required by the | ||
| cluster-api such as: metadata.yaml, infrastructure-provider.yaml, | ||
| cluster-template.yaml and so on. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How are they bundled together? Does goreleaser create them all and move them all into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can mention looking at the Goreleaser builds binary by its own in if you look at the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. Can we add that to the doc? Something as simple as: the details are in goreleaser.yaml, but the process goreleaser does is:
|
||
|
|
||
| GoReleaser works in this way: | ||
|
|
||
| 1. it builds binaries in `./dist` | ||
| 2. moves all the file that has to be added in the release archive and release | ||
| page such as: LICENSE, README, the kubernetes manifests in `./dist` | ||
| 3. Build docker images | ||
| 4. Push all the archives and the images to GitHub and to Docker Hub. | ||
|
|
||
| ## Local workflow | ||
|
|
||
| GoReleaser can be used locally, to visualize how a release will look like for | ||
| example: | ||
|
|
||
| ``` | ||
| $ goreleaser release --rm-dir --skip-publish | ||
| ``` | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have been pretty good about simple make targets that wrap complex commands. As it is, much of our generation (e.g. |
||
|
|
||
| You can run this command if your git HEAD has a tag. You can make a temporary | ||
| one: | ||
|
|
||
| ``` | ||
| git tag v0.10.0 | ||
| ``` | ||
|
|
||
| Or you can decided to run GoRelease in `--snapshot` mode to avoid a fake tag | ||
| (but changelog won't work): | ||
|
|
||
| ``` | ||
| $ goreleaser release --rm-dir --snapshot --skip-publish | ||
| ``` | ||
|
|
||
| *Removing --skip-publish goreleaser will attempt a push to GitHub and to your | ||
| docker image repository (docker.io). In this way you can cut a release from your | ||
| laptop if needed. But it is not a good idea and we use drone for that. Normally | ||
| at Packet only drone.io is capable of pushing to Docker Hub and GitHub.* | ||
|
|
||
| We have an utility target that helps you do try a release: | ||
|
|
||
| ``` | ||
| make release | ||
| ``` | ||
|
|
||
| If you know what you are doing and you have the right access to GitHub and | ||
| Docker Hub you can use: | ||
|
|
||
| ``` | ||
| make release/publish | ||
| ``` | ||
| **THIS IS NOT USUALLY REQUIRED AND YOU SHOULD NOT DO IT!** | ||
|
|
||
| ## Drone workflow | ||
|
|
||
| Drone is capable of triggering a command only when a new tag is pushed. | ||
| The command it runs is: `goreleaser release`. | ||
|
|
||
| In order to push artifacts and a release page, drone needs to have access to | ||
| docker image repository and GitHub via access token. | ||
|
|
||
| ## push from master | ||
|
|
||
| We push images to Docker Hub tagged as the git commit sha and latest every time | ||
| master changes (usually when a PR gets merged). | ||
|
|
||
| This process at the moment does not use GoReleaser (it will may use it in the | ||
| future) and you can check how it works look at the `./.github/workflows/ci.yaml` | ||
| file. In practice when master changes an action will build and push the new | ||
| images to Docker Hub. | ||
|
|
||
| ## example of goreleaser output | ||
|
|
||
| This is an example of a valid goreleaser output that I ran locally via `make release` | ||
|
|
||
| ``` | ||
| goreleaser release --rm-dist --snapshot --skip-publish | ||
|
|
||
| • releasing... | ||
| • loading config file file=.goreleaser.yml | ||
| • running before hooks | ||
| • loading environment variables | ||
| • getting and validating git state | ||
| • releasing v0.1.0, commit 1f8e0e31d10a3f4f909fbcd9249fb12b14bf0010 | ||
| • pipe skipped error=disabled during snapshot mode | ||
| • parsing tag | ||
| • setting defaults | ||
| • snapshotting | ||
| • github/gitlab/gitea releases | ||
| • project name | ||
| • building binaries | ||
| • creating source archive | ||
| • archives | ||
| • linux packages | ||
| • snapcraft packages | ||
| • calculating checksums | ||
| • signing artifacts | ||
| • docker images | ||
| • artifactory | ||
| • blobs | ||
| • homebrew tap formula | ||
| • scoop manifests | ||
| • snapshotting | ||
| • checking ./dist | ||
| • --rm-dist is set, cleaning it up | ||
| • writing effective config file | ||
| • writing config=dist/config.yaml | ||
| • generating changelog | ||
| • pipe skipped error=not available for snapshots | ||
| • building binaries | ||
| • building binary=/Users/gianarb/git/cluster-api-provider-packet/dist/capp_l | ||
| inux_arm64/manager | ||
| • building binary=/Users/gianarb/git/cluster-api-provider-packet/dist/capp_d | ||
| arwin_amd64/manager | ||
| • building binary=/Users/gianarb/git/cluster-api-provider-packet/dist/capp_l | ||
| inux_amd64/manager | ||
| • archives | ||
| • creating archive=dist/cluster-api-provider-packet_v0.1.0-next_Linux_x86_64 | ||
| .tar.gz | ||
| • creating archive=dist/cluster-api-provider-packet_v0.1.0-next_Linux_arm64. | ||
| tar.gz | ||
| • creating archive=dist/cluster-api-provider-packet_v0.1.0-next_Darwin_x86_6 | ||
| 4.tar.gz | ||
| • creating source archive | ||
| • pipe skipped error=source pipe is disabled | ||
| • linux packages | ||
| • snapcraft packages | ||
| • calculating checksums | ||
| • checksumming file=cluster-api-provider-packet_v0.1.0-next_Darwin_x86_64.tar.gz | ||
| • checksumming file=cluster-api-provider-packet_v0.1.0-next_Linux_arm64.tar.gz | ||
| • checksumming file=cluster-api-provider-packet_v0.1.0-next_Linux_x86_64.tar.gz | ||
| • signing artifacts | ||
| • docker images | ||
| • building docker image image=packethost/cluster-api-provider-packet:latest-amd64 | ||
| • building docker image image=packethost/cluster-api-provider-packet:latest-arm64 | ||
| • pipe skipped error=docker.skip_push is set | ||
| • publishing | ||
| • blobs | ||
| • pipe skipped error=blobs section is not configured | ||
| • http upload | ||
| • pipe skipped error=uploads section is not configured | ||
| • docker images | ||
| • pipe skipped error=publishing is disabled | ||
| • snapcraft packages | ||
| • pipe skipped error=publishing is disabled | ||
| • github/gitlab/gitea releases | ||
| • pipe skipped error=publishing is disabled | ||
| • homebrew tap formula | ||
| • token type type= | ||
| • scoop manifests | ||
| • pipe skipped error=publishing is disabled | ||
| • release succeeded after 8.29s | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this create the artifacts in the repo root directory? Or in
dist/? I don't see anything in the config that pushes it intodist, but maybe that is the default?Also, how do we distinguish between one build and another, so we don't accidentally put the darwin-amd64 binary in the linux-arm64 image? The current
make buildtarget createsbin/manager-<GOOS>-<GOARCH>. Can we reuse that structure? Or is goreleaser limited from doing that? I imagine not, with those go text templates I see below, but I don't know.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything that gets created by goreleaser is in
distThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And when it builds, how does it differentiate between the multiple binaries? It looks like it names them all
manager, but there are multiple? Does it use themanagertag just as a tag, and automatically append the right arch/etc.? If so, how doesDockerfile.goreleaserget the right file? Or does it actually manipulate the dockerfile before running it?