Skip to content

(osc): build the PTY debug lines only when debug logging is on #474

(osc): build the PTY debug lines only when debug logging is on

(osc): build the PTY debug lines only when debug logging is on #474

Workflow file for this run

name: Build & Release
on:
push:
tags: ['v*']
pull_request:
branches: [main]
permissions:
contents: write
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-14
platform: mac
# Pinned, not `windows-latest`: that label has rolled over to Windows
# Server 2025, whose image no longer ships the Visual Studio C++
# toolchain node-gyp needs. On it, electron-builder's install-app-deps
# dies with "Could not find any Visual Studio installation to use"
# while rebuilding node-pty, so the Windows build never produces an
# artifact. 2022 still carries the toolchain.
- os: windows-2022
platform: win
# Linux is split per-arch to avoid electron-builder bundling native
# modules from the wrong architecture. When multiple targets (AppImage
# + deb) are built for multiple arches in one invocation, the native
# module rebuild only runs between arch switches for the first target
# type — the second target type reuses whatever was last compiled,
# which can be the wrong arch. See #18.
- os: ubuntu-latest
platform: linux
arch: x64
- os: ubuntu-24.04-arm
platform: linux
arch: arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install setuptools (node-gyp distutils fix)
run: python -m pip install setuptools
- name: Install pacman build tooling (Linux)
if: matrix.platform == 'linux'
run: sudo apt-get update && sudo apt-get install -y libarchive-tools
- name: Install dependencies
run: npm ci
- name: Bundle CodeMirror
run: npm run bundle:codemirror
- name: Build
run: npx electron-builder --${{ matrix.platform }} --publish never
env:
# Passing CSC_LINK="" (empty) makes electron-builder treat the cwd as a
# cert file ("… not a file") on tag builds. Only set the signing vars
# when a cert secret actually exists; otherwise leave them unset and let
# mac.identity:null (package.json) produce a clean unsigned build.
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
CSC_IDENTITY_AUTO_DISCOVERY: ${{ matrix.platform == 'mac' && secrets.CSC_LINK != '' }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.platform }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }}
path: |
dist/*.dmg
dist/*.dmg.blockmap
dist/*.zip
dist/*.zip.blockmap
dist/*.exe
dist/*.exe.blockmap
dist/*.AppImage
dist/*.deb
dist/*.pacman
dist/latest*.yml
if-no-files-found: ignore
publish:
needs: build
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
# Full history + tags: the release notes are derived from the commit range
# between the previous tag and this one.
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
- name: Create GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Create the draft once. Tolerate "already exists" so a re-run after a
# partial failure still proceeds to (re-)upload the assets.
gh release create "${GITHUB_REF_NAME}" \
--draft \
--title "${GITHUB_REF_NAME#v}" \
--notes "" \
|| echo "release already exists — proceeding to asset upload"
# Upload each asset individually with retries. A single whole-batch
# `gh release create ... dist/*` aborts entirely when uploads.github.com
# returns an intermittent 401 on one asset (typically a .blockmap),
# leaving a partial release. Per-file + retry makes publishing reliable.
rc=0
for f in dist/*; do
[ -f "$f" ] || continue
ok=0
for i in 1 2 3 4 5; do
if gh release upload "${GITHUB_REF_NAME}" "$f" --clobber; then ok=1; break; fi
echo "::warning::upload $(basename "$f") attempt $i failed; retrying in 10s"
sleep 10
done
if [ "$ok" != 1 ]; then echo "::error::failed to upload $(basename "$f") after retries"; rc=1; fi
done
exit $rc
# v0.0.63 to v0.0.65 all shipped with an empty body: the step above creates
# the draft with --notes "" and nothing ever filled it in. Derive the body
# from the tag range instead, and fail loudly rather than write an empty one.
- name: Fill in release notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG="${GITHUB_REF_NAME}"
# The tag that precedes this one on this tag's own history, not the
# repository's newest tag.
PREV_TAG="$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)"
if [ -n "$PREV_TAG" ]; then RANGE="${PREV_TAG}..${TAG}"; else RANGE="$TAG"; fi
# main is a chain of PR squash-merges, one subject per PR. The version
# bump commit ("v0.0.65 (#189)") is release plumbing, not a change.
git log --no-merges --format='%s' "$RANGE" \
| grep -Ev '^v[0-9]+\.[0-9]+\.[0-9]+([^0-9].*)?$' > subjects.txt || true
if [ ! -s subjects.txt ]; then
echo "::error::no release-worthy commits in ${RANGE}; refusing to write an empty release body"
exit 1
fi
{
echo "## What's changed"
echo
sed 's/^/- /' subjects.txt
if [ -n "$PREV_TAG" ]; then
echo
echo "**Full changelog**: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/compare/${PREV_TAG}...${TAG}"
fi
} > release-notes.md
# Stays a draft: edit only replaces the body.
gh release edit "$TAG" --notes-file release-notes.md