Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# GitHub Actions Workflows

This directory contains the CI/CD workflows for the CloudAMQP CLI.

## Workflows

### CI Workflow (`ci.yml`)

Runs on every push to `main` or `develop` branches, and on pull requests.

**What it does:**
- Tests with multiple Go versions (1.21, 1.22, 1.23)
- Runs format checks, vet, and tests
- Builds the binary with version information
- Uploads test coverage to Codecov
- Verifies the binary works with `--help` and `version` commands

**Version Information:**
The CI build automatically includes:
- Version: From `git describe --tags --always --dirty` (or "dev" as fallback)
- Build Date: Current date in UTC (YYYY-MM-DD)
- Git Commit: Short commit hash

### Release Workflow (`release.yml`)

Triggers when a tag starting with `v` is pushed (e.g., `v1.0.0`), or can be run manually.

**What it does:**
1. **Build Job**: Builds cross-platform binaries for:
- Linux (amd64, arm64)
- macOS (amd64, arm64)
- Windows (amd64, arm64)

2. **Package Job**: Creates release archives:
- `.tar.gz` for Linux/macOS binaries
- `.zip` for Windows binaries
- Creates GitHub Release with all artifacts

**Version Information:**
Release builds automatically include:
- Version: From the git tag (e.g., `v1.0.0`)
- Build Date: Current date in UTC (YYYY-MM-DD)
- Git Commit: Short commit hash

The version info is embedded using Go's `-ldflags`:
```bash
-ldflags="-w -s -X cloudamqp-cli/cmd.Version=$VERSION -X cloudamqp-cli/cmd.BuildDate=$BUILD_DATE -X cloudamqp-cli/cmd.GitCommit=$GIT_COMMIT"
```

## Creating a Release

To create a new release:

1. **Create and push a tag:**
```bash
git tag v1.0.0
git push origin v1.0.0
```

2. The release workflow will automatically:
- Build binaries for all platforms
- Create archives
- Create a GitHub release with auto-generated release notes
- Upload all artifacts

3. The released binaries will show proper version info:
```bash
$ cloudamqp version
cloudamqp version v1.0.0 (2025-11-26)
https://github.com/cloudamqp/cli/releases/tag/v1.0.0
```

## Manual Workflow Trigger

The release workflow can also be triggered manually from the GitHub Actions UI:
1. Go to Actions tab
2. Select "Build Release" workflow
3. Click "Run workflow"
4. Select branch and click "Run workflow"

## Verification

Both workflows include verification steps:
- **CI**: Tests the built binary with `--help` and `version` commands
- **Release**: Attempts to run `version` command on non-Windows binaries (may skip for cross-compiled binaries)

## Caching

Both workflows use Go module caching to speed up builds:
- Cache key includes Go version and `go.sum` hash
- Cached paths: `~/.cache/go-build` and `~/go/pkg/mod`

## Build Flags

**CI builds:**
- Standard build flags
- Version information included

**Release builds:**
- `-a`: Force rebuilding of packages
- `-installsuffix cgo`: Use suffix for cgo-enabled builds
- `-ldflags="-w -s"`: Strip debug info and symbol tables (smaller binaries)
- Version information via `-X` flags
- `CGO_ENABLED=0`: Disable cgo for static binaries

## Artifacts

**CI Workflow:**
- Uploads test coverage to Codecov

**Release Workflow:**
- Individual binaries (30 days retention)
- Release archives (90 days retention)
- GitHub Release assets (permanent)

## Troubleshooting

If version information is not showing correctly in releases:

1. Check that tags are pushed: `git push origin --tags`
2. Verify tag format: Must start with `v` (e.g., `v1.0.0`)
3. Check workflow logs for version extraction step
4. Ensure no local modifications (avoid `-dirty` in version)

## Local Testing

To test version embedding locally:

```bash
# Using Make (recommended)
make build

# Manual
VERSION=v1.0.0
BUILD_DATE=$(date -u +"%Y-%m-%d")
GIT_COMMIT=$(git rev-parse --short HEAD)

go build -ldflags "\
-X cloudamqp-cli/cmd.Version=$VERSION \
-X cloudamqp-cli/cmd.BuildDate=$BUILD_DATE \
-X cloudamqp-cli/cmd.GitCommit=$GIT_COMMIT" \
-o cloudamqp .
```
20 changes: 18 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,24 @@ jobs:
with:
file: ./coverage.out

- name: Extract version information
id: version
run: |
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
BUILD_DATE=$(date -u +"%Y-%m-%d")
GIT_COMMIT=$(git rev-parse --short HEAD)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "build_date=$BUILD_DATE" >> $GITHUB_OUTPUT
echo "git_commit=$GIT_COMMIT" >> $GITHUB_OUTPUT
echo "Building with version: $VERSION (commit: $GIT_COMMIT, date: $BUILD_DATE)"

- name: Build
run: go build -v -o cloudamqp .
run: |
go build -v \
-ldflags="-X cloudamqp-cli/cmd.Version=${{ steps.version.outputs.version }} -X cloudamqp-cli/cmd.BuildDate=${{ steps.version.outputs.build_date }} -X cloudamqp-cli/cmd.GitCommit=${{ steps.version.outputs.git_commit }}" \
-o cloudamqp .

