diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d5bb10..e9217a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,9 @@ name: CI on: push: - branches: [dev] + branches: [dev, main] pull_request: - branches: [dev] + branches: [dev, main] jobs: test: runs-on: ubuntu-latest diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml new file mode 100644 index 0000000..3b108fd --- /dev/null +++ b/.github/workflows/release-publish.yml @@ -0,0 +1,45 @@ +name: Release Publish +on: + push: + tags: ["v*"] +permissions: + contents: write +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + fetch-tags: true + - uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Parse version from tag + id: version + run: | + TAG="${GITHUB_REF#refs/tags/}" + if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: tag '$TAG' is not semver (vX.Y.Z); skipping publish." >&2 + exit 1 + fi + echo "Publishing $TAG" + echo "version=$TAG" >> "$GITHUB_OUTPUT" + + - name: Ensure clean git state for goreleaser + run: | + git clean -ffdx + if [ -n "$(git status --porcelain)" ]; then + echo "Error: working tree is dirty before goreleaser." >&2 + git status --porcelain + exit 1 + fi + + - uses: goreleaser/goreleaser-action@v6 + with: + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 16b872e..785d3a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,17 +3,18 @@ on: workflow_dispatch: inputs: version: - description: 'Version override (e.g. v1.2.3). Leave empty to auto-detect via git-cliff.' + description: "Version override (e.g. v1.2.3). Leave empty to auto-detect via git-cliff." required: false - default: '' + default: "" permissions: contents: write - pull-requests: write jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 + with: + ref: main - uses: actions/setup-go@v6 with: go-version-file: go.mod @@ -25,6 +26,7 @@ jobs: steps: - uses: actions/checkout@v5 with: + ref: main fetch-depth: 0 fetch-tags: true - uses: actions/setup-go@v6 @@ -34,8 +36,14 @@ jobs: - name: Ensure tags are available run: git fetch --force --tags + - name: Configure git identity + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + - name: Determine version via git-cliff id: cliff + continue-on-error: true uses: orhun/git-cliff-action@v4 with: config: cliff.toml @@ -43,8 +51,11 @@ jobs: - name: Resolve release version id: version + env: + CLIFF_OUTPUT: ${{ steps.cliff.outputs.content }} + INPUT_VERSION: ${{ inputs.version }} run: | - DETECTED_VERSION="$(echo "${{ steps.cliff.outputs.content }}" | tr -d '[:space:]')" + DETECTED_VERSION="$(echo "$CLIFF_OUTPUT" | tr -d '[:space:]')" if [ -z "$DETECTED_VERSION" ]; then LAST_TAG="$(git tag --list 'v*' --sort=-version:refname | head -n1)" if [[ -z "$LAST_TAG" ]]; then @@ -62,7 +73,7 @@ jobs: fi fi - VERSION="${{ inputs.version }}" + VERSION="$INPUT_VERSION" if [ -z "$VERSION" ]; then VERSION="$DETECTED_VERSION" fi @@ -70,6 +81,10 @@ jobs: echo "Error: could not determine version. git-cliff returned nothing (no prior tags?). Use the version override input." >&2 exit 1 fi + if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: resolved version '$VERSION' is not semver (vX.Y.Z)." >&2 + exit 1 + fi if git rev-parse -q --verify "refs/tags/$VERSION" >/dev/null; then echo "Error: tag '$VERSION' already exists. Set workflow input 'version' to a new value." >&2 exit 1 @@ -89,58 +104,21 @@ jobs: TAPPER_PLUGIN_VERSION: ${{ steps.version.outputs.version }} run: go run ./cmd/render-integrations - - name: Build release commit on release branch + - name: Commit release on main env: VERSION: ${{ steps.version.outputs.version }} run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - BRANCH="release/$VERSION" - git checkout -b "$BRANCH" git add CHANGELOG.md integrations/rendered if git diff --staged --quiet; then - echo "No release artifacts to commit; release branch tracks dispatch ref" - else - git commit -m "chore: release $VERSION" + echo "Error: no release artifacts staged. Expected CHANGELOG and rendered integrations to change." >&2 + exit 1 fi - git push origin "$BRANCH" + git commit -m "chore: release $VERSION" + git push origin main - - name: Open and merge release PR into main + - name: Tag and push env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSION: ${{ steps.version.outputs.version }} run: | - BRANCH="release/$VERSION" - PR_URL=$(gh pr create \ - --base main \ - --head "$BRANCH" \ - --title "chore: release $VERSION" \ - --body "Automated release PR for $VERSION.") - gh pr merge "$PR_URL" --rebase --delete-branch - - - name: Tag release on main - env: - VERSION: ${{ steps.version.outputs.version }} - run: | - git fetch origin main --tags - git checkout main - git reset --hard origin/main git tag -a "$VERSION" -m "$VERSION" git push origin "refs/tags/$VERSION" - - - name: Ensure clean git state for goreleaser - run: | - git clean -ffdx - if [ -n "$(git status --porcelain)" ]; then - echo "Error: working tree is dirty before goreleaser." >&2 - git status --porcelain - exit 1 - fi - - - uses: goreleaser/goreleaser-action@v6 - with: - version: latest - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}