Skip to content

Commit 536cf46

Browse files
Add auto-release workflow for validated main updates
1 parent cc53c9d commit 536cf46

2 files changed

Lines changed: 147 additions & 1 deletion

File tree

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
name: Release On Main
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
release:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout main
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Setup Node
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: '20'
26+
27+
- name: Resolve release version and archive
28+
id: release_meta
29+
run: |
30+
set -euo pipefail
31+
VERSION=$(grep -oP '<!ENTITY version "\K[^"]+' folderview.plus.plg)
32+
ARCHIVE="archive/folderview.plus-${VERSION}.txz"
33+
if [ ! -f "${ARCHIVE}" ]; then
34+
echo "ERROR: expected archive not found: ${ARCHIVE}" >&2
35+
exit 1
36+
fi
37+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
38+
echo "archive=${ARCHIVE}" >> "$GITHUB_OUTPUT"
39+
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
40+
41+
- name: Run release guard
42+
run: |
43+
chmod +x scripts/release_guard.sh
44+
bash scripts/release_guard.sh
45+
46+
- name: Run install smoke checks
47+
run: |
48+
chmod +x scripts/install_smoke.sh
49+
bash scripts/install_smoke.sh
50+
51+
- name: Run test suite
52+
run: |
53+
node --test tests/*.mjs
54+
55+
- name: Optional browser smoke checks
56+
env:
57+
FVPLUS_BROWSER_SMOKE_URL: ${{ secrets.FVPLUS_BROWSER_SMOKE_URL }}
58+
FVPLUS_BROWSER_SMOKE_TIMEOUT_MS: '90000'
59+
FVPLUS_BROWSER_SMOKE_IGNORE_HTTPS: '1'
60+
run: |
61+
if [ -z "${FVPLUS_BROWSER_SMOKE_URL:-}" ]; then
62+
echo "Skipping browser smoke checks (FVPLUS_BROWSER_SMOKE_URL not configured)."
63+
exit 0
64+
fi
65+
npm install --no-save playwright
66+
npx playwright install --with-deps chromium firefox
67+
chmod +x scripts/browser_smoke.sh
68+
bash scripts/browser_smoke.sh
69+
70+
- name: Build release notes from current CHANGES block
71+
id: notes
72+
run: |
73+
set -euo pipefail
74+
VERSION="${{ steps.release_meta.outputs.version }}"
75+
NOTES_BLOCK="$(awk -v version="${VERSION}" '
76+
BEGIN { capture = 0 }
77+
/^###/ {
78+
if (capture) {
79+
exit
80+
}
81+
if ($0 ~ "^###" version "[[:space:]]*$") {
82+
capture = 1
83+
next
84+
}
85+
}
86+
{
87+
if (capture) {
88+
print
89+
}
90+
}
91+
' folderview.plus.plg | sed '/^[[:space:]]*$/d')"
92+
93+
if [ -z "${NOTES_BLOCK}" ]; then
94+
echo "ERROR: Missing CHANGES block for version ${VERSION}" >&2
95+
exit 1
96+
fi
97+
98+
{
99+
echo "## FolderView Plus ${VERSION}"
100+
echo
101+
echo "Install URL: \`https://raw.githubusercontent.com/alexphillips-dev/FolderView-Plus/main/folderview.plus.plg\`"
102+
echo
103+
echo "### Changes"
104+
echo "${NOTES_BLOCK}"
105+
} > release_notes.md
106+
107+
- name: Ensure GitHub CLI
108+
run: |
109+
if command -v gh >/dev/null 2>&1; then
110+
gh --version
111+
exit 0
112+
fi
113+
sudo apt-get update
114+
sudo apt-get install -y gh
115+
116+
- name: Create or update GitHub release
117+
env:
118+
GH_TOKEN: ${{ github.token }}
119+
run: |
120+
set -euo pipefail
121+
TAG="${{ steps.release_meta.outputs.tag }}"
122+
ARCHIVE="${{ steps.release_meta.outputs.archive }}"
123+
if gh release view "${TAG}" >/dev/null 2>&1; then
124+
gh release edit "${TAG}" --title "${TAG}" --notes-file release_notes.md
125+
gh release upload "${TAG}" "${ARCHIVE}" --clobber
126+
echo "Updated release ${TAG}"
127+
else
128+
gh release create "${TAG}" "${ARCHIVE}" --title "${TAG}" --notes-file release_notes.md
129+
echo "Created release ${TAG}"
130+
fi

tests/versioning-guard.test.mjs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const ciWorkflowPath = path.join(repoRoot, '.github/workflows/ci.yml');
1111
const releaseMainWorkflowPath = path.join(repoRoot, '.github/workflows/release-main.yml');
1212
const releaseStableWorkflowPath = path.join(repoRoot, '.github/workflows/release-stable.yml');
1313
const releaseBetaWorkflowPath = path.join(repoRoot, '.github/workflows/release-beta.yml');
14+
const releaseOnMainWorkflowPath = path.join(repoRoot, '.github/workflows/release-on-main.yml');
1415
const browserSmokeShellPath = path.join(repoRoot, 'scripts/browser_smoke.sh');
1516
const browserSmokeNodePath = path.join(repoRoot, 'scripts/browser_smoke.mjs');
1617
const pkgBuild = fs.readFileSync(pkgBuildPath, 'utf8');
@@ -20,6 +21,7 @@ const ciWorkflow = fs.readFileSync(ciWorkflowPath, 'utf8');
2021
const releaseMainWorkflow = fs.readFileSync(releaseMainWorkflowPath, 'utf8');
2122
const releaseStableWorkflow = fs.readFileSync(releaseStableWorkflowPath, 'utf8');
2223
const releaseBetaWorkflow = fs.readFileSync(releaseBetaWorkflowPath, 'utf8');
24+
const releaseOnMainWorkflow = fs.readFileSync(releaseOnMainWorkflowPath, 'utf8');
2325
const browserSmokeShell = fs.readFileSync(browserSmokeShellPath, 'utf8');
2426
const browserSmokeNode = fs.readFileSync(browserSmokeNodePath, 'utf8');
2527

@@ -91,10 +93,24 @@ test('browser smoke scripts are optional, URL-gated, and include core UI checks'
9193
});
9294

9395
test('validation workflows include optional browser smoke integration', () => {
94-
for (const workflow of [ciWorkflow, releaseMainWorkflow, releaseStableWorkflow, releaseBetaWorkflow]) {
96+
for (const workflow of [ciWorkflow, releaseMainWorkflow, releaseStableWorkflow, releaseBetaWorkflow, releaseOnMainWorkflow]) {
9597
assert.match(workflow, /Optional browser smoke checks/);
9698
assert.match(workflow, /FVPLUS_BROWSER_SMOKE_URL/);
9799
assert.match(workflow, /bash scripts\/browser_smoke\.sh/);
98100
}
99101
assert.match(releasePrepare, /bash scripts\/browser_smoke\.sh/);
100102
});
103+
104+
test('release-on-main workflow auto-publishes validated releases from current plg version', () => {
105+
assert.match(releaseOnMainWorkflow, /name:\s*Release On Main/);
106+
assert.match(releaseOnMainWorkflow, /push:\s*\n\s*branches:\s*\n\s*-\s*main/);
107+
assert.match(releaseOnMainWorkflow, /bash scripts\/release_guard\.sh/);
108+
assert.match(releaseOnMainWorkflow, /bash scripts\/install_smoke\.sh/);
109+
assert.match(releaseOnMainWorkflow, /node --test tests\/\*\.mjs/);
110+
assert.match(releaseOnMainWorkflow, /release_notes\.md/);
111+
assert.match(releaseOnMainWorkflow, /folderview\.plus\.plg/);
112+
assert.match(releaseOnMainWorkflow, /archive\/folderview\.plus-\$\{VERSION\}\.txz/);
113+
assert.match(releaseOnMainWorkflow, /gh release create/);
114+
assert.match(releaseOnMainWorkflow, /gh release edit/);
115+
assert.match(releaseOnMainWorkflow, /GH_TOKEN:\s*\$\{\{\s*github\.token\s*\}\}/);
116+
});

0 commit comments

Comments
 (0)