Skip to content

Commit f5b46db

Browse files
authored
Merge pull request #120 from beNative/codex/prepare-github-release-and-automate-workflow
Automate release workflow and update documentation for 0.6.5
2 parents 2112bfa + d292841 commit f5b46db

10 files changed

Lines changed: 377 additions & 19 deletions

File tree

.github/workflows/build-packages.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ name: Build & Package
33
on:
44
push:
55
branches: [ main ]
6-
tags: [ 'v*' ]
76
pull_request:
87

98
permissions:

.github/workflows/release.yml

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
create_release:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Check out repository
16+
uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
20+
- name: Build release notes
21+
id: notes
22+
run: |
23+
awk '
24+
/^## / {
25+
if (found) exit
26+
found = 1
27+
}
28+
found { print }
29+
' VERSION_LOG.md > release-notes.md
30+
if [ ! -s release-notes.md ]; then
31+
echo "Failed to extract release notes" >&2
32+
exit 1
33+
fi
34+
echo "Release notes:" >&2
35+
cat release-notes.md >&2
36+
37+
- name: Create GitHub release
38+
id: create_release
39+
uses: actions/create-release@v1
40+
env:
41+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42+
with:
43+
tag_name: ${{ github.ref_name }}
44+
release_name: DocForge ${{ github.ref_name }}
45+
body_path: release-notes.md
46+
draft: false
47+
prerelease: false
48+
49+
package:
50+
needs: create_release
51+
name: ${{ matrix.display-name }}
52+
runs-on: ${{ matrix.os }}
53+
strategy:
54+
fail-fast: false
55+
matrix:
56+
include:
57+
- display-name: macOS x64
58+
os: macos-latest
59+
script: package:mac:x64
60+
arch: x64
61+
npm-platform: darwin
62+
cache-paths: |
63+
~/Library/Caches/electron
64+
~/Library/Caches/electron-builder
65+
- display-name: Windows x64
66+
os: windows-latest
67+
script: package:win:x64
68+
arch: x64
69+
npm-platform: win32
70+
cache-paths: |
71+
~/AppData/Local/electron/Cache
72+
~/AppData/Local/electron-builder/Cache
73+
- display-name: Windows ia32
74+
os: windows-latest
75+
script: package:win:ia32
76+
arch: ia32
77+
npm-platform: win32
78+
cache-paths: |
79+
~/AppData/Local/electron/Cache
80+
~/AppData/Local/electron-builder/Cache
81+
- display-name: Linux x64
82+
os: ubuntu-latest
83+
script: package:linux:x64
84+
arch: x64
85+
npm-platform: linux
86+
cache-paths: |
87+
~/.cache/electron
88+
~/.cache/electron-builder
89+
- display-name: Linux armv7l
90+
os: ubuntu-latest
91+
script: package:linux:armv7l
92+
arch: armv7l
93+
npm-platform: linux
94+
cache-paths: |
95+
~/.cache/electron
96+
~/.cache/electron-builder
97+
- display-name: Linux arm64
98+
os: ubuntu-latest
99+
script: package:linux:arm64
100+
arch: arm64
101+
npm-platform: linux
102+
cache-paths: |
103+
~/.cache/electron
104+
~/.cache/electron-builder
105+
defaults:
106+
run:
107+
shell: bash
108+
env:
109+
NODE_OPTIONS: --max_old_space_size=4096
110+
TAG_NAME: ${{ github.ref_name }}
111+
steps:
112+
- name: Checkout repository
113+
uses: actions/checkout@v4
114+
with:
115+
fetch-depth: 0
116+
117+
- name: Setup Node.js
118+
uses: actions/setup-node@v4
119+
with:
120+
node-version: 20
121+
cache: npm
122+
cache-dependency-path: package-lock.json
123+
124+
- name: Cache Electron downloads
125+
uses: actions/cache@v4
126+
with:
127+
path: ${{ matrix.cache-paths }}
128+
key: ${{ runner.os }}-electron-${{ matrix.arch }}-${{ hashFiles('package-lock.json') }}
129+
restore-keys: |
130+
${{ runner.os }}-electron-${{ matrix.arch }}-
131+
${{ runner.os }}-electron-
132+
133+
- name: Install system dependencies (Linux)
134+
if: runner.os == 'Linux'
135+
run: |
136+
sudo apt-get update
137+
sudo apt-get install --no-install-recommends -y rpm libarchive-tools
138+
if ! sudo apt-get install --no-install-recommends -y libfuse2; then
139+
sudo apt-get install --no-install-recommends -y libfuse2t64
140+
fi
141+
142+
- name: Install dependencies
143+
run: npm ci
144+
env:
145+
npm_config_arch: ${{ matrix.arch }}
146+
npm_config_target_arch: ${{ matrix.arch }}
147+
npm_config_platform: ${{ matrix.npm-platform }}
148+
149+
- name: Prepare native modules
150+
run: npm run postinstall --if-present
151+
env:
152+
npm_config_arch: ${{ matrix.arch }}
153+
npm_config_target_arch: ${{ matrix.arch }}
154+
npm_config_platform: ${{ matrix.npm-platform }}
155+
156+
- name: Package application
157+
run: npm run ${{ matrix.script }}
158+
env:
159+
npm_config_arch: ${{ matrix.arch }}
160+
npm_config_target_arch: ${{ matrix.arch }}
161+
npm_config_platform: ${{ matrix.npm-platform }}
162+
163+
- name: Normalize Windows artifact names
164+
if: runner.os == 'Windows'
165+
env:
166+
MATRIX_ARCH: ${{ matrix.arch }}
167+
run: |
168+
set -euo pipefail
169+
170+
arch="$MATRIX_ARCH"
171+
shopt -s nullglob
172+
173+
exe_name=""
174+
blockmap_name=""
175+
for file in release/*.exe; do
176+
dir=$(dirname "$file")
177+
base=$(basename "$file")
178+
ext="${base##*.}"
179+
stem="${base%.$ext}"
180+
181+
if [[ "$arch" != "x64" ]]; then
182+
renamed="$dir/${stem}-${arch}.${ext}"
183+
mv "$file" "$renamed"
184+
file="$renamed"
185+
fi
186+
187+
exe_name=$(basename "$file")
188+
189+
original_blockmap="$dir/${stem}.${ext}.blockmap"
190+
if [[ -f "$original_blockmap" ]]; then
191+
target_blockmap="$dir/${exe_name}.blockmap"
192+
if [[ "$original_blockmap" != "$target_blockmap" ]]; then
193+
mv "$original_blockmap" "$target_blockmap"
194+
fi
195+
blockmap_name=$(basename "$target_blockmap")
196+
fi
197+
done
198+
199+
latest_file=""
200+
if [[ -f release/latest.yml ]]; then
201+
if [[ "$arch" != "x64" ]]; then
202+
latest_file="release/latest-${arch}.yml"
203+
mv release/latest.yml "$latest_file"
204+
else
205+
latest_file="release/latest.yml"
206+
fi
207+
fi
208+
209+
if [[ -n "$exe_name" && -n "$latest_file" ]]; then
210+
export WINDOWS_EXE_NAME="$exe_name"
211+
export WINDOWS_BLOCKMAP_NAME="$blockmap_name"
212+
export WINDOWS_LATEST_FILE="$latest_file"
213+
python - <<'PY'
214+
import os
215+
import re
216+
from pathlib import Path
217+
from urllib.parse import quote
218+
219+
latest = Path(os.environ["WINDOWS_LATEST_FILE"])
220+
exe_name = os.environ["WINDOWS_EXE_NAME"]
221+
blockmap_name = os.environ.get("WINDOWS_BLOCKMAP_NAME") or ""
222+
223+
def replace_line(line: str, needle: str, replacement: str) -> str:
224+
prefix, _, _ = line.partition(needle)
225+
return f"{prefix}{needle}{replacement}\n"
226+
227+
lines = latest.read_text(encoding="utf-8").splitlines(keepends=True)
228+
updated = []
229+
for line in lines:
230+
stripped = line.strip()
231+
if stripped.startswith("path:") and ".exe" in stripped:
232+
updated.append(replace_line(line, "path:", f" {exe_name}"))
233+
continue
234+
235+
if stripped.startswith("url:") and ".exe" in stripped:
236+
value = stripped.split(None, 1)[1] if len(stripped.split(None, 1)) == 2 else ""
237+
if value.endswith(".exe.blockmap") and blockmap_name:
238+
updated.append(replace_line(line, "url:", f" {quote(blockmap_name)}"))
239+
continue
240+
if value.endswith(".exe"):
241+
updated.append(replace_line(line, "url:", f" {quote(exe_name)}"))
242+
continue
243+
244+
updated.append(line)
245+
246+
latest.write_text("".join(updated), encoding="utf-8")
247+
PY
248+
fi
249+
250+
- name: Upload release assets
251+
env:
252+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
253+
run: |
254+
shopt -s nullglob
255+
files=()
256+
while IFS= read -r -d '' file; do
257+
case "$file" in
258+
*.blockmap) continue ;;
259+
esac
260+
files+=("$file")
261+
done < <(find release -type f -print0)
262+
263+
if [ ${#files[@]} -eq 0 ]; then
264+
echo "No release files found" >&2
265+
exit 1
266+
fi
267+
268+
for file in "${files[@]}"; do
269+
echo "Uploading $(basename "$file")"
270+
gh release upload "$TAG_NAME" "$file" --clobber
271+
done
272+
273+
- name: Upload build logs on failure
274+
if: failure()
275+
uses: actions/upload-artifact@v4
276+
with:
277+
name: ${{ matrix.display-name }}-logs
278+
path: |
279+
npm-debug.log
280+
*.log
281+
release/**/*.log
282+
if-no-files-found: ignore
283+
retention-days: 7

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ To review the history of changes, see the [Version Log](./VERSION_LOG.md).
4343
To create a new public build of DocForge:
4444

