diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..b659002 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,87 @@ +# GitHub Actions - Build and Release + +Two GitHub Actions workflows have been configured to automate builds and release creation: + +## Option 1: `build-release.yml` - Commit Message Based (Recommended for your case) + +**Trigger:** Push to the `main` branch + +**Detection:** Looks for a `v1.0.1` pattern in the commit message + +**Usage:** +```bash +git commit -m "Merge pull request... v1.0.2" +git push origin main +``` + +The workflow: +1. ✅ Extracts the version from the commit message +2. ✅ Builds binaries for Linux, macOS (Intel and ARM), and Windows +3. ✅ Automatically creates a release with that version +4. ✅ Automatically generates release notes by comparing commits +5. ✅ Uploads all build artifacts (binaries) to the release + +**Expected commit format:** +- ✅ `v1.0.1` (simple) +- ✅ `Release v1.0.1` +- ✅ `Merge branch... v1.0.1` + +--- + +## Option 2: `release-by-tag.yml` - Git Tag Based + +**Trigger:** When a tag with format `v1.0.1` is created + +**Usage:** +```bash +git tag v1.0.2 +git push origin v1.0.2 +``` + +Or from GitHub: +1. Go to Releases +2. Click "Draft a new release" +3. Enter the tag (v1.0.2) +4. GitHub Actions will automatically create the release + +**Advantage:** More controlled and the industry-standard approach + +--- + +## Prerequisites + +✅ Workflows are already configured +✅ They use the existing go.mod (Go 1.26.2) +✅ `./cmd/sparkle-cli/main.go` is compiled + +## Variables and Configuration + +If you need to change anything: +- **Go version:** Update `1.26.2` in the workflow +- **Output binaries:** Use format `sparkle-cli-{OS}-{ARCH}` +- **Platforms:** Linux amd64, macOS Intel (amd64), macOS ARM (arm64), Windows amd64 + +## Automatic Release Notes + +GitHub automatically generates release notes by comparing: +- Commits since the previous release +- Merged PRs +- Dependency changes + +## Generated Artifacts + +Each release includes: +- `sparkle-cli-linux-amd64` - Linux 64-bit +- `sparkle-cli-darwin-amd64` - macOS Intel +- `sparkle-cli-darwin-arm64` - macOS Apple Silicon +- `sparkle-cli-windows-amd64.exe` - Windows 64-bit + +--- + +## Recommendation + +Use **Option 1** (`build-release.yml`) if you prefer versioning to be part of the commit message. + +Use **Option 2** (`release-by-tag.yml`) if you prefer the standard Git tag flow (recommended long-term). + +You can keep both active simultaneously without conflicts. diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 0000000..2e18000 --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,147 @@ +name: Build and Release + +on: + push: + branches: + - main + +jobs: + check-version: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.extract.outputs.version }} + is-release: ${{ steps.extract.outputs.is-release }} + steps: + - uses: actions/checkout@v4 + + - name: Extract version from commit message + id: extract + run: | + COMMIT_MSG="${{ github.event.head_commit.message }}" + VERSION=$(echo "$COMMIT_MSG" | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1) + + if [ -z "$VERSION" ]; then + echo "No version found" + echo "is-release=false" >> $GITHUB_OUTPUT + else + echo "Version found: $VERSION" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "is-release=true" >> $GITHUB_OUTPUT + fi + + build: + needs: check-version + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + goos: linux + goarch: amd64 + artifact-name: sparkle-cli-linux-amd64 + - os: macos-latest + goos: darwin + goarch: amd64 + artifact-name: sparkle-cli-darwin-amd64 + - os: macos-latest + goos: darwin + goarch: arm64 + artifact-name: sparkle-cli-darwin-arm64 + - os: windows-latest + goos: windows + goarch: amd64 + artifact-name: sparkle-cli-windows-amd64.exe + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.26.2' + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + run: | + go build -o ${{ matrix.artifact-name }} ./cmd/sparkle-cli/ + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact-name }} + path: ${{ matrix.artifact-name }} + retention-days: 1 + + create-release: + needs: [check-version, build] + if: needs.check-version.outputs.is-release == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ./artifacts + + - name: Prepare release assets + run: | + mkdir -p ./release-assets + find ./artifacts -type f -exec cp {} ./release-assets/ \; + ls -la ./release-assets/ + + - name: Create Release + uses: actions/create-release@v1 + id: create_release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ needs.check-version.outputs.version }} + release_name: Release ${{ needs.check-version.outputs.version }} + draft: false + prerelease: false + generate_release_notes: true + + - name: Upload Linux artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-linux-amd64/sparkle-cli-linux-amd64 + asset_name: sparkle-cli-linux-amd64 + asset_content_type: application/octet-stream + + - name: Upload macOS Intel artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-darwin-amd64/sparkle-cli-darwin-amd64 + asset_name: sparkle-cli-darwin-amd64 + asset_content_type: application/octet-stream + + - name: Upload macOS ARM artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-darwin-arm64/sparkle-cli-darwin-arm64 + asset_name: sparkle-cli-darwin-arm64 + asset_content_type: application/octet-stream + + - name: Upload Windows artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-windows-amd64.exe/sparkle-cli-windows-amd64.exe + asset_name: sparkle-cli-windows-amd64.exe + asset_content_type: application/octet-stream diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d9f72be --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: Build (CI) + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + goos: linux + goarch: amd64 + - os: macos-latest + goos: darwin + goarch: amd64 + - os: macos-latest + goos: darwin + goarch: arm64 + - os: windows-latest + goos: windows + goarch: amd64 + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.26.2' + + - name: Get dependencies + run: go mod download + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + run: go build -o sparkle-cli ./cmd/sparkle-cli/ + + - name: Run tests + run: go test -v ./... + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.26.2' + + - name: golangci-lint + uses: golangci/golangci-lint-action@v8 + with: + version: latest + install-mode: goinstall + args: --timeout 5m diff --git a/.github/workflows/release-by-tag.yml b/.github/workflows/release-by-tag.yml new file mode 100644 index 0000000..109e3b6 --- /dev/null +++ b/.github/workflows/release-by-tag.yml @@ -0,0 +1,126 @@ +name: Build and Release (Tag-based) + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+*' + +permissions: + contents: write + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + goos: linux + goarch: amd64 + artifact-name: sparkle-cli-linux-amd64 + - os: macos-latest + goos: darwin + goarch: amd64 + artifact-name: sparkle-cli-darwin-amd64 + - os: macos-latest + goos: darwin + goarch: arm64 + artifact-name: sparkle-cli-darwin-arm64 + - os: windows-latest + goos: windows + goarch: amd64 + artifact-name: sparkle-cli-windows-amd64.exe + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.26.2' + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + run: | + go build -o ${{ matrix.artifact-name }} ./cmd/sparkle-cli/ + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact-name }} + path: ${{ matrix.artifact-name }} + retention-days: 5 + + create-release: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ./artifacts + + - name: Prepare release assets + run: | + mkdir -p ./release-assets + find ./artifacts -type f ! -name '.gitkeep' -exec cp {} ./release-assets/ \; + chmod +x ./release-assets/sparkle-cli-* + ls -la ./release-assets/ + + - name: Create Release with Auto-generated Notes + uses: actions/create-release@v1 + id: create_release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref_name }} + draft: false + prerelease: false + generate_release_notes: true + + - name: Upload Linux artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-linux-amd64 + asset_name: sparkle-cli-linux-amd64 + asset_content_type: application/octet-stream + + - name: Upload macOS Intel artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-darwin-amd64 + asset_name: sparkle-cli-darwin-amd64 + asset_content_type: application/octet-stream + + - name: Upload macOS ARM artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-darwin-arm64 + asset_name: sparkle-cli-darwin-arm64 + asset_content_type: application/octet-stream + + - name: Upload Windows artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release-assets/sparkle-cli-windows-amd64.exe + asset_name: sparkle-cli-windows-amd64.exe + asset_content_type: application/octet-stream