name: Release Binaries on: push: branches: - main permissions: contents: write env: NODE_VERSION: 20 jobs: prepare-release: runs-on: ubuntu-latest outputs: version: ${{ steps.get_version.outputs.version }} tag: ${{ steps.ensure_tag.outputs.tag }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - name: Read version id: get_version run: | VERSION=$(node -p "require('./package.json').version") echo "version=$VERSION" >> "$GITHUB_OUTPUT" - name: Ensure git tag id: ensure_tag env: VERSION: ${{ steps.get_version.outputs.version }} run: | TAG="v${VERSION}" git fetch --tags if git rev-parse "$TAG" >/dev/null 2>&1; then echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "Tag $TAG already exists" else git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git tag "$TAG" git push origin "$TAG" echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "Created tag $TAG" fi - name: Ensure GitHub release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ steps.ensure_tag.outputs.tag }} VERSION: ${{ steps.get_version.outputs.version }} run: | if gh release view "$TAG" >/dev/null 2>&1; then echo "Release $TAG already exists" else gh release create "$TAG" --title "CodeNomad v${VERSION}" --generate-notes fi build-macos: needs: prepare-release runs-on: macos-13 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: npm - name: Install dependencies run: npm ci - name: Build macOS binaries run: npm run build:mac - name: Upload release assets env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ needs.prepare-release.outputs.tag }} run: | set -euo pipefail shopt -s nullglob for file in release/*; do [ -f "$file" ] || continue case "$file" in *.dmg|*.zip) gh release upload "$TAG" "$file" --clobber ;; *) echo "Skipping non-installer asset: $file" ;; esac done build-windows: needs: prepare-release runs-on: windows-latest env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: npm - name: Install dependencies run: npm ci - name: Build Windows binaries run: npm run build:win - name: Upload release assets shell: pwsh env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ needs.prepare-release.outputs.tag }} run: | Get-ChildItem -Path "release" -File | Where-Object { $_.Name -match '\.(exe|zip)$' } | ForEach-Object { gh release upload $env:TAG $_.FullName --clobber } build-linux: needs: prepare-release runs-on: ubuntu-latest env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: npm - name: Install dependencies run: npm ci - name: Build Linux binaries run: npm run build:linux - name: Upload release assets env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAG: ${{ needs.prepare-release.outputs.tag }} run: | set -euo pipefail shopt -s nullglob for file in release/*; do [ -f "$file" ] || continue case "$file" in *.AppImage|*.deb|*.tar.gz) gh release upload "$TAG" "$file" --clobber ;; *) echo "Skipping non-installer asset: $file" ;; esac done