4545
1. Update the version in `package.json` and regenerate the lockfile with `npm version <new-version> --no-git-tag-version`.
46-
2. Draft the release notes by updating `VERSION_LOG.md` with a new section that summarizes the changes included in the release.
46+
2. Draft the release notes by updating `VERSION_LOG.md` with a new section that summarizes the changes included in the release (the automated workflow copies the top entry into the GitHub release body).
4747
3. Review the Markdown documentation (README, manuals, and release notes) so the written guidance matches the current workflow.
4848
4. Sync the documentation copies under `docs/` (README, manuals, version log) with any updates made at the project root.
49-
5. Run `npm run publish` to build the application and publish the artifacts to the configured GitHub release target via Electron Builder.
50-
6. Once the draft release appears on GitHub, copy the latest `VERSION_LOG.md` entry into the release description and confirm the uploaded artifacts look correct before publishing.
49+
5. Commit the changes and push them to the default branch so the release tag points at the finalized documentation.
50+
6. Create and push a tag that matches the new version (for example, `git tag v0.6.5` followed by `git push origin v0.6.5`) to trigger the automated release workflow.
51+
7. Monitor the "Release" workflow run, then confirm that the published GitHub release lists the correct notes and includes installers for every platform before announcing availability.
5152

5253
## Application Icon Workflow
5354

TECHNICAL_MANUAL.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,20 @@ Electron Builder manages the packaging and publishing workflow for DocForge. The
124124
### Publishing a Release
125125

126126
1. Run `npm version <new-version> --no-git-tag-version` to bump the version in both `package.json` and `package-lock.json` without creating a Git tag.
127-
2. Update `VERSION_LOG.md` with a new section that captures the highlights of the release.
127+
2. Update `VERSION_LOG.md` with a new section that captures the highlights of the release—the automated workflow copies the top entry into the GitHub release body.
128128
3. Review and update the Markdown documentation (README, manuals, release notes) so the written guidance reflects the final state of the build.
129129
4. Sync the Markdown files under `docs/` with the copies at the project root.
130-
5. Execute `npm run publish` to package the application and upload the release artifacts to GitHub.
131-
6. When the draft release is created, paste the freshly written `VERSION_LOG.md` entry into the GitHub release notes and verify the uploaded binaries before making the release public.
130+
5. Commit and push the changes so the release tag points at the finished documentation.
131+
6. Create and push a matching version tag (for example, `git tag v0.6.5` followed by `git push origin v0.6.5`) to trigger the automated release pipeline.
132+
7. Monitor the "Release" workflow run and verify the published GitHub release lists the correct notes and includes the installers for every supported platform before announcing availability.
133+
134+
### Automated Release Workflow
135+
136+
- Tag pushes that match `v*` trigger the `Release` GitHub Actions workflow.
137+
- An initial job extracts the latest section from `VERSION_LOG.md` and creates the GitHub release with those notes.
138+
- A platform matrix rebuilds DocForge via the existing packaging scripts (`npm run package:*`) for macOS, Windows (x64/ia32), and Linux (x64/arm64/armv7l).
139+
- Each job uploads its generated installers (and accompanying update manifests) to the release using the GitHub CLI.
140+
- `npm run publish` remains available for manual distribution, but the automated workflow is the canonical path for tagged releases.
132141

133142
### Application Icon Pipeline
134143

VERSION_LOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# Version Log
22

3+
## v0.6.5 - The Automated Release Update
4+
5+
This maintenance release introduces a hands-free publishing workflow so tagged
6+
builds automatically land on GitHub with installers for every supported
7+
platform.
8+
9+
### 🛠 Improvements
10+
11+
- Added a GitHub Actions release pipeline that rebuilds the application for
12+
macOS, Windows (x64/ia32), and Linux (x64/arm64/armv7l) whenever a tagged
13+
version is pushed and attaches the generated installers to the release.
14+
- Refreshed the release preparation checklist across the documentation set to
15+
describe the tagging workflow and clarify how release notes flow from the
16+
version log into GitHub releases.
17+
- Synced all Markdown documentation so the published guides continue to match
18+
the repository sources.
19+
20+
### 🐛 Fixes
21+
22+
- Removed stale guidance that referenced manually uploading binaries, keeping
23+
the publishing process consistent with the automated workflow.
24+
325
## v0.6.4 - The Checklist Confidence Update
426

527
This maintenance release polishes the publishing checklist and documentation so

docs/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ To review the history of changes, see the [Version Log](./VERSION_LOG.md).
4343
To create a new public build of DocForge:
4444

4545
1. Update the version in `package.json` and regenerate the lockfile with `npm version <new-version> --no-git-tag-version`.
46-
2. Draft the release notes by updating `VERSION_LOG.md` with a new section that summarizes the changes included in the release.
46+
2. Draft the release notes by updating `VERSION_LOG.md` with a new section that summarizes the changes included in the release (the automated workflow copies the top entry into the GitHub release body).
4747
3. Review the Markdown documentation (README, manuals, and release notes) so the written guidance matches the current workflow.
4848
4. Sync the documentation copies under `docs/` (README, manuals, version log) with any updates made at the project root.
49-
5. Run `npm run publish` to build the application and publish the artifacts to the configured GitHub release target via Electron Builder.
50-
6. Once the draft release appears on GitHub, copy the latest `VERSION_LOG.md` entry into the release description and confirm the uploaded artifacts look correct before publishing.
49+
5. Commit the changes and push them to the default branch so the release tag points at the finalized documentation.
50+
6. Create and push a tag that matches the new version (for example, `git tag v0.6.5` followed by `git push origin v0.6.5`) to trigger the automated release workflow.
51+
7. Monitor the "Release" workflow run, then confirm that the published GitHub release lists the correct notes and includes installers for every platform before announcing availability.
5152

5253
## Application Icon Workflow
5354

docs/TECHNICAL_MANUAL.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,20 @@ Electron Builder manages the packaging and publishing workflow for DocForge. The
124124
### Publishing a Release
125125

126126
1. Run `npm version <new-version> --no-git-tag-version` to bump the version in both `package.json` and `package-lock.json` without creating a Git tag.
127-
2. Update `VERSION_LOG.md` with a new section that captures the highlights of the release.
127+
2. Update `VERSION_LOG.md` with a new section that captures the highlights of the release—the automated workflow copies the top entry into the GitHub release body.
128128
3. Review and update the Markdown documentation (README, manuals, release notes) so the written guidance reflects the final state of the build.
129129
4. Sync the Markdown files under `docs/` with the copies at the project root.
130-
5. Execute `npm run publish` to package the application and upload the release artifacts to GitHub.
131-
6. When the draft release is created, paste the freshly written `VERSION_LOG.md` entry into the GitHub release notes and verify the uploaded binaries before making the release public.
130+
5. Commit and push the changes so the release tag points at the finished documentation.
131+
6. Create and push a matching version tag (for example, `git tag v0.6.5` followed by `git push origin v0.6.5`) to trigger the automated release pipeline.
132+
7. Monitor the "Release" workflow run and verify the published GitHub release lists the correct notes and includes the installers for every supported platform before announcing availability.
133+
134+
### Automated Release Workflow
135+
136+
- Tag pushes that match `v*` trigger the `Release` GitHub Actions workflow.
137+
- An initial job extracts the latest section from `VERSION_LOG.md` and creates the GitHub release with those notes.
138+
- A platform matrix rebuilds DocForge via the existing packaging scripts (`npm run package:*`) for macOS, Windows (x64/ia32), and Linux (x64/arm64/armv7l).
139+
- Each job uploads its generated installers (and accompanying update manifests) to the release using the GitHub CLI.
140+
- `npm run publish` remains available for manual distribution, but the automated workflow is the canonical path for tagged releases.
132141

133142
### Application Icon Pipeline
134143

0 commit comments

Comments
 (0)