Centralized repository for GitHub Actions reusable workflows used across CPS-Innovation repositories.
| Workflow | Description |
|---|---|
| dotnet-build.yml | Build, test, and package .NET applications |
| terraform-plan.yml | Terraform plan with change detection |
| terraform-apply.yml | Terraform apply with approval gates |
| terraform-destroy.yml | Terraform destroy with approval gates |
Build, test, and package .NET applications.
jobs:
build:
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/dotnet-build.yml@v1
with:
solution-file: 'src/MyApp.sln'
secrets: inherit| Input | Required | Default | Description |
|---|---|---|---|
runner |
No | cps-cent-runner-nonprod |
Runner to use |
solution-file |
Yes | - | Path to .sln or .csproj file |
dotnet-version |
No | 8.0.x |
.NET SDK version (GitHub-hosted only) |
configuration |
No | Release |
Build configuration |
run-tests |
No | true |
Run unit tests |
use-github-packages |
No | false |
Add GitHub Packages NuGet source |
timeout |
No | 30 |
Job timeout in minutes |
jobs:
build:
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/dotnet-build.yml@v1
with:
solution-file: 'src/MyApp.sln'
use-github-packages: true
run-tests: true
timeout: 15
secrets: inheritInfrastructure deployment with plan, apply, and destroy stages.
- Azure OIDC Authentication - Configure federated credentials in your Azure AD app
- GitHub Secrets - Add to your repository:
AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_ID
- GitHub Environment - Create environments (e.g.,
non-prod,prod) with approval gates
| Input | Required | Default | Description |
|---|---|---|---|
runner |
No | cps-cent-runner-nonprod |
Runner to use |
working-directory |
No | . |
Terraform working directory |
var-file |
Yes | - | Path to tfvars file |
environment |
Yes | - | Environment name / GitHub environment |
state-resource-group |
Yes | - | Resource group containing state storage |
state-storage-account |
Yes | - | Storage account name for tfstate |
state-container |
No | tfstate |
Storage container name |
state-key |
Yes | - | State file name (e.g., nonprod.tfstate) |
timeout |
No | 30 |
Job timeout in minutes |
| Secret | Description |
|---|---|
AZURE_CLIENT_ID |
Azure AD app client ID |
AZURE_TENANT_ID |
Azure AD tenant ID |
AZURE_SUBSCRIPTION_ID |
Azure subscription ID |
Run terraform plan and detect changes.
jobs:
plan:
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/terraform-plan.yml@v1
with:
var-file: 'environments/non-prod.tfvars'
environment: 'nonprod'
state-resource-group: 'rg-tfstate-nonprod'
state-storage-account: 'sttfstatenonprod'
state-container: 'tfstate'
state-key: 'myapp-nonprod.tfstate'
secrets:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}Output: has_changes - true if changes detected, false otherwise.
Apply changes with environment approval gates.
jobs:
apply:
needs: plan
if: needs.plan.outputs.has_changes == 'true'
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/terraform-apply.yml@v1
with:
var-file: 'environments/non-prod.tfvars'
environment: 'non-prod' # GitHub environment with approvers
state-resource-group: 'rg-tfstate-nonprod'
state-storage-account: 'sttfstatenonprod'
state-container: 'tfstate'
state-key: 'myapp-nonprod.tfstate'
secrets:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}Destroy infrastructure (manual trigger recommended).
jobs:
destroy:
if: github.event_name == 'workflow_dispatch'
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/terraform-destroy.yml@v1
with:
var-file: 'environments/non-prod.tfvars'
environment: 'non-prod'
state-resource-group: 'rg-tfstate-nonprod'
state-storage-account: 'sttfstatenonprod'
state-container: 'tfstate'
state-key: 'myapp-nonprod.tfstate'
secrets:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}Complete pipeline with plan, apply, and destroy:
name: Terraform Deploy
on:
push:
branches: [main]
paths-ignore:
- '*.md'
workflow_dispatch:
inputs:
action:
description: 'Action to perform'
type: choice
default: 'plan'
options:
- plan
- apply
- destroy
jobs:
plan:
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/terraform-plan.yml@v1
with:
var-file: 'environments/non-prod.tfvars'
environment: 'nonprod'
state-resource-group: 'rg-tfstate-nonprod'
state-storage-account: 'sttfstatenonprod'
state-key: 'myapp-nonprod.tfstate'
secrets:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
apply:
needs: plan
if: |
needs.plan.outputs.has_changes == 'true' ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'apply')
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/terraform-apply.yml@v1
with:
var-file: 'environments/non-prod.tfvars'
environment: 'non-prod'
state-resource-group: 'rg-tfstate-nonprod'
state-storage-account: 'sttfstatenonprod'
state-key: 'myapp-nonprod.tfstate'
secrets:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
destroy:
if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'destroy'
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/terraform-destroy.yml@v1
with:
var-file: 'environments/non-prod.tfvars'
environment: 'non-prod'
state-resource-group: 'rg-tfstate-nonprod'
state-storage-account: 'sttfstatenonprod'
state-key: 'myapp-nonprod.tfstate'
secrets:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}Always reference workflows by tag (not main) for stability:
# Recommended - major version tag
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/dotnet-build.yml@v1
# Pin to exact version
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/dotnet-build.yml@v1.2.0
# NOT recommended for production
uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/dotnet-build.yml@main| Runner | When to Use |
|---|---|
cps-cent-runner-nonprod |
Default for non-prod environments |
cps-cent-runner-prod |
Production deployments |
ubuntu-latest |
Public repos or when self-hosted unavailable |
Self-hosted runners have pre-installed tools (.NET, Terraform, Azure CLI) - faster builds, no firewall issues.
- Issues: GitHub Issues
- Teams: #devops-support channel