v0.1.3 #4
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| release: | |
| types: [created] | |
| jobs: | |
| check-certificates: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| has-macos-cert: ${{ steps.check-macos.outputs.has-cert }} | |
| has-windows-cert: ${{ steps.check-windows.outputs.has-cert }} | |
| has-linux-cert: ${{ steps.check-linux.outputs.has-cert }} | |
| steps: | |
| - name: Check macOS certificates | |
| id: check-macos | |
| run: | | |
| if [ -n "${{ secrets.MACOS_CERTIFICATE }}" ] && [ -n "${{ secrets.MACOS_CERTIFICATE_PASSWORD }}" ] && [ -n "${{ secrets.APPLE_ID }}" ] && [ -n "${{ secrets.APPLE_APP_PASSWORD }}" ] && [ -n "${{ secrets.APPLE_TEAM_ID }}" ]; then | |
| echo "has-cert=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has-cert=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Check Windows certificates | |
| id: check-windows | |
| run: | | |
| if [ -n "${{ secrets.WINDOWS_CERTIFICATE }}" ] && [ -n "${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}" ]; then | |
| echo "has-cert=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has-cert=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Check Linux certificates | |
| id: check-linux | |
| run: | | |
| if [ -n "${{ secrets.LINUX_CERTIFICATE }}" ]; then | |
| echo "has-cert=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has-cert=false" >> $GITHUB_OUTPUT | |
| fi | |
| build-macos: | |
| needs: check-certificates | |
| if: needs.check-certificates.outputs.has-macos-cert == 'true' | |
| runs-on: macos-latest | |
| outputs: | |
| artifacts: ${{ steps.build.outputs.artifacts }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Import Code-Signing Certificates | |
| uses: Apple-Actions/import-codesign-certs@v5 | |
| with: | |
| p12-file-base64: ${{ secrets.MACOS_CERTIFICATE }} | |
| p12-password: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} | |
| - name: Build and sign macOS binaries | |
| id: build | |
| run: | | |
| # Build macOS binaries | |
| mkdir -p dist | |
| bun build src/index.ts --target=bun-darwin-x64 --compile --minify --outfile=dist/lpop-darwin-x64 | |
| bun build src/index.ts --target=bun-darwin-arm64 --compile --minify --outfile=dist/lpop-darwin-arm64 | |
| # Sign the binaries | |
| codesign --force --options runtime --entitlements scripts/entitlements.plist --sign "Developer ID Application" dist/lpop-darwin-x64 | |
| codesign --force --options runtime --entitlements scripts/entitlements.plist --sign "Developer ID Application" dist/lpop-darwin-arm64 | |
| # Verify signatures | |
| codesign --verify --verbose dist/lpop-darwin-x64 | |
| codesign --verify --verbose dist/lpop-darwin-arm64 | |
| echo "artifacts=darwin-x64,darwin-arm64" >> $GITHUB_OUTPUT | |
| - name: Notarize macOS binaries | |
| run: | | |
| # Create zip files for notarization (Apple requires zip/dmg format) | |
| zip -j dist/lpop-darwin-x64.zip dist/lpop-darwin-x64 | |
| zip -j dist/lpop-darwin-arm64.zip dist/lpop-darwin-arm64 | |
| # Submit for notarization | |
| echo "Submitting darwin-x64 for notarization..." | |
| xcrun notarytool submit dist/lpop-darwin-x64.zip \ | |
| --apple-id "${{ secrets.APPLE_ID }}" \ | |
| --password "${{ secrets.APPLE_APP_PASSWORD }}" \ | |
| --team-id "${{ secrets.APPLE_TEAM_ID }}" \ | |
| --wait | |
| echo "Submitting darwin-arm64 for notarization..." | |
| xcrun notarytool submit dist/lpop-darwin-arm64.zip \ | |
| --apple-id "${{ secrets.APPLE_ID }}" \ | |
| --password "${{ secrets.APPLE_APP_PASSWORD }}" \ | |
| --team-id "${{ secrets.APPLE_TEAM_ID }}" \ | |
| --wait | |
| # Clean up zip files | |
| rm dist/lpop-darwin-x64.zip dist/lpop-darwin-arm64.zip | |
| - name: Upload macOS artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: macos-binaries | |
| path: | | |
| dist/lpop-darwin-x64 | |
| dist/lpop-darwin-arm64 | |
| build-windows: | |
| needs: check-certificates | |
| if: needs.check-certificates.outputs.has-windows-cert == 'true' | |
| runs-on: windows-latest | |
| outputs: | |
| artifacts: ${{ steps.build.outputs.artifacts }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Import Code-Signing Certificate | |
| run: | | |
| echo "${{ secrets.WINDOWS_CERTIFICATE }}" | base64 -d > certificate.p12 | |
| Import-PfxCertificate -FilePath certificate.p12 -CertStoreLocation Cert:\LocalMachine\My -Password (ConvertTo-SecureString -String "${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}" -AsPlainText -Force) | |
| shell: powershell | |
| - name: Build and sign Windows binaries | |
| id: build | |
| run: | | |
| # Build Windows binary | |
| mkdir -p dist | |
| bun build src/index.ts --target=bun-windows-x64 --compile --minify --outfile=dist/lpop-windows-x64.exe | |
| # Sign the binary | |
| $cert = Get-ChildItem -Path Cert:\LocalMachine\My -CodeSigningCert | Select-Object -First 1 | |
| Set-AuthenticodeSignature -FilePath "dist/lpop-windows-x64.exe" -Certificate $cert -TimestampServer "http://timestamp.digicert.com" | |
| # Verify signature | |
| Get-AuthenticodeSignature -FilePath "dist/lpop-windows-x64.exe" | |
| echo "artifacts=windows-x64" >> $env:GITHUB_OUTPUT | |
| shell: powershell | |
| - name: Upload Windows artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-binaries | |
| path: dist/lpop-windows-x64.exe | |
| build-linux: | |
| needs: check-certificates | |
| if: needs.check-certificates.outputs.has-linux-cert == 'true' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| artifacts: ${{ steps.build.outputs.artifacts }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install | |
| - name: Install signing tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y debsigs gnupg | |
| - name: Import GPG key for signing | |
| run: | | |
| echo "${{ secrets.LINUX_CERTIFICATE }}" | base64 -d | gpg --import --batch | |
| - name: Build and sign Linux binaries | |
| id: build | |
| run: | | |
| # Build Linux binaries | |
| mkdir -p dist | |
| bun build src/index.ts --target=bun-linux-x64 --compile --minify --outfile=dist/lpop-linux-x64 | |
| bun build src/index.ts --target=bun-linux-arm64 --compile --minify --outfile=dist/lpop-linux-arm64 | |
| # Make binaries executable | |
| chmod +x dist/lpop-linux-x64 dist/lpop-linux-arm64 | |
| # Sign the binaries with GPG | |
| gpg --armor --detach-sign dist/lpop-linux-x64 | |
| gpg --armor --detach-sign dist/lpop-linux-arm64 | |
| echo "artifacts=linux-x64,linux-arm64" >> $GITHUB_OUTPUT | |
| - name: Upload Linux artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-binaries | |
| path: | | |
| dist/lpop-linux-x64 | |
| dist/lpop-linux-arm64 | |
| dist/lpop-linux-x64.asc | |
| dist/lpop-linux-arm64.asc | |
| upload-to-release: | |
| needs: [check-certificates, build-macos, build-windows, build-linux] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| merge-multiple: true | |
| path: ./artifacts | |
| - name: Display downloaded artifacts | |
| run: | | |
| echo "📦 Downloaded artifacts:" | |
| find ./artifacts -type f -exec ls -la {} \; | |
| - name: Upload Release Assets | |
| uses: softprops/[email protected] | |
| with: | |
| files: | | |
| ./artifacts/* | |
| fail_on_unmatched_files: false | |
| publish-npm: | |
| needs: upload-to-release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| merge-multiple: true | |
| path: ./dist | |
| - name: Display downloaded binaries | |
| run: | | |
| echo "📦 Downloaded binaries for packaging:" | |
| ls -la ./dist/ | |
| - name: Sync version numbers from main package | |
| run: | | |
| # Get version from main package.json | |
| MAIN_VERSION=$(node -e "console.log(require('./package.json').version)") | |
| echo "Main package version: $MAIN_VERSION" | |
| # Update all platform package versions | |
| for pkg in packages/lpop-*/package.json; do | |
| echo "Updating version in $pkg to $MAIN_VERSION" | |
| node -e " | |
| const fs = require('fs'); | |
| const pkg = JSON.parse(fs.readFileSync('$pkg', 'utf8')); | |
| pkg.version = '$MAIN_VERSION'; | |
| fs.writeFileSync('$pkg', JSON.stringify(pkg, null, 2)); | |
| " | |
| done | |
| - name: Copy signed binaries to platform packages | |
| run: | | |
| # Only copy binaries that were successfully signed | |
| if [ "${{ needs.check-certificates.outputs.has-linux-cert }}" == "true" ] && [ -f dist/lpop-linux-x64 ]; then | |
| echo "Copying signed Linux x64 binary" | |
| cp dist/lpop-linux-x64 packages/lpop-linux-x64/ | |
| fi | |
| if [ "${{ needs.check-certificates.outputs.has-linux-cert }}" == "true" ] && [ -f dist/lpop-linux-arm64 ]; then | |
| echo "Copying signed Linux arm64 binary" | |
| cp dist/lpop-linux-arm64 packages/lpop-linux-arm64/ | |
| fi | |
| if [ "${{ needs.check-certificates.outputs.has-macos-cert }}" == "true" ] && [ -f dist/lpop-darwin-x64 ]; then | |
| echo "Copying signed macOS x64 binary" | |
| cp dist/lpop-darwin-x64 packages/lpop-darwin-x64/ | |
| fi | |
| if [ "${{ needs.check-certificates.outputs.has-macos-cert }}" == "true" ] && [ -f dist/lpop-darwin-arm64 ]; then | |
| echo "Copying signed macOS arm64 binary" | |
| cp dist/lpop-darwin-arm64 packages/lpop-darwin-arm64/ | |
| fi | |
| if [ "${{ needs.check-certificates.outputs.has-windows-cert }}" == "true" ] && [ -f dist/lpop-windows-x64.exe ]; then | |
| echo "Copying signed Windows x64 binary" | |
| cp dist/lpop-windows-x64.exe packages/lpop-windows-x64/ | |
| fi | |
| echo "Platform packages with signed binaries:" | |
| for pkg in packages/lpop-*/; do | |
| if [ -f "$pkg/lpop-"* ]; then | |
| echo " - $(basename $pkg)" | |
| fi | |
| done | |
| - name: Publish platform-specific packages with signed binaries | |
| run: | | |
| # Only publish packages that have signed binaries | |
| published_count=0 | |
| if [ "${{ needs.check-certificates.outputs.has-linux-cert }}" == "true" ]; then | |
| if [ -f packages/lpop-linux-x64/lpop-linux-x64 ]; then | |
| echo "Publishing lpop-linux-x64..." | |
| cd packages/lpop-linux-x64 | |
| npm publish --access public | |
| cd ../.. | |
| published_count=$((published_count + 1)) | |
| fi | |
| if [ -f packages/lpop-linux-arm64/lpop-linux-arm64 ]; then | |
| echo "Publishing lpop-linux-arm64..." | |
| cd packages/lpop-linux-arm64 | |
| npm publish --access public | |
| cd ../.. | |
| published_count=$((published_count + 1)) | |
| fi | |
| fi | |
| if [ "${{ needs.check-certificates.outputs.has-macos-cert }}" == "true" ]; then | |
| if [ -f packages/lpop-darwin-x64/lpop-darwin-x64 ]; then | |
| echo "Publishing lpop-darwin-x64..." | |
| cd packages/lpop-darwin-x64 | |
| npm publish --access public | |
| cd ../.. | |
| published_count=$((published_count + 1)) | |
| fi | |
| if [ -f packages/lpop-darwin-arm64/lpop-darwin-arm64 ]; then | |
| echo "Publishing lpop-darwin-arm64..." | |
| cd packages/lpop-darwin-arm64 | |
| npm publish --access public | |
| cd ../.. | |
| published_count=$((published_count + 1)) | |
| fi | |
| fi | |
| if [ "${{ needs.check-certificates.outputs.has-windows-cert }}" == "true" ]; then | |
| if [ -f packages/lpop-windows-x64/lpop-windows-x64.exe ]; then | |
| echo "Publishing lpop-windows-x64..." | |
| cd packages/lpop-windows-x64 | |
| npm publish --access public | |
| cd ../.. | |
| published_count=$((published_count + 1)) | |
| fi | |
| fi | |
| echo "Published $published_count platform packages with signed binaries" | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| - name: Update package.json with available platform packages | |
| run: | | |
| # Create a temporary package.json with only the available platform packages | |
| node -e " | |
| const fs = require('fs'); | |
| const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); | |
| const optDeps = {}; | |
| if ('${{ needs.check-certificates.outputs.has-linux-cert }}' === 'true') { | |
| if (fs.existsSync('packages/lpop-linux-x64/lpop-linux-x64')) { | |
| optDeps['lpop-linux-x64'] = pkg.version; | |
| } | |
| if (fs.existsSync('packages/lpop-linux-arm64/lpop-linux-arm64')) { | |
| optDeps['lpop-linux-arm64'] = pkg.version; | |
| } | |
| } | |
| if ('${{ needs.check-certificates.outputs.has-macos-cert }}' === 'true') { | |
| if (fs.existsSync('packages/lpop-darwin-x64/lpop-darwin-x64')) { | |
| optDeps['lpop-darwin-x64'] = pkg.version; | |
| } | |
| if (fs.existsSync('packages/lpop-darwin-arm64/lpop-darwin-arm64')) { | |
| optDeps['lpop-darwin-arm64'] = pkg.version; | |
| } | |
| } | |
| if ('${{ needs.check-certificates.outputs.has-windows-cert }}' === 'true') { | |
| if (fs.existsSync('packages/lpop-windows-x64/lpop-windows-x64.exe')) { | |
| optDeps['lpop-windows-x64'] = pkg.version; | |
| } | |
| } | |
| pkg.optionalDependencies = optDeps; | |
| fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)); | |
| console.log('Updated optionalDependencies:', optDeps); | |
| " | |
| - name: Publish main package | |
| run: npm publish --access public | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |