Skip to content
Open
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
102 changes: 102 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Release

on:
push:
branches:
- master
workflow_dispatch:

permissions: {}

concurrency:
group: github-release
cancel-in-progress: false

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
fetch-depth: 0

- name: Set up tools
uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0

- name: Resolve binding version
id: version
run: |
set -euo pipefail
version=$(sed -n 's/^PKG_VERSION=\${1:-"\([0-9]\+\.[0-9]\+\.[0-9]\+\)"}.*/\1/p' bin/generate | head -1 || true)
if [ -z "$version" ]; then
echo "Could not parse PKG_VERSION from bin/generate" >&2
exit 1
fi
tag="v${version}"
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "tag=${tag}" >> "$GITHUB_OUTPUT"

- name: Skip if this version is already released
id: existing
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.version.outputs.tag }}
run: |
set -euo pipefail
if gh release view "$TAG" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "GitHub release ${TAG} already exists; nothing to do."
exit 0
fi
if gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${TAG}" >/dev/null 2>&1; then
echo "exists=tag-only" >> "$GITHUB_OUTPUT"
echo "Tag ${TAG} exists without a GitHub release; will attach one."
exit 0
fi
echo "exists=false" >> "$GITHUB_OUTPUT"

- name: Check out existing tag
if: steps.existing.outputs.exists == 'tag-only'
env:
TAG: ${{ steps.version.outputs.tag }}
run: |
set -euo pipefail
git fetch --no-tags origin "refs/tags/${TAG}:refs/tags/${TAG}" || true
git checkout --detach "refs/tags/${TAG}"

- name: Test
if: steps.existing.outputs.exists != 'true'
run: go test -v ./...
Comment thread
BartoszBlizniak marked this conversation as resolved.

- name: Create GitHub release
if: steps.existing.outputs.exists != 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.version.outputs.tag }}
VERSION: ${{ steps.version.outputs.version }}
EXISTS: ${{ steps.existing.outputs.exists }}
run: |
set -euo pipefail
api_version=$(grep -m1 -E '^\- API version:' README.md | awk '{print $4}' || true)
notes="Go API bindings ${TAG}."
notes="${notes}"$'\n\n'"- Binding version: \`${VERSION}\`"
if [ -n "${api_version:-}" ]; then
notes="${notes}"$'\n'"- Cloudsmith API version: \`${api_version}\`"
fi

extra=()
if [ "$EXISTS" = "tag-only" ]; then
extra+=(--verify-tag)
else
extra+=(--target "${GITHUB_SHA}")
fi

gh release create "$TAG" \
--title "$TAG" \
--notes "$notes" \
--generate-notes \
"${extra[@]}"
9 changes: 6 additions & 3 deletions CONTRIBUTING.MD
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,26 @@ Convenience tasks:

* Update `PKG_VERSION` in `bin/generate`
* Run `bin/generate` (or `mise run generate`) to generate bindings
* Create a PR specifing API and binding version
* Create git tag and release in github
* Create a PR specifying API and binding version
* After merge, the **Release** workflow tags `v$PKG_VERSION` and creates the GitHub release when that tag does not already exist

### Automated approach (local)

* Run `./scripts/update-bindings.sh` (or `mise run update-bindings`) to automatically update the bindings.
* This will then provide you with the URL for the PR to release the updated bindings.
* Preferred usage: `./scripts/update-bindings.sh`
* For full options and usage examples, run: `./scripts/update-bindings.sh --help`
* After PR is merged, follow the displayed instructions to create the git tag and GitHub release.
* After the PR is merged, the **Release** workflow creates the git tag and GitHub release.

### Automated approach (CI)

* The **Update API bindings** GitHub Actions workflow regenerates the bindings
and opens a PR — on demand (`workflow_dispatch`, optionally with a specific
version) or daily on a schedule. It opens a PR only when the regenerated
bindings actually change, and closes any superseded automated PRs first.
* The **Release** workflow runs on every push to `master`. It reads
`PKG_VERSION` from `bin/generate`, runs tests, and creates `v$PKG_VERSION`
plus a GitHub release when that version is not already published.

## Contributor License Agreement

Expand Down
20 changes: 4 additions & 16 deletions scripts/update-bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -205,22 +205,10 @@ Cloudsmith API version: $api_version
create_tag_and_release_instructions() {
local version="$1"
local tag_name="v${version}"

echo ""
log_info "After the PR is merged, create a git tag and release:"
echo ""
echo "1. Switch to master and pull latest changes:"
echo " git checkout master"
echo " git pull"
echo ""
echo "2. Create and push the tag:"
echo " git tag -a $tag_name -m \"Release version $version\""
echo " git push origin $tag_name"

echo ""
echo "3. Go to GitHub releases page and create a new release:"
echo " - Select tag: $tag_name"
echo " - Release title: Release $version"
echo " - Add release notes as needed"
log_info "After the PR is merged, the Release workflow publishes ${tag_name}."
echo "If that run is skipped or fails, re-run the Release workflow from Actions."
echo ""
}

Expand All @@ -244,7 +232,7 @@ usage() {
echo " * Auto-increment the patch version (e.g. 1.2.3 -> 1.2.4)"
echo " * Auto-fetch the latest Cloudsmith API version"
echo " - Use -v only for larger version increments (minor/major bumps)"
echo " - After PR is merged, you'll need to create a git tag and GitHub release"
echo " - After the PR is merged, the Release workflow creates the git tag and GitHub release"
}

main() {
Expand Down