From f9f5e6017907ec75ac673e2f69c74209f0e123bd Mon Sep 17 00:00:00 2001 From: Callum Evans Date: Sun, 22 Mar 2026 21:59:01 +0000 Subject: [PATCH 1/3] Bump goreleaser --- .github/workflows/go-releaser-checks.yml | 6 +++--- .github/workflows/go-releaser-release.yml | 2 +- .goreleaser.yaml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/go-releaser-checks.yml b/.github/workflows/go-releaser-checks.yml index 999e178..4cb2409 100644 --- a/.github/workflows/go-releaser-checks.yml +++ b/.github/workflows/go-releaser-checks.yml @@ -17,16 +17,16 @@ jobs: fetch-depth: 0 - name: Check GoReleaser - uses: goreleaser/goreleaser-action@v6 + uses: goreleaser/goreleaser-action@v7 with: distribution: goreleaser version: '~> v2' args: check - name: GoReleaser dry-run - uses: goreleaser/goreleaser-action@v6 + uses: goreleaser/goreleaser-action@v7 with: distribution: goreleaser version: '~> v2' args: build --snapshot - \ No newline at end of file + diff --git a/.github/workflows/go-releaser-release.yml b/.github/workflows/go-releaser-release.yml index 298bc25..8cc6fda 100644 --- a/.github/workflows/go-releaser-release.yml +++ b/.github/workflows/go-releaser-release.yml @@ -33,7 +33,7 @@ jobs: passphrase: ${{ secrets.GPG_PASSPHRASE }} - name: GoReleaser release - uses: goreleaser/goreleaser-action@v6 + uses: goreleaser/goreleaser-action@v7 with: distribution: goreleaser version: '~> v2' diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 1f7550f..2da7e9e 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -60,7 +60,7 @@ homebrew_casks: - name: terrable url: template: "https://github.com/terrable-dev/terrable/releases/download/{{ .Tag }}/{{ .ArtifactName }}" - directory: Formula + directory: Casks commit_author: name: goreleaserbot email: bot@goreleaser.com @@ -70,4 +70,4 @@ homebrew_casks: repository: owner: terrable-dev name: homebrew-tap - branch: main + branch: "{{ envOrDefault \"HOMEBREW_TAP_BRANCH\" \"main\" }}" From da2e7b75974e4fdbe75612d4e5cd9bcbe550ec29 Mon Sep 17 00:00:00 2001 From: Callum Evans Date: Sun, 22 Mar 2026 22:20:51 +0000 Subject: [PATCH 2/3] .. --- .github/workflows/go-releaser-checks.yml | 14 ++++ .github/workflows/go-releaser-release.yml | 41 +++++++++++- .github/workflows/publish-new-version-tag.yml | 21 +++++- .../workflows/publish-preview-version-tag.yml | 65 +++++++++++++++++++ .goreleaser.yaml | 6 ++ main.go | 2 +- terrable_build.go | 15 +++++ 7 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/publish-preview-version-tag.yml diff --git a/.github/workflows/go-releaser-checks.yml b/.github/workflows/go-releaser-checks.yml index 4cb2409..9f8fc22 100644 --- a/.github/workflows/go-releaser-checks.yml +++ b/.github/workflows/go-releaser-checks.yml @@ -16,12 +16,24 @@ jobs: with: fetch-depth: 0 + - name: Read version from file + id: version + run: | + VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) + if [[ -z "$VERSION" ]]; then + echo "Failed to read version from terrable_build" >&2 + exit 1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + - name: Check GoReleaser uses: goreleaser/goreleaser-action@v7 with: distribution: goreleaser version: '~> v2' args: check + env: + TERRABLE_BUILD_VERSION: ${{ steps.version.outputs.version }} - name: GoReleaser dry-run uses: goreleaser/goreleaser-action@v7 @@ -29,4 +41,6 @@ jobs: distribution: goreleaser version: '~> v2' args: build --snapshot + env: + TERRABLE_BUILD_VERSION: ${{ steps.version.outputs.version }} diff --git a/.github/workflows/go-releaser-release.yml b/.github/workflows/go-releaser-release.yml index 8cc6fda..79f3aff 100644 --- a/.github/workflows/go-releaser-release.yml +++ b/.github/workflows/go-releaser-release.yml @@ -5,6 +5,17 @@ on: tags: - 'v*' workflow_dispatch: + inputs: + publish: + description: Publish artifacts. Requires running from a tag. + required: true + type: boolean + default: false + homebrew_tap_branch: + description: Homebrew tap branch to update for published releases. + required: false + type: string + default: preview jobs: go-releaser-release: @@ -12,12 +23,39 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + env: + HOMEBREW_TAP_BRANCH: ${{ github.event_name == 'workflow_dispatch' && inputs.homebrew_tap_branch || (github.ref_type == 'tag' && contains(github.ref_name, '-') && 'preview' || 'main') }} steps: - name: Check out repository uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Read version from file + id: version + run: | + VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) + if [[ -z "$VERSION" ]]; then + echo "Failed to read version from terrable_build" >&2 + exit 1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Select GoReleaser mode + id: goreleaser_mode + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.publish }}" != "true" ]]; then + echo "args=release --snapshot --clean" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "args=release --clean" >> "$GITHUB_OUTPUT" + + - name: Ensure published releases run from a tag + if: ${{ steps.goreleaser_mode.outputs.args == 'release --clean' && github.ref_type != 'tag' }} + run: | + echo "Published releases must run from a tag. Use workflow_dispatch with publish=false for a branch snapshot build." >&2 + exit 1 + - name: Generate GitHub App token id: generate_token uses: tibdex/github-app-token@v2 @@ -37,7 +75,8 @@ jobs: with: distribution: goreleaser version: '~> v2' - args: release --clean + args: ${{ steps.goreleaser_mode.outputs.args }} env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} + TERRABLE_BUILD_VERSION: ${{ steps.version.outputs.version }} diff --git a/.github/workflows/publish-new-version-tag.yml b/.github/workflows/publish-new-version-tag.yml index 66eeb95..7d09aa4 100644 --- a/.github/workflows/publish-new-version-tag.yml +++ b/.github/workflows/publish-new-version-tag.yml @@ -30,10 +30,25 @@ jobs: - name: Read version from file id: version run: | - VERSION=$(grep -oP 'version\s*=\s*\K[\d.]+' terrable_build) - echo "::set-output name=version::$VERSION" + VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) + if [[ -z "$VERSION" ]]; then + echo "Failed to read version from terrable_build" >&2 + exit 1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Check whether tag already exists + id: tag + run: | + TAG="v${{ steps.version.outputs.version }}" + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "exists=false" >> "$GITHUB_OUTPUT" - name: Create and push tag + if: ${{ steps.tag.outputs.exists != 'true' }} env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} run: | @@ -41,4 +56,4 @@ jobs: git config user.email bot@goreleaser.com git tag -a v${{ steps.version.outputs.version }} -m "Version ${{ steps.version.outputs.version }}" git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git v${{ steps.version.outputs.version }} - \ No newline at end of file + diff --git a/.github/workflows/publish-preview-version-tag.yml b/.github/workflows/publish-preview-version-tag.yml new file mode 100644 index 0000000..0087c6d --- /dev/null +++ b/.github/workflows/publish-preview-version-tag.yml @@ -0,0 +1,65 @@ +name: Publish Preview Version Tag + +on: + workflow_dispatch: + inputs: + suffix: + description: Optional prerelease suffix like rc.1 or preview.42. + required: false + type: string + +jobs: + publish-preview-version-tag: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Generate GitHub App token + id: generate_token + uses: tibdex/github-app-token@v2 + with: + app_id: ${{ secrets.ACTIONS_APP_ID }} + private_key: ${{ secrets.ACTIONS_APP_PRIVATE_KEY }} + + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ steps.generate_token.outputs.token }} + + - name: Read version from file + id: version + run: | + VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) + if [[ -z "$VERSION" ]]; then + echo "Failed to read version from terrable_build" >&2 + exit 1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Build prerelease tag name + id: tag + run: | + SUFFIX="${{ inputs.suffix }}" + if [[ -z "$SUFFIX" ]]; then + SUFFIX="preview.${GITHUB_RUN_NUMBER}" + fi + TAG="v${{ steps.version.outputs.version }}-${SUFFIX}" + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + - name: Ensure preview tag does not already exist + run: | + if git rev-parse "${{ steps.tag.outputs.tag }}" >/dev/null 2>&1; then + echo "Tag ${{ steps.tag.outputs.tag }} already exists" >&2 + exit 1 + fi + + - name: Create and push preview tag + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + run: | + git config user.name goreleaserbot + git config user.email bot@goreleaser.com + git tag -a "${{ steps.tag.outputs.tag }}" -m "Preview ${{ steps.tag.outputs.tag }}" + git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "${{ steps.tag.outputs.tag }}" diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2da7e9e..3978c51 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -19,6 +19,12 @@ signs: checksum: name_template: "checksums.txt" +snapshot: + version_template: "{{ .Env.TERRABLE_BUILD_VERSION }}-snapshot-{{ .ShortCommit }}" + +release: + prerelease: auto + archives: - formats: [ tar.gz ] name_template: >- diff --git a/main.go b/main.go index 1e1f246..7483906 100644 --- a/main.go +++ b/main.go @@ -12,7 +12,7 @@ import ( func main() { app := &cli.App{ Name: "terrable", - Version: buildInfo()["version"], + Version: buildVersion(), Commands: []*cli.Command{ { diff --git a/terrable_build.go b/terrable_build.go index e4e325d..522c739 100644 --- a/terrable_build.go +++ b/terrable_build.go @@ -5,6 +5,9 @@ import ( "strings" ) +// These are set by GoReleaser via ldflags on tagged and snapshot builds. +var version string + //go:embed terrable_build var configFile string @@ -31,3 +34,15 @@ func buildInfo() map[string]string { return config } + +func buildVersion() string { + if version != "" { + return version + } + + if fileVersion := buildInfo()["version"]; fileVersion != "" { + return fileVersion + } + + return "dev" +} From 9be1fe21217a2f56f72bf2d320bbb48229a57d60 Mon Sep 17 00:00:00 2001 From: Callum Evans Date: Sun, 22 Mar 2026 22:39:30 +0000 Subject: [PATCH 3/3] .. --- .github/workflows/go-releaser-checks.yml | 21 +++-- .github/workflows/go-releaser-release.yml | 35 ++------- .github/workflows/publish-new-version-tag.yml | 36 +++++---- .../workflows/publish-preview-version-tag.yml | 73 ++++++++++-------- .goreleaser.yaml | 3 +- scripts/read_build_info.sh | 49 ++++++++++++ terrable_build.go | 22 +++++- terrable_build_test.go | 76 +++++++++++++++++++ 8 files changed, 230 insertions(+), 85 deletions(-) create mode 100755 scripts/read_build_info.sh create mode 100644 terrable_build_test.go diff --git a/.github/workflows/go-releaser-checks.yml b/.github/workflows/go-releaser-checks.yml index 9f8fc22..eb513c6 100644 --- a/.github/workflows/go-releaser-checks.yml +++ b/.github/workflows/go-releaser-checks.yml @@ -16,15 +16,18 @@ jobs: with: fetch-depth: 0 - - name: Read version from file - id: version + - name: Read build metadata + id: build_info run: | - VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) - if [[ -z "$VERSION" ]]; then - echo "Failed to read version from terrable_build" >&2 + bash ./scripts/read_build_info.sh >> "$GITHUB_OUTPUT" + + - name: Reject preview-tag in pull requests to main + if: ${{ github.event_name == 'pull_request' && github.base_ref == 'main' }} + run: | + if [[ -n "${{ steps.build_info.outputs.preview_tag }}" ]]; then + echo "preview-tag must be empty for pull requests targeting main." >&2 exit 1 fi - echo "version=$VERSION" >> "$GITHUB_OUTPUT" - name: Check GoReleaser uses: goreleaser/goreleaser-action@v7 @@ -33,7 +36,8 @@ jobs: version: '~> v2' args: check env: - TERRABLE_BUILD_VERSION: ${{ steps.version.outputs.version }} + TERRABLE_BUILD_VERSION: ${{ steps.build_info.outputs.version }} + TERRABLE_BUILD_PREVIEW_TAG: ${{ steps.build_info.outputs.preview_tag }} - name: GoReleaser dry-run uses: goreleaser/goreleaser-action@v7 @@ -42,5 +46,6 @@ jobs: version: '~> v2' args: build --snapshot env: - TERRABLE_BUILD_VERSION: ${{ steps.version.outputs.version }} + TERRABLE_BUILD_VERSION: ${{ steps.build_info.outputs.version }} + TERRABLE_BUILD_PREVIEW_TAG: ${{ steps.build_info.outputs.preview_tag }} diff --git a/.github/workflows/go-releaser-release.yml b/.github/workflows/go-releaser-release.yml index 79f3aff..9e896e8 100644 --- a/.github/workflows/go-releaser-release.yml +++ b/.github/workflows/go-releaser-release.yml @@ -5,17 +5,6 @@ on: tags: - 'v*' workflow_dispatch: - inputs: - publish: - description: Publish artifacts. Requires running from a tag. - required: true - type: boolean - default: false - homebrew_tap_branch: - description: Homebrew tap branch to update for published releases. - required: false - type: string - default: preview jobs: go-releaser-release: @@ -24,38 +13,27 @@ jobs: permissions: contents: write env: - HOMEBREW_TAP_BRANCH: ${{ github.event_name == 'workflow_dispatch' && inputs.homebrew_tap_branch || (github.ref_type == 'tag' && contains(github.ref_name, '-') && 'preview' || 'main') }} + HOMEBREW_TAP_BRANCH: ${{ github.ref_type == 'tag' && contains(github.ref_name, '-') && 'preview' || 'main' }} steps: - name: Check out repository uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Read version from file - id: version + - name: Read build metadata + id: build_info run: | - VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) - if [[ -z "$VERSION" ]]; then - echo "Failed to read version from terrable_build" >&2 - exit 1 - fi - echo "version=$VERSION" >> "$GITHUB_OUTPUT" + bash ./scripts/read_build_info.sh >> "$GITHUB_OUTPUT" - name: Select GoReleaser mode id: goreleaser_mode run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.publish }}" != "true" ]]; then + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then echo "args=release --snapshot --clean" >> "$GITHUB_OUTPUT" exit 0 fi echo "args=release --clean" >> "$GITHUB_OUTPUT" - - name: Ensure published releases run from a tag - if: ${{ steps.goreleaser_mode.outputs.args == 'release --clean' && github.ref_type != 'tag' }} - run: | - echo "Published releases must run from a tag. Use workflow_dispatch with publish=false for a branch snapshot build." >&2 - exit 1 - - name: Generate GitHub App token id: generate_token uses: tibdex/github-app-token@v2 @@ -79,4 +57,5 @@ jobs: env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} - TERRABLE_BUILD_VERSION: ${{ steps.version.outputs.version }} + TERRABLE_BUILD_VERSION: ${{ steps.build_info.outputs.version }} + TERRABLE_BUILD_PREVIEW_TAG: ${{ steps.build_info.outputs.preview_tag }} diff --git a/.github/workflows/publish-new-version-tag.yml b/.github/workflows/publish-new-version-tag.yml index 7d09aa4..8189715 100644 --- a/.github/workflows/publish-new-version-tag.yml +++ b/.github/workflows/publish-new-version-tag.yml @@ -27,33 +27,39 @@ jobs: fetch-depth: 0 token: ${{ steps.generate_token.outputs.token }} - - name: Read version from file - id: version + - name: Read build metadata + id: build_info run: | - VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) - if [[ -z "$VERSION" ]]; then - echo "Failed to read version from terrable_build" >&2 + bash ./scripts/read_build_info.sh >> "$GITHUB_OUTPUT" + + - name: Reject preview-tag on main + run: | + if [[ -n "${{ steps.build_info.outputs.preview_tag }}" ]]; then + echo "preview-tag must be empty on main releases." >&2 exit 1 fi - echo "version=$VERSION" >> "$GITHUB_OUTPUT" - - name: Check whether tag already exists + - name: Check whether stable tag already exists id: tag run: | - TAG="v${{ steps.version.outputs.version }}" + TAG="v${{ steps.build_info.outputs.version }}" if git rev-parse "$TAG" >/dev/null 2>&1; then - echo "exists=true" >> "$GITHUB_OUTPUT" - exit 0 + EXISTING_COMMIT=$(git rev-list -n1 "$TAG") + if [[ "$EXISTING_COMMIT" == "$GITHUB_SHA" ]]; then + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "Tag $TAG already exists at $EXISTING_COMMIT. Bump terrable_build version before releasing again." >&2 + exit 1 fi - echo "exists=false" >> "$GITHUB_OUTPUT" + echo "skip=false" >> "$GITHUB_OUTPUT" - name: Create and push tag - if: ${{ steps.tag.outputs.exists != 'true' }} + if: ${{ steps.tag.outputs.skip != 'true' }} env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} run: | git config user.name goreleaserbot git config user.email bot@goreleaser.com - git tag -a v${{ steps.version.outputs.version }} -m "Version ${{ steps.version.outputs.version }}" - git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git v${{ steps.version.outputs.version }} - + git tag -a v${{ steps.build_info.outputs.version }} -m "Version ${{ steps.build_info.outputs.version }}" + git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git v${{ steps.build_info.outputs.version }} diff --git a/.github/workflows/publish-preview-version-tag.yml b/.github/workflows/publish-preview-version-tag.yml index 0087c6d..76e1cdf 100644 --- a/.github/workflows/publish-preview-version-tag.yml +++ b/.github/workflows/publish-preview-version-tag.yml @@ -1,12 +1,11 @@ name: Publish Preview Version Tag on: - workflow_dispatch: - inputs: - suffix: - description: Optional prerelease suffix like rc.1 or preview.42. - required: false - type: string + push: + branches-ignore: + - main + paths: + - 'terrable_build' jobs: publish-preview-version-tag: @@ -15,51 +14,63 @@ jobs: contents: write steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Read build metadata + id: build_info + run: | + bash ./scripts/read_build_info.sh >> "$GITHUB_OUTPUT" + + - name: Decide whether this branch should publish a preview + id: preview + run: | + if [[ -z "${{ steps.build_info.outputs.preview_tag }}" ]]; then + echo "publish=false" >> "$GITHUB_OUTPUT" + echo "No preview-tag set in terrable_build, so no preview tag will be published." + exit 0 + fi + echo "publish=true" >> "$GITHUB_OUTPUT" + - name: Generate GitHub App token + if: ${{ steps.preview.outputs.publish == 'true' }} id: generate_token uses: tibdex/github-app-token@v2 with: app_id: ${{ secrets.ACTIONS_APP_ID }} private_key: ${{ secrets.ACTIONS_APP_PRIVATE_KEY }} - - name: Check out repository + - name: Check out repository with app token + if: ${{ steps.preview.outputs.publish == 'true' }} uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ steps.generate_token.outputs.token }} - - name: Read version from file - id: version - run: | - VERSION=$(sed -nE 's/^[[:space:]]*version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)[[:space:]]*$/\1/p' terrable_build | head -n1) - if [[ -z "$VERSION" ]]; then - echo "Failed to read version from terrable_build" >&2 - exit 1 - fi - echo "version=$VERSION" >> "$GITHUB_OUTPUT" - - - name: Build prerelease tag name + - name: Check whether preview tag already exists + if: ${{ steps.preview.outputs.publish == 'true' }} id: tag run: | - SUFFIX="${{ inputs.suffix }}" - if [[ -z "$SUFFIX" ]]; then - SUFFIX="preview.${GITHUB_RUN_NUMBER}" - fi - TAG="v${{ steps.version.outputs.version }}-${SUFFIX}" - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - - - name: Ensure preview tag does not already exist - run: | - if git rev-parse "${{ steps.tag.outputs.tag }}" >/dev/null 2>&1; then - echo "Tag ${{ steps.tag.outputs.tag }} already exists" >&2 + TAG="v${{ steps.build_info.outputs.version }}-${{ steps.build_info.outputs.preview_tag }}" + echo "name=$TAG" >> "$GITHUB_OUTPUT" + if git rev-parse "$TAG" >/dev/null 2>&1; then + EXISTING_COMMIT=$(git rev-list -n1 "$TAG") + if [[ "$EXISTING_COMMIT" == "$GITHUB_SHA" ]]; then + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "Tag $TAG already exists at $EXISTING_COMMIT. Bump preview-tag in terrable_build before publishing a new preview." >&2 exit 1 fi + echo "skip=false" >> "$GITHUB_OUTPUT" - name: Create and push preview tag + if: ${{ steps.preview.outputs.publish == 'true' && steps.tag.outputs.skip != 'true' }} env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} run: | git config user.name goreleaserbot git config user.email bot@goreleaser.com - git tag -a "${{ steps.tag.outputs.tag }}" -m "Preview ${{ steps.tag.outputs.tag }}" - git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "${{ steps.tag.outputs.tag }}" + git tag -a "${{ steps.tag.outputs.name }}" -m "Preview ${{ steps.tag.outputs.name }}" + git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "${{ steps.tag.outputs.name }}" diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 3978c51..48b1c0a 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -20,7 +20,7 @@ checksum: name_template: "checksums.txt" snapshot: - version_template: "{{ .Env.TERRABLE_BUILD_VERSION }}-snapshot-{{ .ShortCommit }}" + version_template: "{{ .Env.TERRABLE_BUILD_VERSION }}{{ if .Env.TERRABLE_BUILD_PREVIEW_TAG }}-{{ .Env.TERRABLE_BUILD_PREVIEW_TAG }}{{ end }}-snapshot-{{ .ShortCommit }}" release: prerelease: auto @@ -51,6 +51,7 @@ scoops: - name: terrable url_template: "https://github.com/terrable-dev/terrable/releases/download/{{ .Tag }}/{{ .ArtifactName }}" directory: bucket + skip_upload: auto commit_author: name: goreleaserbot email: bot@goreleaser.com diff --git a/scripts/read_build_info.sh b/scripts/read_build_info.sh new file mode 100755 index 0000000..41c359a --- /dev/null +++ b/scripts/read_build_info.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +set -euo pipefail + +file="${1:-terrable_build}" + +read_key() { + local key="$1" + + awk -F= -v key="$key" ' + $0 ~ /^[[:space:]]*#/ || $0 ~ /^[[:space:]]*$/ { next } + { + current_key = $1 + sub(/^[[:space:]]+/, "", current_key) + sub(/[[:space:]]+$/, "", current_key) + + if (current_key != key) { + next + } + + value = substr($0, index($0, "=") + 1) + sub(/^[[:space:]]+/, "", value) + sub(/[[:space:]]+$/, "", value) + + if ((value ~ /^".*"$/) || (value ~ /^'\''.*'\''$/)) { + value = substr(value, 2, length(value) - 2) + } + + print value + exit + } + ' "$file" +} + +version="$(read_key version)" +preview_tag="$(read_key preview-tag)" + +if [[ -z "$version" || ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "terrable_build must include version = X.Y.Z" >&2 + exit 1 +fi + +if [[ -n "$preview_tag" && ! "$preview_tag" =~ ^[0-9A-Za-z][0-9A-Za-z.-]*$ ]]; then + echo "terrable_build preview-tag must match ^[0-9A-Za-z][0-9A-Za-z.-]*$" >&2 + exit 1 +fi + +echo "version=$version" +echo "preview_tag=$preview_tag" diff --git a/terrable_build.go b/terrable_build.go index 522c739..c3b5b67 100644 --- a/terrable_build.go +++ b/terrable_build.go @@ -27,7 +27,7 @@ func buildInfo() map[string]string { if len(parts) == 2 { key := strings.TrimSpace(parts[0]) - value := strings.TrimSpace(parts[1]) + value := normalizeBuildValue(parts[1]) config[key] = value } } @@ -40,9 +40,27 @@ func buildVersion() string { return version } - if fileVersion := buildInfo()["version"]; fileVersion != "" { + info := buildInfo() + + if fileVersion := info["version"]; fileVersion != "" { + if previewTag := info["preview-tag"]; previewTag != "" { + return fileVersion + "-" + previewTag + } + return fileVersion } return "dev" } + +func normalizeBuildValue(value string) string { + value = strings.TrimSpace(value) + + if len(value) >= 2 { + if (value[0] == '"' && value[len(value)-1] == '"') || (value[0] == '\'' && value[len(value)-1] == '\'') { + return value[1 : len(value)-1] + } + } + + return value +} diff --git a/terrable_build_test.go b/terrable_build_test.go new file mode 100644 index 0000000..72e6702 --- /dev/null +++ b/terrable_build_test.go @@ -0,0 +1,76 @@ +package main + +import "testing" + +func TestBuildInfoNormalizesQuotedValues(t *testing.T) { + originalConfig := configFile + originalVersion := version + t.Cleanup(func() { + configFile = originalConfig + version = originalVersion + }) + + configFile = ` +version = "1.2.3" +preview-tag = 'rc.1' +` + version = "" + + info := buildInfo() + + if got := info["version"]; got != "1.2.3" { + t.Fatalf("expected version 1.2.3, got %q", got) + } + + if got := info["preview-tag"]; got != "rc.1" { + t.Fatalf("expected preview-tag rc.1, got %q", got) + } +} + +func TestBuildVersionPrefersInjectedVersion(t *testing.T) { + originalConfig := configFile + originalVersion := version + t.Cleanup(func() { + configFile = originalConfig + version = originalVersion + }) + + configFile = "version = 1.2.3\npreview-tag = rc.1\n" + version = "9.9.9" + + if got := buildVersion(); got != "9.9.9" { + t.Fatalf("expected injected version, got %q", got) + } +} + +func TestBuildVersionUsesPreviewTagFromBuildInfo(t *testing.T) { + originalConfig := configFile + originalVersion := version + t.Cleanup(func() { + configFile = originalConfig + version = originalVersion + }) + + configFile = "version = 1.2.3\npreview-tag = preview.4\n" + version = "" + + if got := buildVersion(); got != "1.2.3-preview.4" { + t.Fatalf("expected preview build version, got %q", got) + } +} + +func TestBuildVersionDefaultsToDev(t *testing.T) { + originalConfig := configFile + originalVersion := version + t.Cleanup(func() { + configFile = originalConfig + version = originalVersion + }) + + configFile = "" + version = "" + + if got := buildVersion(); got != "dev" { + t.Fatalf("expected dev fallback, got %q", got) + } +}