feat: shll help-dump CLI tree export + shll.ai publish step (#14) #11
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| inputs: | |
| bump: | |
| description: 'Version bump' | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| default: patch | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| # workflow_dispatch must run from main; tag-push is allowed from any ref. | |
| if: github.event_name == 'push' || github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event_name == 'workflow_dispatch' && 'main' || github.ref }} | |
| - name: Create tag (manual dispatch) | |
| if: github.event_name == 'workflow_dispatch' | |
| id: create_tag | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| ./scripts/release.sh "${{ inputs.bump }}" | |
| echo "tag=$(git tag --sort=-v:refname | head -1)" >> "$GITHUB_OUTPUT" | |
| - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | |
| with: | |
| go-version-file: src/go.mod | |
| cache-dependency-path: src/go.sum | |
| - name: Extract version from tag | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| tag="${{ steps.create_tag.outputs.tag }}" | |
| else | |
| tag="${GITHUB_REF#refs/tags/}" | |
| fi | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "version=${tag#v}" >> "$GITHUB_OUTPUT" | |
| - name: Cross-compile | |
| working-directory: src | |
| run: | | |
| mkdir -p ../dist | |
| targets="darwin/arm64 darwin/amd64 linux/arm64 linux/amd64" | |
| for target in $targets; do | |
| os="${target%/*}" | |
| arch="${target#*/}" | |
| output="shll-${os}-${arch}" | |
| echo "Building ${output}..." | |
| mkdir -p "../dist/${output}" | |
| CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" \ | |
| go build -ldflags "-X main.version=${{ steps.version.outputs.tag }}" \ | |
| -o "../dist/${output}/shll" ./cmd/shll | |
| tar -czf "../dist/${output}.tar.gz" -C "../dist/${output}" shll | |
| done | |
| - name: Determine release notes base tag | |
| id: release-base | |
| run: | | |
| tag="${{ steps.version.outputs.tag }}" | |
| # Extract major.minor from current tag (e.g. v0.2.0 → 0.2) | |
| current_minor=$(echo "$tag" | sed 's/^v//' | cut -d. -f1-2) | |
| patch=$(echo "$tag" | sed 's/^v//' | cut -d. -f3) | |
| if [ "$patch" = "0" ]; then | |
| # Minor version bump — find the first tag of the previous minor version | |
| major=$(echo "$current_minor" | cut -d. -f1) | |
| minor=$(echo "$current_minor" | cut -d. -f2) | |
| prev_minor=$((minor - 1)) | |
| prev_prefix="v${major}.${prev_minor}." | |
| # Get the earliest tag matching the previous minor version | |
| base_tag=$(git tag -l "${prev_prefix}*" --sort=version:refname | head -1) | |
| if [ -n "$base_tag" ]; then | |
| echo "base_tag=$base_tag" >> "$GITHUB_OUTPUT" | |
| echo "Using base tag: $base_tag (minor version release)" | |
| else | |
| echo "No previous minor version tags found, using default" | |
| fi | |
| fi | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.tag }} | |
| files: dist/*.tar.gz | |
| generate_release_notes: true | |
| previous_tag: ${{ steps.release-base.outputs.base_tag }} | |
| - name: Build native binary for help-dump | |
| working-directory: src | |
| run: | | |
| CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ | |
| go build -ldflags "-X main.version=${{ steps.version.outputs.tag }}" \ | |
| -o /tmp/shll-native ./cmd/shll | |
| - name: Generate help/shll.json | |
| run: | | |
| mkdir -p help | |
| /tmp/shll-native help-dump > help/shll.json | |
| jq empty help/shll.json # fail the job if it does not parse | |
| # sanity: confirm the version embedded matches the release tag | |
| test "$(jq -r .version help/shll.json)" = "${{ steps.version.outputs.tag }}" | |
| - name: Publish to shll.ai | |
| env: | |
| SHLLAI_TOKEN: ${{ secrets.SHLLAI_TOKEN }} | |
| GH_TOKEN: ${{ secrets.SHLLAI_TOKEN }} | |
| run: | | |
| tag="${{ steps.version.outputs.tag }}" | |
| branch="shll-help-${tag}" | |
| git clone "https://x-access-token:${SHLLAI_TOKEN}@github.com/sahil87/shll.ai.git" /tmp/shll.ai | |
| cp help/shll.json /tmp/shll.ai/help/shll.json | |
| cd /tmp/shll.ai | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git checkout -b "$branch" | |
| git add help/shll.json | |
| # No-op guard: skip cleanly if the reference is byte-identical to main. | |
| if git diff --cached --quiet; then | |
| echo "help/shll.json unchanged — skipping PR" | |
| exit 0 | |
| fi | |
| git commit -m "shll: update help/shll.json for ${tag}" | |
| # Force-push so re-running the same release is idempotent: the branch is | |
| # per-tag ("shll-help-${tag}"), so a re-run would otherwise fail on a | |
| # plain push because the branch already exists on the remote. -f makes | |
| # the branch track this run's commit (and refreshes any open PR for it). | |
| git push -f origin "$branch" | |
| # When there IS a change: open the PR AND drive it to merge (auto-merge), | |
| # never leave it dangling. On a re-run an open PR for this branch may | |
| # already exist — create it only if absent, then enable auto-merge. | |
| pr_url=$(gh pr list --repo sahil87/shll.ai --head "$branch" --state open \ | |
| --json url --jq '.[0].url') | |
| if [ -z "$pr_url" ]; then | |
| pr_url=$(gh pr create --repo sahil87/shll.ai --base main --head "$branch" \ | |
| --title "shll: command reference for ${tag}" \ | |
| --body "Automated CLI help-tree export for shll ${tag}. Generated by shll's release workflow (help-dump).") | |
| fi | |
| gh pr merge --repo sahil87/shll.ai "$pr_url" --auto --squash | |
| - name: Update Homebrew tap | |
| env: | |
| TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| run: | | |
| version="${{ steps.version.outputs.version }}" | |
| sha_darwin_arm64=$(sha256sum dist/shll-darwin-arm64.tar.gz | cut -d' ' -f1) | |
| sha_darwin_amd64=$(sha256sum dist/shll-darwin-amd64.tar.gz | cut -d' ' -f1) | |
| sha_linux_arm64=$(sha256sum dist/shll-linux-arm64.tar.gz | cut -d' ' -f1) | |
| sha_linux_amd64=$(sha256sum dist/shll-linux-amd64.tar.gz | cut -d' ' -f1) | |
| git clone "https://x-access-token:${TAP_TOKEN}@github.com/sahil87/homebrew-tap.git" /tmp/homebrew-tap | |
| sed \ | |
| -e "s/VERSION_PLACEHOLDER/${version}/" \ | |
| -e "s/SHA_DARWIN_ARM64/${sha_darwin_arm64}/" \ | |
| -e "s/SHA_DARWIN_AMD64/${sha_darwin_amd64}/" \ | |
| -e "s/SHA_LINUX_ARM64/${sha_linux_arm64}/" \ | |
| -e "s/SHA_LINUX_AMD64/${sha_linux_amd64}/" \ | |
| .github/formula-template.rb > /tmp/homebrew-tap/Formula/shll.rb | |
| cd /tmp/homebrew-tap | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add Formula/shll.rb | |
| git commit -m "shll v${version}" | |
| git push |