Skip to content

Commit 0f34de3

Browse files
authored
add GitHub Actions workflow for Unity package release (#11)
1 parent 8dde32b commit 0f34de3

1 file changed

Lines changed: 126 additions & 0 deletions

File tree

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
name: Release Unity Package
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: 'Tag to release (e.g. v1.0.0)'
11+
required: true
12+
type: string
13+
14+
concurrency:
15+
group: release-${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
16+
cancel-in-progress: false
17+
18+
jobs:
19+
release:
20+
runs-on: ubuntu-24.04
21+
permissions:
22+
contents: write
23+
steps:
24+
- name: Resolve immutable target
25+
id: target
26+
env:
27+
GH_TOKEN: ${{ github.token }}
28+
INPUT_TAG: ${{ github.event.inputs.tag }}
29+
run: |
30+
shopt -s inherit_errexit
31+
TAG="${INPUT_TAG:-${GITHUB_REF#refs/tags/}}"
32+
if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
33+
echo "Error: Tag '$TAG' does not match expected format v<major>.<minor>.<patch>"
34+
exit 1
35+
fi
36+
REF_JSON="$(gh api "repos/${{ github.repository }}/git/ref/tags/${TAG}")" || {
37+
echo "Error: Tag $TAG not found or API request failed" >&2
38+
exit 1
39+
}
40+
OBJ_TYPE="$(echo "$REF_JSON" | jq -r '.object.type')"
41+
OBJ_SHA="$(echo "$REF_JSON" | jq -r '.object.sha')"
42+
if [ "$OBJ_TYPE" = "tag" ]; then
43+
COMMIT_SHA="$(gh api "repos/${{ github.repository }}/git/tags/${OBJ_SHA}" --jq '.object.sha')" || {
44+
echo "Error: Failed to dereference annotated tag $TAG" >&2
45+
exit 1
46+
}
47+
elif [ "$OBJ_TYPE" = "commit" ]; then
48+
COMMIT_SHA="$OBJ_SHA"
49+
else
50+
echo "Error: Unsupported tag object type: $OBJ_TYPE" >&2
51+
exit 1
52+
fi
53+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
54+
echo "sha=$COMMIT_SHA" >> "$GITHUB_OUTPUT"
55+
56+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
57+
with:
58+
ref: ${{ steps.target.outputs.sha }}
59+
persist-credentials: false
60+
61+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
62+
with:
63+
node-version: '22'
64+
65+
- name: Extract version from package.json
66+
id: version
67+
working-directory: Packages/AudioConductor
68+
run: |
69+
VERSION=$(jq -r '.version' package.json)
70+
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
71+
echo "Error: version '$VERSION' in package.json does not match semver format"
72+
exit 1
73+
fi
74+
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
75+
echo "Releasing Audio Conductor v$VERSION"
76+
77+
- name: Verify version matches tag
78+
run: |
79+
TAG_VERSION="${{ steps.target.outputs.tag }}"
80+
TAG_VERSION="${TAG_VERSION#v}"
81+
PACKAGE_VERSION="${{ steps.version.outputs.VERSION }}"
82+
if [ "$TAG_VERSION" != "$PACKAGE_VERSION" ]; then
83+
echo "Error: Tag (${{ steps.target.outputs.tag }}) does not match package.json version ($PACKAGE_VERSION)"
84+
exit 1
85+
fi
86+
echo "Version verified: $TAG_VERSION = $PACKAGE_VERSION ✓"
87+
88+
- name: Create package archive with npm pack
89+
working-directory: Packages/AudioConductor
90+
run: |
91+
TARBALL=$(npm pack --json | jq -r '.[0].filename')
92+
mv "$TARBALL" ../../audioconductor-${{ steps.version.outputs.VERSION }}.tgz
93+
echo "Package archive created"
94+
95+
- name: Extract changelog and create release notes
96+
run: |
97+
VERSION="${{ steps.version.outputs.VERSION }}"
98+
awk "/## v${VERSION}/{flag=1; next} /^## v/{flag=0} flag" \
99+
Packages/AudioConductor/CHANGELOG.md > release-notes.md
100+
if [ ! -s release-notes.md ]; then
101+
echo "Error: No CHANGELOG entry found for v$VERSION"
102+
exit 1
103+
fi
104+
echo "" >> release-notes.md
105+
echo "## Installation" >> release-notes.md
106+
echo "" >> release-notes.md
107+
echo "1. Download \`audioconductor-${VERSION}.tgz\`" >> release-notes.md
108+
echo "2. In Unity Package Manager, select \"Add package from tarball...\" to install" >> release-notes.md
109+
110+
- name: Create GitHub Release
111+
env:
112+
GH_TOKEN: ${{ github.token }}
113+
run: |
114+
TAG="${{ steps.target.outputs.tag }}"
115+
VERSION="${{ steps.version.outputs.VERSION }}"
116+
if gh release view "$TAG" > /dev/null 2>&1; then
117+
gh release edit "$TAG" \
118+
--title "Audio Conductor $TAG" \
119+
--notes-file release-notes.md
120+
gh release upload "$TAG" audioconductor-${VERSION}.tgz --clobber
121+
else
122+
gh release create "$TAG" \
123+
--title "Audio Conductor $TAG" \
124+
--notes-file release-notes.md \
125+
audioconductor-${VERSION}.tgz
126+
fi

0 commit comments

Comments
 (0)