Skip to content
Draft
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f7c72eb
updates.
RossBugginsNHS Nov 19, 2025
268e7df
remove disabled publish workflow.
RossBugginsNHS Nov 19, 2025
1ee5722
test: add comprehensive schema handling tests for import_asyncapi.py
RossBugginsNHS Nov 20, 2025
b3964e6
fix: resolve 19 SonarCloud MAJOR severity issues in dependancies.sh
RossBugginsNHS Nov 20, 2025
1d50f5e
ci: download Python coverage reports for SonarCloud analysis
RossBugginsNHS Nov 20, 2025
f69fc2e
Tests for other python.
RossBugginsNHS Nov 20, 2025
54fbafd
fix: preserve directory structure in Python coverage artifact upload
RossBugginsNHS Nov 20, 2025
5be0388
Python coverage from anywhere.
RossBugginsNHS Nov 20, 2025
1ef90fc
Correct spellings, remove duplicate dependencies file.
RossBugginsNHS Nov 20, 2025
eaefc8d
skipping dynamic and sonar via env vars.
RossBugginsNHS Nov 21, 2025
11aa83a
use not cancelled
RossBugginsNHS Nov 21, 2025
d1e6a8d
use not cancelled
RossBugginsNHS Nov 21, 2025
b92ad6c
skip scan deps
RossBugginsNHS Nov 21, 2025
2bdfbcd
add in needs.
RossBugginsNHS Nov 21, 2025
5d1d90d
quote true and falses.
RossBugginsNHS Nov 21, 2025
61f1741
remove needs.
RossBugginsNHS Nov 21, 2025
1a3ca79
invert check
RossBugginsNHS Nov 21, 2025
c2593be
invert check
RossBugginsNHS Nov 21, 2025
ee29b3f
trying vars.
RossBugginsNHS Nov 21, 2025
67e978f
adding to metadata instead.
RossBugginsNHS Nov 21, 2025
8db5c7c
checks without strings.
RossBugginsNHS Nov 21, 2025
f9e0186
all from initial metadata.
RossBugginsNHS Nov 21, 2025
2be6dd5
all from initial metadata.
RossBugginsNHS Nov 21, 2025
bfc9d79
pass correctly.
RossBugginsNHS Nov 21, 2025
bc68a64
remove quotes.
RossBugginsNHS Nov 21, 2025
7431acb
remove more quotes.
RossBugginsNHS Nov 21, 2025
37c43e5
outputs appear to always be strings.
RossBugginsNHS Nov 21, 2025
00ca80e
composite actions dont support any types apart from strings.
RossBugginsNHS Nov 21, 2025
626242d
add warning when sonar check disabled.
RossBugginsNHS Nov 21, 2025
26363fa
make publish docs a composite action
RossBugginsNHS Nov 21, 2025
39d66a9
put watning on dep scan being skipped
RossBugginsNHS Nov 21, 2025
a2756c4
add shells.
RossBugginsNHS Nov 21, 2025
9d0b640
add summary step warnings.
RossBugginsNHS Nov 21, 2025
78255e9
add summary step warnings.
RossBugginsNHS Nov 21, 2025
f6f0c8e
add summary step warnings.
RossBugginsNHS Nov 21, 2025
999c282
improve warning messages.
RossBugginsNHS Nov 21, 2025
03a45f9
improve warning messages.
RossBugginsNHS Nov 21, 2025
e4b1219
try out test results.
RossBugginsNHS Nov 21, 2025
ebed2b3
adding python too.
RossBugginsNHS Nov 21, 2025
c5a2901
checks write for test reports.
RossBugginsNHS Nov 21, 2025
e6f3c09
set permissions
RossBugginsNHS Nov 21, 2025
b5ef489
security: fix GitHub Actions command injection vulnerabilities and se…
RossBugginsNHS Nov 21, 2025
56186e8
fix: add checkout step for test-reporter and pin to commit SHA
RossBugginsNHS Nov 21, 2025
abeb4cd
Set url for sonar.
RossBugginsNHS Nov 21, 2025
12942e1
Set bypass of docs.
RossBugginsNHS Nov 21, 2025
ee7c474
Correct check for make docs existing.
RossBugginsNHS Nov 21, 2025
d3dce52
add check on tests.sh not existing in docs from main unit test.
RossBugginsNHS Nov 21, 2025
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
Binary file removed .coverage
Binary file not shown.
6 changes: 3 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"containerEnv": {
"GITHUBMONITOR": "false",
"MAKECONFIG": "true",
"SHOWWELCOME": "true",
"SHOWWELCOME": "false",
"UPDATEFROMTEMPLATE": "false"
},
"image": "ghcr.io/nhsdigital/nhs-notify-devcontainer-loaded-codespaces:main",
"name": "Codespaces Online Development"
"image": "ghcr.io/nhsdigital/nhs-notify-devcontainer-loaded-codespaces:1.0.19",
"name": "Codespaces"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"containerEnv": {
"GITHUBMONITOR": "false",
"MAKECONFIG": "true",
"SHOWWELCOME": "true",
"SHOWWELCOME": "false",
"UPDATEFROMTEMPLATE": "false"
},
"image": "ghcr.io/nhsdigital/nhs-notify-devcontainer-loaded:1.0.17",
"name": "Notify Loaded 1.0.17",
"image": "ghcr.io/nhsdigital/nhs-notify-devcontainer-loaded:1.0.19",
"name": "Local Development",
"postStartCommand": "mkdir -p ~/.gnupg && echo '## 1-day timeout' > ~/.gnupg/gpg-agent.conf && echo 'default-cache-ttl 86400' >> ~/.gnupg/gpg-agent.conf && echo 'max-cache-ttl 86400' >> ~/.gnupg/gpg-agent.conf && gpg-connect-agent reloadagent /bye 2>/dev/null || true"
}
4 changes: 4 additions & 0 deletions .devcontainer/ubuntu/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",
"name": "Ubuntu 24"
}
38 changes: 23 additions & 15 deletions .github/actions/build-docs/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,39 @@ runs:
steps:
- name: Checkout
uses: actions/checkout@v5
- uses: actions/setup-node@v6
with:
node-version: 24
- name: Npm cli install
working-directory: ./docs
run: npm ci
shell: bash
- name: Setup Ruby
uses: ruby/setup-ruby@v1.267.0
with:
ruby-version: "3.4.7" # Not needed with a .ruby-version file
bundler-cache: false # runs 'bundle install' and caches installed gems automatically
#cache-version: 0 # Increment this number if you need to re-download cached gems
working-directory: "./docs"

