Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ jobs:
publish_release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
packages: write
steps:
- name: Checkout head
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
Expand All @@ -32,6 +36,8 @@ jobs:
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version-file: 'go.mod'
- name: Set up cosign
uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
- name: Get tag version
id: git
run: echo "tag_version=$(make version)" >> "$GITHUB_OUTPUT"
Expand Down
20 changes: 20 additions & 0 deletions .goreleaser.yaml
Copy link
Copy Markdown
Member Author

@scop scop Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A problem with doing the signatures this way in goreleaser is that when cosign is not running within the GH builder context, it won't be using the GH OIDC provider, and thus in local goreleaser runs it resorts to prompting the user to access signstore using their browser. And it appears that conditionalizing the signing is a goreleaser pro feature.
(BTW the prompt will be only shown in the goreleaser output when running with --verbose (or alternatively we could add output: true to the goreleaser *signs config)).

In that sense, it would perhaps be better to implement the signing in GH workflows proper, rather than in goreleaser (even though it's quite convenient that way).

Setting draft until we've settled on the approach on this.

Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ archives:
checksum:
name_template: 'checksums.txt'

signs:
- certificate: ${artifact}-keyless.pem
signature: ${artifact}-keyless.sig
cmd: cosign
args:
- sign-blob
- --b64=false
- --output-certificate=${certificate}
- --output-signature=${signature}
- --yes
- ${artifact}
artifacts: checksum

snapshot:
name_template: "{{ .Tag }}-next"

Expand Down Expand Up @@ -172,6 +185,13 @@ dockers:
- "--label=org.opencontainers.image.version={{.Version}}"
- "--label=org.opencontainers.image.source=https://github.com/UpCloudLtd/upcloud-cli.git"

docker_signs:
- args:
- sign
- --yes
- ${artifact}@${digest}
artifacts: all

release:
# Repo in which the release will be created.
# Default is extracted from the origin remote URL or empty if its private hosted.
Expand Down
2 changes: 1 addition & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
- sets the version based on the tag
- creates a draft release to GitHub
- populates the release notes from `CHANGELOG.md` with `make release-notes`
- builds and uploads binaries & SHA sum for given release
- builds, uploads, and signs assets for given release
5. Verify that [release notes](https://github.com/UpCloudLtd/upcloud-cli/releases) are in line with `CHANGELOG.MD`
6. Publish the drafted release
39 changes: 39 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,45 @@ After installing `upctl`, you can run `upctl version` command to verify that the
upctl version
```

### Verify assets

Project release packages' SHA-256 checksums are available in the project releases,
files `checksums.txt`. They can be checked for example with:

```sh
# make sure at least one downloaded package and checksums.txt are in the current directory
sha256sum -c --ignore-missing checksums.txt
```

Project release checksum files and Docker images are signed using the
[Sigstore framework](https://www.sigstore.dev), and can be verified with
[cosign](https://docs.sigstore.dev/cosign/).

For example, to verify package checksums file for a release:

```sh
project_url=https://github.com/UpCloudLtd/upcloud-cli
release=vX.Y.Z
cosign verify-blob \
--certificate-identity ${project_url}/.github/workflows/publish.yml@refs/tags/${release} \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate ${project_url}/releases/download/${release}/checksums.txt-keyless.pem \
--signature ${project_url}/releases/download/${release}/checksums.txt-keyless.sig \
${project_url}/releases/download/${release}/checksums.txt
```

And to verify the Docker image for a release:

```sh
project=UpCloudLtd/upcloud-cli
release=vX.Y.Z
cosign verify \
ghcr.io/${project}:${release} \
--certificate-identity https://github.com/${project}/.github/workflows/publish.yml@refs/tags/${release} \
--certificate-oidc-issuer https://token.actions.githubusercontent.com |
jq .
```

### Configure shell completions

`upctl` provides shell completions for multiple shells. Run `upctl completion --help` to list the supported shells.
Expand Down