Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

CPS Centralised Reusable Workflows

Centralized repository for GitHub Actions reusable workflows used across CPS-Innovation repositories.

Available Workflows

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

.NET Build Workflow

Build, test, and package .NET applications.

Usage

jobs:
  build:
    uses: CPS-Innovation/CPS-Centralised-Reusable-Workflows/.github/workflows/dotnet-build.yml@v1
    with:
      solution-file: 'src/MyApp.sln'
    secrets: inherit

Inputs

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

Example with GitHub Packages

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: inherit

Terraform Workflows

Infrastructure deployment with plan, apply, and destroy stages.

Prerequisites

  1. Azure OIDC Authentication - Configure federated credentials in your Azure AD app
  2. GitHub Secrets - Add to your repository:
    • AZURE_CLIENT_ID
    • AZURE_TENANT_ID
    • AZURE_SUBSCRIPTION_ID
  3. GitHub Environment - Create environments (e.g., non-prod, prod) with approval gates

Inputs (Same for all Terraform workflows)

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

Secrets Required

Secret Description
AZURE_CLIENT_ID Azure AD app client ID
AZURE_TENANT_ID Azure AD tenant ID
AZURE_SUBSCRIPTION_ID Azure subscription ID

Terraform Plan

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.


Terraform Apply

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 }}

Terraform Destroy

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 }}

Full Terraform Pipeline Example

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 }}

Versioning

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 Selection

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.


Support

About

No description, website, or topics provided.

Resources

Code of conduct

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors