name: Create Release on: workflow_dispatch: inputs: version: description: 'Release version (e.g., v1.0.0)' required: true type: string release_notes: description: 'Release notes (optional)' required: false type: string prerelease: description: 'Is this a pre-release?' required: false type: boolean default: false draft: description: 'Create as draft?' required: false type: boolean default: false jobs: create-release: runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Validate version format run: | VERSION="${{ inputs.version }}" if [[ ! $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then echo "Error: Version must be in format vX.Y.Z or vX.Y.Z-suffix" echo "Examples: v1.0.0, v2.1.3, v1.0.0-beta.1" exit 1 fi echo "Version format is valid: $VERSION" - name: Check if tag exists id: check_tag run: | if git rev-parse "${{ inputs.version }}" >/dev/null 2>&1; then echo "exists=true" >> $GITHUB_OUTPUT echo "Tag ${{ inputs.version }} already exists" else echo "exists=false" >> $GITHUB_OUTPUT echo "Tag ${{ inputs.version }} does not exist, will create it" fi - name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.24' cache: true - name: Build all platforms run: | mkdir -p dist VERSION="${{ inputs.version }}" LDFLAGS="-s -w -X main.Version=${VERSION}" echo "Building for all platforms with version ${VERSION}..." # Linux amd64 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-server-linux-amd64 ./cmd/server CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-client-linux-amd64 ./cmd/client # Linux arm64 CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-server-linux-arm64 ./cmd/server CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-client-linux-arm64 ./cmd/client # Darwin amd64 CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-server-darwin-amd64 ./cmd/server CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-client-darwin-amd64 ./cmd/client # Darwin arm64 CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-server-darwin-arm64 ./cmd/server CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-client-darwin-arm64 ./cmd/client # Windows amd64 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-server-windows-amd64.exe ./cmd/server CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="${LDFLAGS}" \ -o dist/gotunnel-client-windows-amd64.exe ./cmd/client - name: Generate checksums run: | cd dist sha256sum * > SHA256SUMS cat SHA256SUMS cd .. - name: Create compressed archives run: | cd dist VERSION="${{ inputs.version }}" # Linux tar -czf gotunnel-server-${VERSION}-linux-amd64.tar.gz gotunnel-server-linux-amd64 tar -czf gotunnel-client-${VERSION}-linux-amd64.tar.gz gotunnel-client-linux-amd64 tar -czf gotunnel-server-${VERSION}-linux-arm64.tar.gz gotunnel-server-linux-arm64 tar -czf gotunnel-client-${VERSION}-linux-arm64.tar.gz gotunnel-client-linux-arm64 # Darwin tar -czf gotunnel-server-${VERSION}-darwin-amd64.tar.gz gotunnel-server-darwin-amd64 tar -czf gotunnel-client-${VERSION}-darwin-amd64.tar.gz gotunnel-client-darwin-amd64 tar -czf gotunnel-server-${VERSION}-darwin-arm64.tar.gz gotunnel-server-darwin-arm64 tar -czf gotunnel-client-${VERSION}-darwin-arm64.tar.gz gotunnel-client-darwin-arm64 # Windows zip gotunnel-server-${VERSION}-windows-amd64.zip gotunnel-server-windows-amd64.exe zip gotunnel-client-${VERSION}-windows-amd64.zip gotunnel-client-windows-amd64.exe # Clean up raw binaries rm gotunnel-server-* gotunnel-client-* 2>/dev/null || true cd .. - name: List release assets run: | echo "Release assets to be uploaded:" ls -lah dist/ - name: Create tag if: steps.check_tag.outputs.exists == 'false' run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git tag -a ${{ inputs.version }} -m "Release ${{ inputs.version }}" git push origin ${{ inputs.version }} - name: Prepare release notes id: release_notes run: | if [ -n "${{ inputs.release_notes }}" ]; then echo "${{ inputs.release_notes }}" > release_notes.md else echo "Release ${{ inputs.version }}" > release_notes.md echo "" >> release_notes.md echo "## Assets" >> release_notes.md echo "" >> release_notes.md echo "Download the appropriate binary for your platform:" >> release_notes.md echo "" >> release_notes.md echo "- **Linux (amd64/arm64)**: \`.tar.gz\` files" >> release_notes.md echo "- **macOS (amd64/arm64)**: \`.tar.gz\` files" >> release_notes.md echo "- **Windows (amd64)**: \`.zip\` files" >> release_notes.md echo "" >> release_notes.md echo "Verify downloads with \`SHA256SUMS\`" >> release_notes.md fi cat release_notes.md - name: Create Release uses: softprops/action-gh-release@v1 with: tag_name: ${{ inputs.version }} name: Release ${{ inputs.version }} body_path: release_notes.md files: | dist/*.tar.gz dist/*.zip dist/SHA256SUMS draft: ${{ inputs.draft }} prerelease: ${{ inputs.prerelease }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Release created successfully run: | echo "✅ Release ${{ inputs.version }} created successfully!" echo "🔗 View it at: ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ inputs.version }}"