- name: "Setup dependencies and asdf with cache"
uses: ./.github/actions/setup-dependencies-asdf-with-cache

# - uses: actions/setup-node@v6
# with:
# node-version: 24
# - name: Npm cli install
# working-directory: ./docs
# run: npm ci
# shell: bash
# - name: Setup Ruby
# uses: ruby/setup-ruby@v1.267.0
# with:
# ruby-version: "3.4.7" # Not needed with a .ruby-version file
# bundler-cache: false # runs 'bundle install' and caches installed gems automatically
# #cache-version: 0 # Increment this number if you need to re-download cached gems
# working-directory: "./docs"

- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Build with Jekyll
working-directory: ./docs
# Outputs to the './_site' directory by default
shell: bash
run: make build-ci BASE_URL=${{ steps.pages.outputs.base_path }} VERSION=${{ inputs.version }}
#run: make build-ci BASE_URL=${{ steps.pages.outputs.base_path }} VERSION=${{ inputs.version }}
run: make build BASE_URL="${BASE_URL}" VERSION="${VERSION}"
#run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
env:
JEKYLL_ENV: production
BASE_URL: ${{ steps.pages.outputs.base_path }}
VERSION: ${{ inputs.version }}
- name: Upload artifact
# Automatically uploads an artifact from the './_site' directory by default
uses: actions/upload-pages-artifact@v3
Expand Down
34 changes: 0 additions & 34 deletions .github/actions/build-schemas/action.yml

