rework CI a bit #8
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: SDK tag | |
| # Auto-pins the plugin ABI contract: on every push to main, if src/sdk/sdk_version.zig's | |
| # `sdk_version` doesn't already have a matching `sdk-v<major>.<minor>.<patch>` tag, create and | |
| # push one at this commit. Then pack the plugin-facing `sdk/` package (plus vendored | |
| # `src/core` + `src/sdk`) into `fizzy-sdk-v*.tar.gz` and publish it as a GitHub release asset | |
| # on that tag — the URL third-party plugins pin (docs/PLUGINS.md §2.3). The git archive of the | |
| # monorepo is *not* a valid plugin pin: its root zon owns Velopack. | |
| # | |
| # `sdk-v*` is a separate namespace from the app's `v*` release tags (release.yml triggers on | |
| # `tags: ["v*"]`, a glob on the ref's start — `sdk-v...` doesn't start with `v`, so this can | |
| # never fire the app build/package pipeline). | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "src/sdk/sdk_version.zig" | |
| - "src/sdk/version.zig" | |
| - "sdk/sdk_version.zig" | |
| - "sdk/**" | |
| - "scripts/pack-sdk.sh" | |
| - ".github/workflows/sdk-tag.yml" | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }} | |
| cancel-in-progress: false | |
| jobs: | |
| tag-and-release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Compute sdk_version | |
| id: ver | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| block=$(awk '/pub const sdk_version = std\.SemanticVersion\{/,/\};/' src/sdk/sdk_version.zig) | |
| major=$(grep -oE '\.major = [0-9]+' <<<"$block" | grep -oE '[0-9]+') | |
| minor=$(grep -oE '\.minor = [0-9]+' <<<"$block" | grep -oE '[0-9]+') | |
| patch=$(grep -oE '\.patch = [0-9]+' <<<"$block" | grep -oE '[0-9]+') | |
| if [[ -z "$major" || -z "$minor" || -z "$patch" ]]; then | |
| echo "Failed to parse sdk_version out of src/sdk/sdk_version.zig" >&2 | |
| exit 1 | |
| fi | |
| tag="sdk-v${major}.${minor}.${patch}" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "version=${major}.${minor}.${patch}" >> "$GITHUB_OUTPUT" | |
| echo "Resolved sdk_version -> $tag" | |
| - name: Create tag if missing | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| tag="${{ steps.ver.outputs.tag }}" | |
| if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then | |
| echo "Tag $tag already exists." | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git tag -a "$tag" -m "SDK ${{ steps.ver.outputs.version }} (plugin pin + ABI fingerprint)" | |
| git push origin "$tag" | |
| echo "Pushed $tag" | |
| - name: Build changelog since previous SDK tag | |
| id: changelog | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| tag="${{ steps.ver.outputs.tag }}" | |
| # Newest sdk-v* tag (other than this one) that is an ancestor of HEAD. | |
| prev="" | |
| while read -r t; do | |
| [[ "$t" == "$tag" ]] && continue | |
| if git merge-base --is-ancestor "$t" HEAD 2>/dev/null; then | |
| prev="$t" | |
| break | |
| fi | |
| done < <(git tag --list 'sdk-v*' --sort=-v:refname) | |
| out="${RUNNER_TEMP:-/tmp}/CHANGELOG_SDK.md" | |
| echo "file=$out" >> "$GITHUB_OUTPUT" | |
| if [[ -z "$prev" ]]; then | |
| printf '## Changes\n\nFirst published SDK release — no previous `sdk-v*` tag to diff against.\n' >"$out" | |
| echo "No previous SDK tag found." | |
| else | |
| range="${prev}..HEAD" | |
| echo "Changelog range: $range" | |
| printf '## Changes since `%s`\n\n' "$prev" >"$out" | |
| sdk_log=$(git log "$range" --no-merges --format='- %s (%h)' -- sdk src/sdk scripts/pack-sdk.sh) | |
| if [[ -n "$sdk_log" ]]; then | |
| printf '### SDK\n\n%s\n\n' "$sdk_log" >>"$out" | |
| fi | |
| all_log=$(git log "$range" --no-merges --format='- %s (%h)') | |
| if [[ -n "$all_log" ]]; then | |
| printf '<details>\n<summary>All commits in this range</summary>\n\n%s\n\n</details>\n\n' "$all_log" >>"$out" | |
| fi | |
| printf '[Full diff](https://github.com/%s/compare/%s...%s)\n' \ | |
| "${{ github.repository }}" "$prev" "$tag" >>"$out" | |
| fi | |
| cat "$out" | |
| - name: Pack SDK tarball | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| chmod +x scripts/pack-sdk.sh | |
| ./scripts/pack-sdk.sh "$PWD/zig-out/sdk" | |
| ls -la zig-out/sdk/ | |
| - name: Publish GitHub release asset | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| tag="${{ steps.ver.outputs.tag }}" | |
| version="${{ steps.ver.outputs.version }}" | |
| asset="zig-out/sdk/fizzy-sdk-v${version}.tar.gz" | |
| test -f "$asset" | |
| notes_file="$(mktemp)" | |
| cat >"$notes_file" <<EOF | |
| Plugin-facing SDK package for Fizzy \`${version}\`. | |
| Pin in your plugin's \`build.zig.zon\`: | |
| \`\`\`zig | |
| .fizzy = .{ | |
| .url = "https://github.com/fizzyedit/fizzy/releases/download/${tag}/fizzy-sdk-v${version}.tar.gz", | |
| .hash = "…", // zig fetch --save=fizzy <url> | |
| }, | |
| \`\`\` | |
| Do **not** pin the git archive of this tag — that is the full monorepo (app zon / Velopack). | |
| This asset is the \`sdk/\` package with \`src/core\` + \`src/sdk\` vendored in. | |
| Locally, \`.path = "../fizzy/sdk"\` is fine while developing against an unreleased SDK. | |
| See [docs/PLUGINS.md](https://github.com/fizzyedit/fizzy/blob/main/docs/PLUGINS.md) §2.3. | |
| EOF | |
| # Strip the common leading indent from the YAML-embedded heredoc. | |
| sed -i 's/^ //' "$notes_file" | |
| # Append the commit changelog computed against the previous sdk-v* tag. | |
| printf '\n---\n\n' >>"$notes_file" | |
| cat "${{ steps.changelog.outputs.file }}" >>"$notes_file" | |
| # Idempotent: create the release if missing, else replace the sdk asset + notes. | |
| if gh release view "$tag" >/dev/null 2>&1; then | |
| echo "Release $tag exists — uploading/replacing asset and refreshing notes." | |
| gh release upload "$tag" "$asset" --clobber | |
| gh release edit "$tag" --notes-file "$notes_file" | |
| else | |
| gh release create "$tag" "$asset" \ | |
| --title "Fizzy SDK $version" \ | |
| --notes-file "$notes_file" | |
| fi | |
| echo "Published $asset on $tag" | |
| gh release view "$tag" --json assets --jq '.assets[].name' |