Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
name: "Release"

on:
push:
tags: ["v*.*.*"]

permissions:
contents: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
release:
if: github.repository == 'z-shell/zunit'
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install zsh
run: sudo apt-get update && sudo apt-get install -yq zsh
- name: Build zunit
run: ./build.zsh
- name: Verify release tag
run: |
tag="${GITHUB_REF_NAME}"
scripts/verify-release-tag.zsh "$tag" ./zunit
- name: Publish GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
tag="${GITHUB_REF_NAME}"
if gh release view "$tag" >/dev/null 2>&1; then
gh release upload "$tag" ./zunit#zunit --clobber
else
gh release create "$tag" ./zunit#zunit --title "$tag" --generate-notes
fi
2 changes: 1 addition & 1 deletion .github/workflows/zsh-n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
run: sudo apt-get update && sudo apt-get install -yq zsh
- name: Check Zsh syntax
run: |
find src -type f -name '*.zsh' -print | sort | while read -r file; do
find src scripts -type f -name '*.zsh' -print | sort | while read -r file; do
zsh -n "$file"
done
zsh -n build.zsh
Expand Down
30 changes: 30 additions & 0 deletions scripts/verify-release-tag.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env zsh
# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
# vim: ft=zsh sw=2 ts=2 et

builtin emulate -L zsh
builtin setopt err_return no_unset pipe_fail

local tag="${1:-}"
local binary="${2:-./zunit}"

if [[ ! "$tag" =~ '^v[0-9]+[.][0-9]+[.][0-9]+$' ]]; then
print -ru2 -- "Expected semantic version tag like v1.2.3, got '${tag:-<empty>}'"
exit 1
fi

if [[ ! -x "$binary" ]]; then
print -ru2 -- "Release binary '$binary' is missing or is not executable"
exit 1
fi

local expected_version="${tag#v}"
local actual_version
actual_version="$($binary --version)"

if [[ "$actual_version" != "$expected_version" ]]; then
print -ru2 -- "Release tag $tag does not match zunit version $actual_version"
exit 1
fi

print -r -- "Release tag $tag matches zunit version $actual_version"
51 changes: 51 additions & 0 deletions tests/release.zunit
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env zunit

@test 'release tag guard accepts a matching semantic version tag' {
local sandbox binary
sandbox="$(mktemp -d)"
binary="$sandbox/zunit"

print -r -- '#!/usr/bin/env zsh' > "$binary"
print -r -- '[[ $1 == --version ]] && print -r -- 1.2.3' >> "$binary"
chmod u+x "$binary"

run "$PWD/scripts/verify-release-tag.zsh" v1.2.3 "$binary"

assert "$state" equals 0
assert "$output" contains 'Release tag v1.2.3 matches zunit version 1.2.3'
}

@test 'release tag guard rejects a mismatched binary version' {
local sandbox binary
sandbox="$(mktemp -d)"
binary="$sandbox/zunit"

print -r -- '#!/usr/bin/env zsh' > "$binary"
print -r -- '[[ $1 == --version ]] && print -r -- 1.2.4' >> "$binary"
chmod u+x "$binary"

run "$PWD/scripts/verify-release-tag.zsh" v1.2.3 "$binary"

assert "$state" equals 1
assert "$output" contains 'Release tag v1.2.3 does not match zunit version 1.2.4'
}

@test 'release tag guard rejects non-semantic tags' {
run "$PWD/scripts/verify-release-tag.zsh" latest ./zunit

assert "$state" equals 1
assert "$output" contains 'Expected semantic version tag like v1.2.3'
}

@test 'release workflow publishes the zunit binary only for semantic tags' {
local workflow
workflow="$(< "$PWD/.github/workflows/release.yml")"

assert "$workflow" contains 'tags: ["v*.*.*"]'
assert "$workflow" does_not_contain 'branches: [main]'
assert "$workflow" contains 'contents: write'
assert "$workflow" contains 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5'
assert "$workflow" contains 'scripts/verify-release-tag.zsh "$tag" ./zunit'
assert "$workflow" contains 'gh release create "$tag" ./zunit#zunit'
assert "$workflow" contains 'gh release upload "$tag" ./zunit#zunit --clobber'
}
Loading