Add reusable Go CI/CD pipeline GitHub Action

Introduce a composite action for Go projects supporting multiple workflows: protected branches, minimal CI, and tagged releases. Includes automated tests, builds (library/application), and optional Docker image publishing. Detailed documentation provided for seamless integration.
This commit is contained in:
Rene Nochebuena 2025-04-22 19:19:37 -06:00
parent e9209ea2c3
commit 9cf4faab85
Signed by: Rene Nochebuena
GPG Key ID: A9FD83117EA538D8
2 changed files with 185 additions and 1 deletions

View File

@ -1,2 +1,84 @@
# go-ci # Go CI/CD Composite Action
A reusable GitHub Action for Go projects, forged to handle various CI/CD scenarios like a true warrior of code. Supports protected branches, tagged releases, and minimal development flows — with optional Docker image publishing for applications.
## 🔧 Features
- Multiple workflow modes: `protected`, `tag`, and `minimal`
- Go version configuration
- Automatic test execution with code coverage
- Build support for both libraries and applications
- Conditional Docker image creation and publishing
- Composable and easy to integrate in any Go project
## 📥 Inputs
| Input Name | Description | Required | Default |
|---------------------|-------------------------------------------------------------------------|----------|---------------|
| `workflow-type` | Type of CI/CD flow (`protected`, `minimal`, `tag`) | Yes | `protected` |
| `go-version` | Go version to install and use | No | `1.24` |
| `build-type` | Type of build (`application`, `library`) | No | `application` |
| `container-registry`| Container registry URL (used if publishing Docker image) | Yes | — |
| `publish-docker` | Whether to build and push Docker image (`true` / `false`) | No | `true` |
## ⚙️ Workflow Types
- **protected**: Full CI/CD pipeline for mainline branches. Runs tests, builds the binary, and optionally publishes a Docker image.
- **minimal**: Lean setup for pull requests or early development. Runs tests and builds only.
- **tag**: Triggered on Git tags. Behaves like `protected`, ideal for versioned releases.
## 🚀 How to Use
```yaml
name: Go CI/CD Pipeline
on: [push, pull_request, workflow_dispatch]
jobs:
go-ci:
runs-on: ubuntu-latest
steps:
- uses: your-org/go-ci-action@v1
with:
workflow-type: 'protected'
go-version: '1.24'
build-type: 'application'
container-registry: ghcr.io/your-org
publish-docker: 'true'
```
> Replace your-org/go-ci-action and ghcr.io/your-org with your actual repository and registry.
## 🛠️ Step Breakdown
1. **Checkout code** Pulls the code from your repo.
2. **Set up Go** Installs and configures the specified Go version.
3. **Download dependencies** Runs `go mod tidy` to sync modules.
4. **Run tests** Executes unit tests with JSON and coverage output.
5. **Build** Builds all packages (`library`) or compiles an app binary (`application`).
6. **Generate image tag** Creates a Docker tag based on branch/tag/ref.
7. **Login to registry** Authenticates with your container registry.
8. **Build & push image** Pushes the image if `publish-docker` is enabled.
## 🔐 Requirements
You must configure these in your environment for the action to work correctly:
### Environment Variables
- `DEPLOYER_USERNAME`: Your Docker registry username
### Secrets
- `DEPLOYER_TOKEN`: Your Docker registry password or access token
## 🧙 Best Practices
- Use `minimal` for development and PRs to save resources.
- Use `tag` for releases to generate versioned images.
- Disable `publish-docker` when working on Go libraries or services not meant to be containerized.
---
Crafted with reusability, clarity, and precision in mind. May your builds be swift and your tests ever green.
_“We dont just build software — we forge legacy.”_

102
action.yml Normal file
View File

@ -0,0 +1,102 @@
name: 'Go CI/CD Pipeline'
description: 'Standardized workflow for Go projects (protected branches, tags, minimal CI)'
inputs:
workflow-type:
description: 'Workflow type (protected, minimal, tag), default: protected'
required: true
default: 'protected'
go-version:
description: 'Go version'
required: false
default: '1.24'
build-type:
description: 'Build type (library/application), default: application'
required: false
default: 'application'
container-registry:
description: 'Container registry url'
required: true
publish-docker:
description: 'Publish Docker image (true/false)'
required: false
default: 'true'
runs:
using: 'composite'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup go
uses: actions/setup-go@v5
with:
go-version: ${{ inputs.go-version }}
- name: Download dependencies
shell: bash
run: |
go mod tidy -x
- name: Run tests
shell: bash
run: |
go test -json > test-report.out
go test -coverprofile=coverage.out
- name: Build library
if: inputs.build-type == 'library'
shell: bash
run: |
go build ./...
- name: Build application
if: inputs.build-type == 'application'
shell: bash
run: |
go build -o ./bin/app main.go
- name: Generate container image tag
if: inputs.publish-docker == 'true' && inputs.build-type == 'application' && (inputs.workflow-type == 'protected' || inputs.workflow-type == 'tag')
id: generate-tag
shell: bash
run: |
repository="${{ github.repository }}"
ref="${{ github.ref }}"
if [[ "$ref" == "refs/heads/develop" ]]; then
tag="$(git rev-parse --short HEAD)"
elif [[ "$ref" == "refs/heads/main" ]]; then
tag="latest"
elif [[ "$ref" == refs/heads/release/* ]]; then
version="${ref#refs/heads/release/}"
tag="${version}-release"
elif [[ "$ref" == refs/tags/* ]]; then
tag="${ref#refs/tags/}"
else
echo "Unsupported ref: $ref"
exit 1
fi
echo "container-tag=${repository}:${tag}" >> $GITHUB_OUTPUT
- name: Login to Registry
if: inputs.publish-docker == 'true' && inputs.build-type == 'application' && (inputs.workflow-type == 'protected' || inputs.workflow-type == 'tag')
uses: docker/login-action@v3
with:
registry: ${{ inputs.container-registry }}
username: ${{ env.DEPLOYER_USERNAME }}
password: ${{ secrets.DEPLOYER_TOKEN }}
- name: Set up Docker Buildx
if: inputs.publish-docker == 'true' && inputs.build-type == 'application' && (inputs.workflow-type == 'protected' || inputs.workflow-type == 'tag')
uses: docker/setup-buildx-action@v3
- name: Build and push container image
if: inputs.publish-docker == 'true' && inputs.build-type == 'application' && (inputs.workflow-type == 'protected' || inputs.workflow-type == 'tag')
uses: docker/build-push-action@v6
with:
push: true
tags: "${{ inputs.container-registry }}/${{ steps.generate-tag.outputs.container-tag }}"