This file was deleted.

12 changes: 12 additions & 0 deletions .github/actions/perform-static-analysis/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,28 @@ inputs:
sonar_token:
description: "Sonar token, the API key"
required: false
# Note, conmpsite actions only support string inputs
ignore_sonar_failure:
description: "Whether to fail the build if the quality gate fails"
default: 'false'

runs:
using: "composite"
steps:
- name: "Warn that ignore failure is enabled"
if: ${{ fromJSON(inputs.ignore_sonar_failure) }}
shell: bash
run: |
echo "WARNING: SonarQube failures will be ignored as per configuration."
echo "::warning title=Ignore Sonar failures is enabled:: SonarQube failures will be ignored as per configuration."
- name: "Check prerequisites for performing static analysis"
shell: bash
id: check
run: echo "secret_exist=${{ inputs.sonar_token != '' }}" >> $GITHUB_OUTPUT
- name: "Perform static analysis"
shell: bash
if: steps.check.outputs.secret_exist == 'true'
continue-on-error: ${{ fromJSON(inputs.ignore_sonar_failure) }}
run: |
export BRANCH_NAME=${GITHUB_HEAD_REF:-$(echo $GITHUB_REF | sed 's#refs/heads/##')}
export SONAR_ORGANISATION_KEY=${{ inputs.sonar_organisation_key }}
Expand Down
73 changes: 73 additions & 0 deletions .github/actions/publish-docs/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: "Build Docs"
description: "build jekyll docs"
inputs:
version:
description: "Version of the software, set by the CI/CD pipeline workflow"
required: true
type: string
is_version_prerelease:
description: "Is this a semantically versioned pre release, set by the CI/CD pipeline workflow"
required: true
type: string

runs:
using: "composite"
steps:
- name: "Checkout code"
uses: actions/checkout@v5

- name: "Get artifacts: jekyll docs"
uses: actions/download-artifact@v5
with:
path: ./artifacts/jekyll-docs-${{ inputs.version }}
name: jekyll-docs-${{ inputs.version }}

- name: "Get artifacts: schema"
uses: actions/download-artifact@v5
with:
path: ./artifacts/schemas-${{ inputs.version }}
name: schemas-${{ inputs.version }}

- name: Draft Release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
gh release create \
"${{ inputs.version }}" \
--draft \
--latest \
--title "${{ inputs.version }}" \
--notes "Release of ${{ inputs.version }}" \
${{ inputs.is_version_prerelease == 'true' && '--prerelease' || '' }}

- name: "Upload jeykll docs release asset"
shell: bash
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
cp ./artifacts/jekyll-docs-${{ inputs.version }}/artifact.tar $RUNNER_TEMP/jekyll-docs-${{ inputs.version }}.tar
gh release upload \
"${{ inputs.version }}" \
$RUNNER_TEMP/jekyll-docs-${{ inputs.version }}.tar#jekyll-docs-${{ inputs.version }}

- name: "Upload schema release asset"
shell: bash
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
cp ./artifacts/schemas-${{ inputs.version }}/artifact.tar $RUNNER_TEMP/schemas-${{ inputs.version }}.tar
gh release upload \
"${{ inputs.version }}" \
$RUNNER_TEMP/schemas-${{ inputs.version }}.tar#schemas-${{ inputs.version }}


- name: Publish Release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: gh release edit "${{ inputs.version }}" --draft=false
48 changes: 48 additions & 0 deletions .github/actions/setup-dependencies-asdf-with-cache/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: 'Setup depenasdf with cache'
description: 'Restores asdf cache, installs dependencies, and saves cache'
runs:
using: "composite"
steps:
- name: "Restore asdf cache"
id: cache-asdf
uses: actions/cache/restore@v4
with:
path: |
~/.asdf
key: ${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}
restore-keys: |
${{ runner.os }}-asdf-

- name: "Check cache status"
shell: bash
run: |
if [ "${{ steps.cache-asdf.outputs.cache-hit }}" == "true" ]; then
echo "✅ Cache hit! asdf and tools restored from cache. 🚀🚀🚀"
else
echo "❌ Cache miss. asdf and tools will be installed from scratch. 🔨🔨🔨"
fi

- name: "Install dependencies"
shell: bash -l {0}
run: |
make dependencies

- name: "Save asdf cache"
id: save-asdf-cache
if: steps.cache-asdf.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
~/.asdf
key: ${{ steps.cache-asdf.outputs.cache-primary-key }}

- name: "Check cache save status"
shell: bash
run: |
if [ "${{ steps.cache-asdf.outputs.cache-hit }}" == "true" ]; then
echo "ℹ️ Cache was restored from previous run - no save needed"
elif [ "${{ steps.save-asdf-cache.outcome }}" == "success" ]; then
echo "✅ Cache saved successfully for future runs! 💾"
else
echo "⚠️ Cache save was skipped or failed"
fi
51 changes: 43 additions & 8 deletions .github/workflows/cicd-1-pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ jobs:
is_version_prerelease: ${{ steps.variables.outputs.is_version_prerelease }}
does_pull_request_exist: ${{ steps.pr_exists.outputs.does_pull_request_exist }}
pr_number: ${{ steps.pr_exists.outputs.pr_number }}
skip_scan_dependencies: ${{ fromJSON(vars.SKIP_SCAN_DEPENDENCIES || 'false') }}
skip_dynamic_acceptance: ${{ fromJSON(vars.SKIP_DYNAMIC_ACCEPTANCE || 'false') }}
ignore_sonar_failure: ${{ fromJSON(vars.IGNORE_SONAR_FAILURE || 'false') }}
steps:
- name: "Checkout code"
uses: actions/checkout@v5
Expand Down Expand Up @@ -86,10 +89,33 @@ jobs:
export DOES_PULL_REQUEST_EXIST="${{ steps.pr_exists.outputs.does_pull_request_exist }}"
export IS_VERSION_PRERELEASE="${{ steps.variables.outputs.is_version_prerelease }}"
make list-variables

- name: "Warning on skip scan dependencies"
if: ${{ fromJSON(vars.SKIP_SCAN_DEPENDENCIES || 'false') }}
run: |
echo "WARNING: Skipping dependency scan as per configuration."
echo "::warning title=Skipping dependency scan:: Skipping dependency scan as per configuration."
echo "⚠️🔍 Skipping dependency scan as per configuration. ⚠️" >> $GITHUB_STEP_SUMMARY

- name: "Warning on skip dynamic acceptance"
if: ${{ fromJSON(vars.SKIP_DYNAMIC_ACCEPTANCE || 'false') }}
run: |
echo "WARNING: Skipping dynamic acceptance as per configuration."
echo "::warning title=Skipping dynamic acceptance:: Skipping dynamic acceptance as per configuration."
echo "⚠️🚀 Skipping dynamic acceptance as per configuration. ⚠️" >> $GITHUB_STEP_SUMMARY

- name: "Warning on ignore sonar failure"
if: ${{ fromJSON(vars.IGNORE_SONAR_FAILURE || 'false') }}
run: |
echo "WARNING: SonarQube failures will be ignored as per configuration."
echo "::warning title=Ignore Sonar failures is enabled:: SonarQube failures will be ignored as per configuration."
echo "⚠️📊 SonarQube failures will be ignored as per configuration. ⚠️" >> $GITHUB_STEP_SUMMARY

commit-stage: # Recommended maximum execution time is 2 minutes
name: "Commit stage"
needs: [metadata]
uses: ./.github/workflows/stage-1-commit.yaml

