Fix tray icon not appearing on first launch (macOS) #26
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: 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 | |
| with: | |
| fetch-depth: 0 # Need full history for tag comparison | |
| - name: Check for SDK changes | |
| id: sdk-changes | |
| run: | | |
| CURRENT_TAG="${GITHUB_REF_NAME}" | |
| PREVIOUS_TAG=$(git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | grep -v "$CURRENT_TAG" | head -n1) | |
| if [ -z "$PREVIOUS_TAG" ]; then | |
| echo "No previous tag found, publishing SDK" | |
| echo "changed=true" >> $GITHUB_OUTPUT | |
| else | |
| CHANGES=$(git diff --name-only "$PREVIOUS_TAG" "$CURRENT_TAG" -- sdk/) | |
| if [ -n "$CHANGES" ]; then | |
| echo "SDK changes detected:" | |
| echo "$CHANGES" | |
| echo "changed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "No SDK changes since $PREVIOUS_TAG, skipping publish" | |
| echo "changed=false" >> $GITHUB_OUTPUT | |
| fi | |
| fi | |
| - name: Set up Node.js | |
| if: steps.sdk-changes.outputs.changed == 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| registry-url: 'https://npm.pkg.github.com' | |
| scope: '@simplyprint' | |
| - name: Install dependencies and build | |
| if: steps.sdk-changes.outputs.changed == 'true' | |
| working-directory: sdk | |
| run: | | |
| npm ci | |
| npm run build | |
| - name: Update package version | |
| if: steps.sdk-changes.outputs.changed == 'true' | |
| working-directory: sdk | |
| run: | | |
| VERSION="${GITHUB_REF_NAME#v}" | |
| npm version "$VERSION" --no-git-tag-version --allow-same-version | |
| - name: Publish to GitHub Packages | |
| if: steps.sdk-changes.outputs.changed == 'true' | |
| 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 |