- name: Test binary
run: ./cloudamqp --help
run: |
./cloudamqp --help
./cloudamqp version
31 changes: 30 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,42 @@ jobs:
- name: Download dependencies
run: go mod download

- name: Extract version information
id: version
run: |
# Extract version from tag (remove 'v' prefix if present)
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION="${GITHUB_REF#refs/tags/}"
else
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT

# Get build date in UTC
BUILD_DATE=$(date -u +"%Y-%m-%d")
echo "build_date=$BUILD_DATE" >> $GITHUB_OUTPUT

# Get short commit hash
GIT_COMMIT=$(git rev-parse --short HEAD)
echo "git_commit=$GIT_COMMIT" >> $GITHUB_OUTPUT

echo "Building version: $VERSION (commit: $GIT_COMMIT, date: $BUILD_DATE)"

- name: Build binary
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0
run: |
go build -a -installsuffix cgo -ldflags="-w -s" -o cloudamqp-${{ matrix.name }}${{ matrix.ext }} .
go build -a -installsuffix cgo \
-ldflags="-w -s -X cloudamqp-cli/cmd.Version=${{ steps.version.outputs.version }} -X cloudamqp-cli/cmd.BuildDate=${{ steps.version.outputs.build_date }} -X cloudamqp-cli/cmd.GitCommit=${{ steps.version.outputs.git_commit }}" \
-o cloudamqp-${{ matrix.name }}${{ matrix.ext }} .

- name: Verify version (Linux/macOS only)
if: matrix.goos != 'windows'
run: |
chmod +x cloudamqp-${{ matrix.name }}${{ matrix.ext }}
./cloudamqp-${{ matrix.name }}${{ matrix.ext }} version || echo "Version verification skipped for cross-compiled binary"

- name: Upload artifact
uses: actions/upload-artifact@v4
Expand Down
119 changes: 119 additions & 0 deletions BUILD_VERSION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Building with Version Information

The `cloudamqp` CLI supports version information that can be set at build time using Go's `-ldflags`.

## Version Variables

The following variables are available in `cmd/version.go`:
- `Version` - The version number (e.g., "1.0.0")
- `BuildDate` - The build date (e.g., "2025-11-25")
- `GitCommit` - The git commit hash (optional)

## Build Examples

### Using Make (Recommended)

The Makefile automatically extracts version information from git:

```bash
# Build with automatic git version
make build
```

Output:
```
$ ./cloudamqp version
cloudamqp version v0.1.0-8-g285bd2b (2025-11-26)
https://github.com/cloudamqp/cli/releases/tag/v0.1.0-8-g285bd2b
```

Show version information before building:
```bash
make version-info
```

Override version manually:
```bash
make build VERSION=1.0.0 BUILD_DATE=2025-11-25
```

### Manual Build (without Make)

#### Development Build
```bash
go build -o cloudamqp-cli
```
Output:
```
$ cloudamqp-cli version
cloudamqp version dev (development build)
```

#### Release Build
```bash
go build -ldflags "\
-X cloudamqp-cli/cmd.Version=1.0.0 \
-X cloudamqp-cli/cmd.BuildDate=2025-11-25 \
-X cloudamqp-cli/cmd.GitCommit=abc123" \
-o cloudamqp-cli
```
Output:
```
$ cloudamqp-cli version
cloudamqp version 1.0.0 (2025-11-25)
https://github.com/cloudamqp/cli/releases/tag/v1.0.0
```

### Using Git Information
```bash
VERSION=$(git describe --tags --always --dirty)
BUILD_DATE=$(date -u +"%Y-%m-%d")
GIT_COMMIT=$(git rev-parse --short HEAD)

go build -ldflags "\
-X cloudamqp-cli/cmd.Version=${VERSION} \
-X cloudamqp-cli/cmd.BuildDate=${BUILD_DATE} \
-X cloudamqp-cli/cmd.GitCommit=${GIT_COMMIT}" \
-o cloudamqp-cli
```

## Usage

The version can be displayed in two ways:

```bash
# Using the version command
cloudamqp version

# Using the --version or -v flag
cloudamqp --version
cloudamqp -v
```

Both produce identical output, similar to GitHub CLI (`gh`).

## CI/CD Integration

### GitHub Actions Example
```yaml
- name: Build
run: |
VERSION=${GITHUB_REF#refs/tags/}
BUILD_DATE=$(date -u +"%Y-%m-%d")
GIT_COMMIT=${GITHUB_SHA::7}

go build -ldflags "\
-X cloudamqp-cli/cmd.Version=${VERSION} \
-X cloudamqp-cli/cmd.BuildDate=${BUILD_DATE} \
-X cloudamqp-cli/cmd.GitCommit=${GIT_COMMIT}" \
-o cloudamqp-cli
```

### GoReleaser Example
```yaml
builds:
- ldflags:
- -X cloudamqp-cli/cmd.Version={{.Version}}
- -X cloudamqp-cli/cmd.BuildDate={{.Date}}
- -X cloudamqp-cli/cmd.GitCommit={{.ShortCommit}}
```
Loading
Loading