Skip to content

fix(ci): use node for cross-platform symlink removal (PowerShell rm -… #23

fix(ci): use node for cross-platform symlink removal (PowerShell rm -…

fix(ci): use node for cross-platform symlink removal (PowerShell rm -… #23

Workflow file for this run

# ==============================================
# NoteCode Release Pipeline
# ==============================================
# Triggered by pushing a version tag (v*)
# Publishes to: npm registry + GitHub Releases (Electron binaries)
#
# Usage:
# git tag v1.0.0 && git push origin main --tags
#
# Pre-release:
# git tag v1.0.0-beta.1 && git push origin main --tags
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write # Required for creating GitHub Releases
env:
NODE_VERSION: '20'
jobs:
# ============================================
# Job 1: Publish to npm registry
# ============================================
npm-publish:
name: Publish to npm
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
- name: Cache node_modules
uses: actions/cache@v4
with:
path: |
node_modules
backend/node_modules
frontend/node_modules
key: npm-publish-${{ runner.os }}-${{ hashFiles('package.json', 'backend/package.json', 'frontend/package.json') }}
restore-keys: npm-publish-${{ runner.os }}-
- name: Install dependencies
run: npm install --ignore-scripts
# --ignore-scripts: skip electron rebuild (not needed for npm publish)
- name: Build backend
run: npm run build --prefix backend
- name: Build frontend
run: npm run build --prefix frontend
- name: Publish to npm
run: npm publish || echo "::warning::npm publish failed (version may already exist)"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# ============================================
# Job 2: Build Electron (matrix: win/mac/linux)
# ============================================
electron-build:
name: Build Electron (${{ matrix.platform }})
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
platform: win
- os: macos-latest
platform: mac
- os: ubuntu-latest
platform: linux
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
# Cache node_modules and Electron binaries per OS
- name: Cache node_modules
uses: actions/cache@v4
with:
path: |
node_modules
backend/node_modules
frontend/node_modules
electron/node_modules
key: electron-deps-${{ runner.os }}-${{ hashFiles('package.json', 'backend/package.json', 'frontend/package.json', 'electron/package.json') }}
restore-keys: electron-deps-${{ runner.os }}-
- name: Cache Electron binaries
uses: actions/cache@v4
with:
path: |
~/.cache/electron
~/.cache/electron-builder
~/AppData/Local/electron/Cache
~/AppData/Local/electron-builder/Cache
~/Library/Caches/electron
~/Library/Caches/electron-builder
key: electron-bin-${{ runner.os }}-${{ hashFiles('electron/package.json') }}
restore-keys: electron-bin-${{ runner.os }}-
# Disable Windows Defender real-time scanning — causes massive I/O slowdown
# when 7z processes thousands of small files in node_modules
- name: Disable Windows Defender (Windows only)
if: runner.os == 'Windows'
run: Set-MpPreference -DisableRealtimeMonitoring $true
shell: powershell
- name: Install all dependencies
run: npm install --ignore-scripts
- name: Install backend dependencies
run: npm install --prefix backend --ignore-scripts
- name: Install frontend dependencies
run: npm install --prefix frontend
- name: Install electron dependencies
run: npm install --prefix electron --ignore-scripts
- name: Build backend
run: cd backend && npm run build
- name: Build frontend
run: cd frontend && npm run build
- name: Build electron
run: cd electron && npm run build
# Remove workspace symlinks that cause infinite traversal in 7z/electron-builder
- name: Remove workspace symlinks from backend node_modules
run: |
node -e "const fs=require('fs'); ['notecode','notecode-app'].forEach(p => { const t='backend/node_modules/'+p; try { fs.rmSync(t,{recursive:true,force:true}); console.log('Removed',t); } catch(e) { console.log('Skip',t,e.message); } });"
- name: Package Electron (${{ matrix.platform }})
run: cd electron && npx --no-install electron-builder --${{ matrix.platform }} --publish never
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEBUG: electron-builder
ELECTRON_BUILDER_COMPRESSION_LEVEL: 0
# Code signing (optional - add when certificates are available)
# CSC_LINK: ${{ secrets.MAC_CERT_P12 }}
# CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}
# WIN_CSC_LINK: ${{ secrets.WIN_CERT_PFX }}
# WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CERT_PASSWORD }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: electron-${{ matrix.platform }}
path: |
release/*.exe
release/*.dmg
release/*.zip
release/*.AppImage
release/*.deb
release/*.rpm
release/*.yml
release/*.yaml
if-no-files-found: warn
retention-days: 7
# ============================================
# Job 3: Create GitHub Release with artifacts
# ============================================
create-release:
name: Create GitHub Release
needs: [npm-publish, electron-build]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for changelog generation
- name: Download all Electron artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: electron-*
merge-multiple: true
- name: List artifacts
run: ls -la artifacts/ || echo "No artifacts found"
- name: Generate changelog from commits
id: changelog
run: |
# Find previous tag for changelog range
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
if [ -z "$PREV_TAG" ]; then
CHANGELOG=$(git log --oneline --pretty=format:"- %s" HEAD)
else
CHANGELOG=$(git log --oneline --pretty=format:"- %s" ${PREV_TAG}..HEAD)
fi
# Write to output (multiline safe)
echo "changelog<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: "NoteCode ${{ github.ref_name }}"
body: |
## What's Changed
${{ steps.changelog.outputs.changelog }}
## Downloads
| Platform | File |
|----------|------|
| Windows (installer) | `NoteCode-*-win-x64.exe` |
| Windows (portable) | `NoteCode-*-win-x64-portable.exe` |
| macOS (Intel) | `NoteCode-*-mac-x64.dmg` |
| macOS (Apple Silicon) | `NoteCode-*-mac-arm64.dmg` |
| Linux (AppImage) | `NoteCode-*-linux-x64.AppImage` |
| Linux (deb) | `NoteCode-*-linux-x64.deb` |
| Linux (rpm) | `NoteCode-*-linux-x64.rpm` |
## CLI (npm)
```bash
npx notecode-app
# or install globally
npm install -g notecode-app
```
files: artifacts/*
draft: false
prerelease: ${{ contains(github.ref_name, 'beta') || contains(github.ref_name, 'alpha') || contains(github.ref_name, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}