Skip to content

v0.1.3

v0.1.3 #4

Workflow file for this run

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 }}