with:
build_datetime: "${{ needs.metadata.outputs.build_datetime }}"
build_timestamp: "${{ needs.metadata.outputs.build_timestamp }}"
Expand All @@ -98,11 +124,17 @@ jobs:
python_version: "${{ needs.metadata.outputs.python_version }}"
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
version: "${{ needs.metadata.outputs.version }}"
# secrets: inherit
skip_scan_dependencies: ${{ fromJSON(needs.metadata.outputs.skip_scan_dependencies) }}

test-stage: # Recommended maximum execution time is 5 minutes
name: "Test stage"
needs: [metadata, commit-stage]
uses: ./.github/workflows/stage-2-test.yaml
permissions:
id-token: write
contents: read
checks: write
actions: read
with:
build_datetime: "${{ needs.metadata.outputs.build_datetime }}"
build_timestamp: "${{ needs.metadata.outputs.build_timestamp }}"
Expand All @@ -111,8 +143,10 @@ jobs:
python_version: "${{ needs.metadata.outputs.python_version }}"
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
version: "${{ needs.metadata.outputs.version }}"
secrets: #inherit
ignore_sonar_failure: ${{ fromJSON(needs.metadata.outputs.ignore_sonar_failure) }}
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

build-stage: # Recommended maximum execution time is 3 minutes
name: "Build stage"
needs: [metadata, test-stage]
Expand All @@ -126,12 +160,13 @@ jobs:
python_version: "${{ needs.metadata.outputs.python_version }}"
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
version: "${{ needs.metadata.outputs.version }}"
# secrets: inherit


pr-create-dynamic-environment:
name: Trigger dynamic environment creation
needs: [metadata, build-stage]
runs-on: ubuntu-latest
if: needs.metadata.outputs.does_pull_request_exist == 'true' || (github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened'))
if: ${{ !needs.metadata.outputs.skip_dynamic_acceptance && (needs.metadata.outputs.does_pull_request_exist == 'true' || (github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened'))) }}
steps:
- uses: actions/checkout@v5.0.0
- name: Trigger dynamic environment creation
Expand All @@ -151,6 +186,7 @@ jobs:
--overrideProjectName "nhs" \
--overrideRoleName "nhs-main-acct-digital-letters-github-deploy" \
--overrides "branch_name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"

acceptance-stage: # Recommended maximum execution time is 10 minutes
name: "Acceptance stage"
needs: [metadata, pr-create-dynamic-environment]
Expand All @@ -162,12 +198,12 @@ jobs:
secrets:
APP_PEM_FILE: ${{ secrets.APP_PEM_FILE }}
APP_CLIENT_ID: ${{ secrets.APP_CLIENT_ID }}

publish-stage: # Recommended maximum execution time is 10 minutes
name: "Publish stage"
needs: [metadata, acceptance-stage] #PUT THIS BACK WHEN ACCEPTANCE STAGE IS ENABLED
#needs: [metadata, build-stage] BYPASSING ACCEPTANCE STAGE
needs: [metadata, build-stage, acceptance-stage]
uses: ./.github/workflows/stage-5-publish.yaml
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
if: ${{(!cancelled() && fromJSON(needs.metadata.outputs.skip_dynamic_acceptance) && needs.build-stage.result == 'success') || (success() && github.event_name == 'push' && github.ref == 'refs/heads/main')}}
with:
build_datetime: "${{ needs.metadata.outputs.build_datetime }}"
build_timestamp: "${{ needs.metadata.outputs.build_timestamp }}"
Expand All @@ -177,4 +213,3 @@ jobs:
terraform_version: "${{ needs.metadata.outputs.terraform_version }}"
version: "${{ needs.metadata.outputs.version }}"
is_version_prerelease: "${{ needs.metadata.outputs.is_version_prerelease }}"
# secrets: inherit
Loading
Loading