Skip to content

Add opt-in crash reporting with Sentry integration #24

Add opt-in crash reporting with Sentry integration

Add opt-in crash reporting with Sentry integration #24

Workflow file for this run

name: Build and Release
on:
push:
tags: ['v*'] # Only run on version tags for releases
workflow_dispatch: # allow manually triggering builds
permissions:
contents: write
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Install PC/SC development files
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
- name: Run tests
run: go test -v -race -coverprofile=coverage.out ./...
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: ./coverage.out
fail_ci_if_error: false
build:
name: Build (${{ matrix.name }})
needs: test
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
name: linux-x64
- os: macos-15-intel
goos: darwin
goarch: amd64
name: macos-intel
- os: macos-latest
goos: darwin
goarch: arm64
name: macos-apple-silicon
- os: windows-latest
goos: windows
goarch: amd64
name: windows-x64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
# Linux dependencies
- name: Install Linux dependencies
if: matrix.goos == 'linux'
run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
# Generate Windows resource file (icon + version info)
- name: Generate Windows resources
if: matrix.goos == 'windows'
shell: bash
run: |
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest
VERSION="${GITHUB_REF_NAME:-v0.0.0}"
VERSION="${VERSION#v}" # Remove 'v' prefix
# Validate version format (x.y.z), default to 0.0.0 for non-tag builds
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
IFS='.' read -r MAJOR MINOR PATCH <<< "${VERSION}"
else
MAJOR=0; MINOR=0; PATCH=0; VERSION="0.0.0"
fi
cat > cmd/nfc-agent/versioninfo.json << EOF
{
"FixedFileInfo": {
"FileVersion": {"Major": ${MAJOR}, "Minor": ${MINOR}, "Patch": ${PATCH}, "Build": 0},
"ProductVersion": {"Major": ${MAJOR}, "Minor": ${MINOR}, "Patch": ${PATCH}, "Build": 0}
},
"StringFileInfo": {
"ProductName": "NFC Agent",
"FileDescription": "NFC card reader service for SimplyPrint",
"CompanyName": "SimplyPrint",
"LegalCopyright": "Copyright © SimplyPrint",
"ProductVersion": "${VERSION}"
},
"IconPath": "../../build/windows/icon.ico"
}
EOF
cd cmd/nfc-agent && goversioninfo -64
- name: Build
shell: bash
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 1
run: |
VERSION="${GITHUB_REF_NAME:-dev}"
VERSION="${VERSION#v}" # Remove 'v' prefix if present
BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
GIT_COMMIT="${GITHUB_SHA:-unknown}"
# Add -H windowsgui on Windows to hide console window
EXTRA_LDFLAGS=""
if [ "$GOOS" = "windows" ]; then
EXTRA_LDFLAGS="-H windowsgui"
fi
go build -ldflags="-s -w ${EXTRA_LDFLAGS} -X 'github.com/SimplyPrint/nfc-agent/internal/api.Version=${VERSION}' -X 'github.com/SimplyPrint/nfc-agent/internal/api.BuildTime=${BUILD_TIME}' -X 'github.com/SimplyPrint/nfc-agent/internal/api.GitCommit=${GIT_COMMIT}'" -o dist/nfc-agent${{ matrix.goos == 'windows' && '.exe' || '' }} ./cmd/nfc-agent
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: nfc-agent-${{ matrix.name }}
path: dist/
# macOS code signing and DMG creation
macos-package:
name: Package macOS
needs: build
if: startsWith(github.ref, 'refs/tags/')
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Download macOS Apple Silicon artifact
uses: actions/download-artifact@v4
with:
name: nfc-agent-macos-apple-silicon
path: dist/arm64/
- name: Download macOS Intel artifact
uses: actions/download-artifact@v4
with:
name: nfc-agent-macos-intel
path: dist/amd64/
- name: Create universal binary
run: |
mkdir -p dist/universal
lipo -create dist/arm64/nfc-agent dist/amd64/nfc-agent -output dist/universal/nfc-agent
chmod +x dist/universal/nfc-agent
- name: Import Code Signing Certificate
if: env.APPLE_CERTIFICATE != ''
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12
security create-keychain -p "" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "" build.keychain
security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
- name: Create App Bundle
run: |
mkdir -p "dist/NFC Agent.app/Contents/MacOS"
mkdir -p "dist/NFC Agent.app/Contents/Resources"
cp dist/universal/nfc-agent "dist/NFC Agent.app/Contents/MacOS/"
cp build/darwin/Info.plist "dist/NFC Agent.app/Contents/"
cp build/darwin/AppIcon.icns "dist/NFC Agent.app/Contents/Resources/"
# Update version in Info.plist
VERSION="${GITHUB_REF_NAME#v}"
sed -i '' "s/1.0.0/${VERSION}/g" "dist/NFC Agent.app/Contents/Info.plist"
- name: Sign App Bundle
if: env.APPLE_CERTIFICATE != ''
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }}
run: |
codesign --force --options runtime --sign "$APPLE_IDENTITY" --entitlements build/darwin/entitlements.plist "dist/NFC Agent.app"
- name: Create DMG
run: |
VERSION="${GITHUB_REF_NAME#v}"
# Install create-dmg for nice "drag to Applications" UX
brew install create-dmg
# Create DMG with Applications symlink
create-dmg \
--volname "NFC Agent" \
--volicon "build/darwin/AppIcon.icns" \
--window-pos 200 120 \
--window-size 600 400 \
--icon-size 100 \
--icon "NFC Agent.app" 150 185 \
--hide-extension "NFC Agent.app" \
--app-drop-link 450 185 \
"dist/NFC-Agent-${VERSION}-macos.dmg" \
"dist/NFC Agent.app" \
|| true # create-dmg returns non-zero even on success sometimes
- name: Notarize DMG
if: env.APPLE_ID != ''
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
run: |
VERSION="${GITHUB_REF_NAME#v}"
xcrun notarytool submit "dist/NFC-Agent-${VERSION}-macos.dmg" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_PASSWORD" --wait
xcrun stapler staple "dist/NFC-Agent-${VERSION}-macos.dmg"
- name: Upload DMG artifact
uses: actions/upload-artifact@v4
with:
name: nfc-agent-macos-dmg
path: dist/*.dmg
# Windows installer
windows-package:
name: Package Windows
needs: build
if: startsWith(github.ref, 'refs/tags/')
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Download Windows artifact
uses: actions/download-artifact@v4
with:
name: nfc-agent-windows-x64
path: dist/nfc-agent_windows_amd64_v1/
- name: Install Inno Setup
run: choco install innosetup -y
- name: Build installer
run: |
$version = "${{ github.ref_name }}".TrimStart('v')
& "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" /DVersion=$version build\windows\installer.iss
- name: Upload installer artifact
uses: actions/upload-artifact@v4
with:
name: nfc-agent-windows-installer
path: dist/*.exe
# Linux packages
linux-package:
name: Package Linux
needs: build
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libpcsclite-dev
- name: Install GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
install-only: true
- name: Build packages with GoReleaser
run: |
goreleaser release --clean --skip=publish --config .goreleaser.yaml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload deb package
uses: actions/upload-artifact@v4
with:
name: nfc-agent-linux-deb
path: dist/*.deb
- name: Upload rpm package
uses: actions/upload-artifact@v4
with:
name: nfc-agent-linux-rpm
path: dist/*.rpm
- name: Upload tar.gz archive
uses: actions/upload-artifact@v4
with:
name: nfc-agent-linux-tarball
path: dist/*.tar.gz
# Create release
release:
name: Create Release
needs: [macos-package, windows-package, linux-package]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts/
- name: Prepare release files
run: |
mkdir -p release
VERSION="${GITHUB_REF_NAME#v}"
# Copy installer packages
find artifacts -type f \( -name "*.dmg" -o -name "*-setup.exe" -o -name "*.deb" -o -name "*.rpm" -o -name "*.tar.gz" \) -exec cp {} release/ \;
# Also include standalone Windows exe with friendly name
if [ -f "artifacts/nfc-agent-windows-x64/nfc-agent.exe" ]; then
cp "artifacts/nfc-agent-windows-x64/nfc-agent.exe" "release/NFC-Agent-${VERSION}-windows.exe"
fi
ls -la release/
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: release/*
generate_release_notes: true
draft: false
prerelease: ${{ contains(github.ref, '-') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Publish SDK to GitHub Packages (npm)
npm-publish:
name: Publish SDK
needs: release
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-')
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://npm.pkg.github.com'
scope: '@simplyprint'
- name: Install dependencies and build
working-directory: sdk
run: |
npm ci
npm run build
- name: Update package version
working-directory: sdk
run: |
VERSION="${GITHUB_REF_NAME#v}"
npm version "$VERSION" --no-git-tag-version --allow-same-version
- name: Publish to GitHub Packages
working-directory: sdk
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Update Homebrew tap
homebrew:
name: Update Homebrew
needs: release
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-')
runs-on: ubuntu-latest
steps:
- name: Update Homebrew Cask
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
VERSION: ${{ github.ref_name }}
run: |
VERSION="${VERSION#v}"
DMG_URL="https://github.com/SimplyPrint/nfc-agent/releases/download/v${VERSION}/NFC-Agent-${VERSION}-macos.dmg"
# Download and calculate SHA256
SHA256=$(curl -sL "$DMG_URL" | shasum -a 256 | cut -d' ' -f1)
# Clone tap repo
git clone "https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/SimplyPrint/homebrew-tap.git" tap
cd tap
# Update Cask file
cat > Casks/nfc-agent.rb << EOF
cask "nfc-agent" do
version "${VERSION}"
sha256 "${SHA256}"
url "https://github.com/SimplyPrint/nfc-agent/releases/download/v#{version}/NFC-Agent-#{version}-macos.dmg"
name "NFC Agent"
desc "NFC card reader agent for SimplyPrint"
homepage "https://github.com/SimplyPrint/nfc-agent"
livecheck do
url :url
strategy :github_latest
end
app "NFC Agent.app"
zap trash: [
"~/Library/Application Support/NFC Agent",
"~/Library/Preferences/com.simplyprint.nfc-agent.plist",
"~/Library/LaunchAgents/com.simplyprint.nfc-agent.plist",
]
end
EOF
# Commit and push
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Casks/nfc-agent.rb
git commit -m "Update nfc-agent to ${VERSION}"
git push