Skip to content

feat: shll help-dump CLI tree export + shll.ai publish step (#14) #11

feat: shll help-dump CLI tree export + shll.ai publish step (#14)

feat: shll help-dump CLI tree export + shll.ai publish step (#14) #11

Workflow file for this run

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