release: Bump version to 0.4.2 #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: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Release version (e.g., v0.1.0)" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| packages: write | |
| jobs: | |
| build: | |
| name: Build Binaries | |
| strategy: | |
| matrix: | |
| include: | |
| - os: linux | |
| arch: amd64 | |
| goos: linux | |
| goarch: amd64 | |
| runner: ubuntu-latest | |
| - os: linux | |
| arch: arm64 | |
| goos: linux | |
| goarch: arm64 | |
| runner: ubuntu-latest | |
| - os: darwin | |
| arch: amd64 | |
| goos: darwin | |
| goarch: amd64 | |
| runner: macos-latest | |
| - os: darwin | |
| arch: arm64 | |
| goos: darwin | |
| goarch: arm64 | |
| runner: macos-latest | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.23" | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.version }}" | |
| else | |
| VERSION="${{ github.ref_name }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "version_clean=${VERSION#v}" >> $GITHUB_OUTPUT | |
| - name: Get build metadata | |
| id: metadata | |
| run: | | |
| echo "commit=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT | |
| echo "date=$(date -u +'%Y-%m-%d')" >> $GITHUB_OUTPUT | |
| echo "author=Leonardo Zanobi" >> $GITHUB_OUTPUT | |
| echo "website=https://commandchronicles.dev" >> $GITHUB_OUTPUT | |
| - name: Import Apple Developer Certificate | |
| if: matrix.os == 'darwin' | |
| uses: apple-actions/import-codesign-certs@v1 | |
| with: | |
| p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} | |
| p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} | |
| keychain: signing_temp | |
| create-keychain: true | |
| - name: Build binary | |
| run: | | |
| BINARY_NAME="ccr-${{ matrix.os }}-${{ matrix.arch }}" | |
| echo "Building ${{ matrix.os }}/${{ matrix.arch }} binary with pure Go..." | |
| # Pure Go build - no CGO needed since we use modernc.org/sqlite | |
| CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go build -ldflags="-X main.version=${{ steps.version.outputs.version_clean }} -X main.commit=${{ steps.metadata.outputs.commit }} -X main.date=${{ steps.metadata.outputs.date }} -X 'main.author=${{ steps.metadata.outputs.author }}' -X main.website=${{ steps.metadata.outputs.website }} -w -s" -o "${BINARY_NAME}" . | |
| # Verify binary was created | |
| ls -la "${BINARY_NAME}" | |
| file "${BINARY_NAME}" || echo "file command not available" | |
| # Show binary info | |
| echo "Binary size: $(du -h ${BINARY_NAME} | cut -f1)" | |
| - name: Sign and Notarize macOS Binary | |
| if: matrix.os == 'darwin' | |
| run: | | |
| BINARY_NAME="ccr-${{ matrix.os }}-${{ matrix.arch }}" | |
| # Check if signing identity is set | |
| if [ -z "${{ secrets.APPLE_SIGNING_IDENTITY }}" ]; then | |
| echo "❌ Error: APPLE_SIGNING_IDENTITY secret is not set!" | |
| echo "Available signing identities on this system:" | |
| security find-identity -v -p codesigning || echo "Could not list identities" | |
| echo "" | |
| echo "Please add APPLE_SIGNING_IDENTITY secret to your repository with a value like:" | |
| echo "Developer ID Application: Your Name (TEAMID)" | |
| exit 1 | |
| fi | |
| # Sign the binary | |
| echo "Signing macOS binary with Developer ID..." | |
| echo "Using signing identity: ${{ secrets.APPLE_SIGNING_IDENTITY }}" | |
| codesign --force --options runtime --sign "${{ secrets.APPLE_SIGNING_IDENTITY }}" "${BINARY_NAME}" | |
| # Verify signature | |
| echo "Verifying signature..." | |
| codesign -vvv --deep --strict "${BINARY_NAME}" | |
| # Prepare for notarization | |
| echo "Preparing for notarization..." | |
| ditto -c -k --keepParent "${BINARY_NAME}" "${BINARY_NAME}.zip" | |
| # Notarize with Apple | |
| echo "Submitting for notarization (this may take a few minutes)..." | |
| NOTARIZATION_SUCCESS=false | |
| SUBMISSION_OUTPUT=$(xcrun notarytool submit "${BINARY_NAME}.zip" \ | |
| --apple-id "${{ secrets.APPLE_ID }}" \ | |
| --password "${{ secrets.APPLE_APP_PASSWORD }}" \ | |
| --team-id "${{ secrets.APPLE_TEAM_ID }}" \ | |
| --wait 2>&1) || NOTARIZE_STATUS=$? | |
| echo "$SUBMISSION_OUTPUT" | |
| # Check if notarization was rejected | |
| if echo "$SUBMISSION_OUTPUT" | grep -q "status: Rejected"; then | |
| echo "⚠️ Notarization was rejected. Fetching log for details..." | |
| SUBMISSION_ID=$(echo "$SUBMISSION_OUTPUT" | grep "id:" | head -1 | awk '{print $2}') | |
| echo "Fetching notarization log for submission ID: $SUBMISSION_ID" | |
| xcrun notarytool log "$SUBMISSION_ID" \ | |
| --apple-id "${{ secrets.APPLE_ID }}" \ | |
| --password "${{ secrets.APPLE_APP_PASSWORD }}" \ | |
| --team-id "${{ secrets.APPLE_TEAM_ID }}" \ | |
| notarization-log.json || true | |
| echo "Notarization log:" | |
| cat notarization-log.json | jq '.' 2>/dev/null || cat notarization-log.json || echo "Could not retrieve log" | |
| echo "" | |
| echo "Common rejection reasons:" | |
| echo "- Binary not signed with hardened runtime (--options runtime)" | |
| echo "- Missing entitlements" | |
| echo "- Invalid code signature" | |
| echo "- Binary compiled with incompatible SDK version" | |
| echo "" | |
| echo "⚠️ WARNING: Continuing with signed but not notarized binary" | |
| echo "Users will see a Gatekeeper warning but can still run the app by right-clicking and selecting Open" | |
| elif echo "$SUBMISSION_OUTPUT" | grep -q "status: Accepted"; then | |
| NOTARIZATION_SUCCESS=true | |
| echo "✅ Notarization accepted!" | |
| fi | |
| # Only staple if notarization was successful | |
| if [ "$NOTARIZATION_SUCCESS" = true ]; then | |
| # Staple the notarization ticket | |
| echo "Stapling notarization ticket..." | |
| if xcrun stapler staple "${BINARY_NAME}"; then | |
| echo "✅ Successfully stapled notarization ticket" | |
| # Verify stapling | |
| echo "Verifying stapled notarization..." | |
| xcrun stapler validate "${BINARY_NAME}" || echo "⚠️ Staple validation failed but continuing" | |
| echo "✅ macOS code signing and notarization completed successfully!" | |
| else | |
| echo "⚠️ Failed to staple notarization ticket but continuing with signed binary" | |
| fi | |
| else | |
| echo "⚠️ Skipping stapling due to notarization failure" | |
| echo "✅ macOS code signing completed (without notarization)" | |
| fi | |
| - name: Generate checksum | |
| run: | | |
| BINARY_NAME="ccr-${{ matrix.os }}-${{ matrix.arch }}" | |
| if [[ "${{ matrix.os }}" == "darwin" ]]; then | |
| shasum -a 256 "${BINARY_NAME}" > "${BINARY_NAME}.sha256" | |
| else | |
| sha256sum "${BINARY_NAME}" > "${BINARY_NAME}.sha256" | |
| fi | |
| echo "Generated checksum for ${BINARY_NAME}:" | |
| cat "${BINARY_NAME}.sha256" | |
| - name: Upload binary artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ccr-${{ matrix.os }}-${{ matrix.arch }} | |
| path: | | |
| ccr-${{ matrix.os }}-${{ matrix.arch }} | |
| ccr-${{ matrix.os }}-${{ matrix.arch }}.sha256 | |
| retention-days: 5 | |
| release: | |
| name: Create Release | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.version }}" | |
| else | |
| VERSION="${{ github.ref_name }}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./artifacts | |
| - name: Prepare release assets | |
| run: | | |
| mkdir -p ./release-assets | |
| find ./artifacts -name "ccr-*" -type f -exec cp {} ./release-assets/ \; | |
| # Create combined checksums file | |
| cd ./release-assets | |
| find . -name "*.sha256" -exec cat {} \; > checksums.txt | |
| echo "Release assets:" | |
| ls -la | |
| echo "Checksums file:" | |
| cat checksums.txt | |
| - name: Generate release notes | |
| id: release_notes | |
| run: | | |
| # Get the git tag message | |
| TAG_MESSAGE=$(git tag -l --format='%(contents)' ${{ steps.version.outputs.version }}) | |
| # Create release notes with tag message and standard sections | |
| cat << EOF > release_notes.md | |
| ## ccr ${{ steps.version.outputs.version }} | |
| ${TAG_MESSAGE} | |
| ### 📦 Binaries | |
| | Platform | Architecture | Download | | |
| |----------|-------------|----------| | |
| | Linux | x86_64 | [ccr-linux-amd64](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.version }}/ccr-linux-amd64) | | |
| | Linux | ARM64 | [ccr-linux-arm64](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.version }}/ccr-linux-arm64) | | |
| | macOS | Intel | [ccr-darwin-amd64](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.version }}/ccr-darwin-amd64) | | |
| | macOS | Apple Silicon | [ccr-darwin-arm64](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.version }}/ccr-darwin-arm64) | | |
| ### 📋 Checksums | |
| Download [checksums.txt](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.version }}/checksums.txt) to verify binary integrity. | |
| ### 📚 Documentation | |
| See the [README](https://github.com/${{ github.repository }}/blob/main/README.md) for installation and usage instructions. | |
| --- | |
| **Full Changelog**: https://github.com/${{ github.repository }}/commits/${{ steps.version.outputs.version }} | |
| EOF | |
| echo "Generated release notes:" | |
| cat release_notes.md | |
| - name: Create GitHub Release | |
| run: | | |
| # Check if release already exists and delete it | |
| if gh release view "${{ steps.version.outputs.version }}" > /dev/null 2>&1; then | |
| echo "Release ${{ steps.version.outputs.version }} already exists, deleting it" | |
| gh release delete "${{ steps.version.outputs.version }}" --yes || true | |
| fi | |
| # Determine if this is a prerelease | |
| PRERELEASE_FLAG="" | |
| if [[ "${{ steps.version.outputs.version }}" =~ -(rc|beta|alpha|dev) ]]; then | |
| PRERELEASE_FLAG="--prerelease" | |
| fi | |
| # Create the release | |
| echo "Creating release with assets from ./release-assets/" | |
| assets="" | |
| for file in ./release-assets/*; do | |
| if [ -f "$file" ]; then | |
| assets="$assets $file" | |
| fi | |
| done | |
| echo "Assets to upload: $assets" | |
| gh release create "${{ steps.version.outputs.version }}" \ | |
| --title "🚀 CommandChronicles CLI ${{ steps.version.outputs.version }} - Secure Shell History Management" \ | |
| --notes-file release_notes.md \ | |
| $PRERELEASE_FLAG \ | |
| $assets | |
| echo "✅ Release created successfully" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Cleanup artifacts | |
| if: always() | |
| run: | | |
| echo "Cleaning up artifacts..." | |
| # No need to delete artifacts as they'll expire automatically | |
| notify: | |
| name: Post-Release Notifications | |
| needs: [build, release] | |
| runs-on: ubuntu-latest | |
| if: success() | |
| steps: | |
| - name: Release Success | |
| run: | | |
| echo "🎉 Release ${{ github.ref_name }} completed successfully!" | |
| echo "📦 Binaries built for 4 platforms (Linux and macOS)" | |
| echo "✅ GitHub release created with enhanced formatting" | |
| echo "🔗 Release URL: https://github.com/${{ github.repository }}/releases/tag/${{ github.ref_name }}" | |
| echo "📊 Release features: Direct download links, security verification, quick start guide" | |
| echo "🚀 Installation command: curl -fsSL https://raw.githubusercontent.com/${{ github.repository }}/main/scripts/install.sh | sh" |