From a4478a263f183987bd815690634d3cdb343d5cee Mon Sep 17 00:00:00 2001 From: Andy Mitchell <326561+Themitchell@users.noreply.github.com> Date: Fri, 6 Mar 2026 17:04:59 +0000 Subject: [PATCH 1/4] Move ui tests to features and run as test stage not acceptance stage --- .github/workflows/stage-2-test.yaml | 14 ++++++++++++++ .github/workflows/stage-4-acceptance.yaml | 1 - scripts/tests/{ui.sh => features.sh} | 2 +- scripts/tests/test.mk | 5 +++++ 4 files changed, 20 insertions(+), 2 deletions(-) rename scripts/tests/{ui.sh => features.sh} (90%) diff --git a/.github/workflows/stage-2-test.yaml b/.github/workflows/stage-2-test.yaml index 69b7ba9a..f1d631f2 100644 --- a/.github/workflows/stage-2-test.yaml +++ b/.github/workflows/stage-2-test.yaml @@ -61,6 +61,20 @@ jobs: - name: "Save the linting result" run: | echo "Nothing to save" + test-features: + name: "Feature tests" + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: "Checkout code" + uses: actions/checkout@v6 + - name: "Run feature tests" + run: | + cp .env.example .env + make test-features + - name: "Save result" + run: | + echo "Nothing to save" test-coverage: name: "Test coverage" needs: [test-unit] diff --git a/.github/workflows/stage-4-acceptance.yaml b/.github/workflows/stage-4-acceptance.yaml index 44bf0643..115e8d3f 100644 --- a/.github/workflows/stage-4-acceptance.yaml +++ b/.github/workflows/stage-4-acceptance.yaml @@ -87,7 +87,6 @@ jobs: uses: actions/checkout@v6 - name: "Run UI test" run: | - cp .env.example .env make test-ui - name: "Save result" run: | diff --git a/scripts/tests/ui.sh b/scripts/tests/features.sh similarity index 90% rename from scripts/tests/ui.sh rename to scripts/tests/features.sh index d3a5bda2..cbd03ab0 100755 --- a/scripts/tests/ui.sh +++ b/scripts/tests/features.sh @@ -1,4 +1,4 @@ -echo Running UI Tests +echo Running Feature Tests if [[ -n "${TAG:-}" ]]; then TAG="--tags=$TAG" diff --git a/scripts/tests/test.mk b/scripts/tests/test.mk index 37d8f25f..fdd9b0f7 100644 --- a/scripts/tests/test.mk +++ b/scripts/tests/test.mk @@ -14,6 +14,9 @@ test-unit: # Run your unit tests from scripts/test/unit @Testing test-lint: # Lint your code from scripts/test/lint @Testing make _test name="lint" +test-features: # Run feature (Behave) tests @Testing + make _test name="features" + test-coverage: # Evaluate code coverage from scripts/test/coverage @Testing make _test name="coverage" @@ -55,6 +58,7 @@ test: # Run all the test tasks @Testing make \ test-unit \ test-lint \ + test-features \ test-coverage \ test-contract \ test-security \ @@ -89,3 +93,4 @@ ${VERBOSE}.SILENT: \ test-ui \ test-ui-performance \ test-unit \ + test-features \ From 541812013b4b56da290a832c977bf960d5a04047 Mon Sep 17 00:00:00 2001 From: Andy Mitchell <326561+Themitchell@users.noreply.github.com> Date: Fri, 6 Mar 2026 17:06:52 +0000 Subject: [PATCH 2/4] Use cached docker images in pipeline to speed up test runs --- .github/workflows/stage-2-test.yaml | 122 ++++++++++++++++++++++++++-- docker-compose.ci.yml | 11 +++ 2 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 docker-compose.ci.yml diff --git a/.github/workflows/stage-2-test.yaml b/.github/workflows/stage-2-test.yaml index f1d631f2..1060e33e 100644 --- a/.github/workflows/stage-2-test.yaml +++ b/.github/workflows/stage-2-test.yaml @@ -33,14 +33,70 @@ on: type: string jobs: + build-compose-cache: + name: "Build Docker Compose cache" + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: "Checkout code" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - name: "Set up Docker Buildx" + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f + - name: "Build asset_builder for cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: asset_builder + push: false + load: true + tags: ${{ github.event.repository.name }}_asset_builder:latest + cache-from: type=gha,scope=compose-asset + cache-to: type=gha,scope=compose-asset,mode=max + - name: "Build web image for cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: development + push: false + load: true + tags: ${{ github.event.repository.name }}_web:latest + cache-from: type=gha,scope=compose-web + cache-to: type=gha,scope=compose-web,mode=max + test-unit: name: "Unit tests" + needs: [build-compose-cache] runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 steps: - name: "Checkout code" - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - name: "Set up Docker Buildx" + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f + - name: "Build asset_builder from cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: asset_builder + push: false + load: true + tags: ${{ github.event.repository.name }}_asset_builder:latest + cache-from: type=gha,scope=compose-asset + cache-to: type=gha,scope=compose-asset,mode=max + - name: "Build web image from cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: development + push: false + load: true + tags: ${{ github.event.repository.name }}_web:latest + cache-from: type=gha,scope=compose-web + cache-to: type=gha,scope=compose-web,mode=max - name: "Run unit test suite" + env: + COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml + COMPOSE_PROJECT_NAME: ${{ github.event.repository.name }} run: | cp .env.example .env make test-unit @@ -49,12 +105,38 @@ jobs: echo "Nothing to save" test-lint: name: "Linting" + needs: [build-compose-cache] runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 steps: - name: "Checkout code" - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - name: "Set up Docker Buildx" + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f + - name: "Build asset_builder from cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: asset_builder + push: false + load: true + tags: ${{ github.event.repository.name }}_asset_builder:latest + cache-from: type=gha,scope=compose-asset + cache-to: type=gha,scope=compose-asset,mode=max + - name: "Build web image from cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: development + push: false + load: true + tags: ${{ github.event.repository.name }}_web:latest + cache-from: type=gha,scope=compose-web + cache-to: type=gha,scope=compose-web,mode=max - name: "Run linting" + env: + COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml + COMPOSE_PROJECT_NAME: ${{ github.event.repository.name }} run: | cp .env.example .env make test-lint @@ -63,12 +145,38 @@ jobs: echo "Nothing to save" test-features: name: "Feature tests" + needs: [build-compose-cache] runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: "Checkout code" - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - name: "Set up Docker Buildx" + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f + - name: "Build asset_builder from cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: asset_builder + push: false + load: true + tags: ${{ github.event.repository.name }}_asset_builder:latest + cache-from: type=gha,scope=compose-asset + cache-to: type=gha,scope=compose-asset,mode=max + - name: "Build web image from cache" + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 + with: + context: . + target: development + push: false + load: true + tags: ${{ github.event.repository.name }}_web:latest + cache-from: type=gha,scope=compose-web + cache-to: type=gha,scope=compose-web,mode=max - name: "Run feature tests" + env: + COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml + COMPOSE_PROJECT_NAME: ${{ github.event.repository.name }} run: | cp .env.example .env make test-features @@ -82,7 +190,7 @@ jobs: timeout-minutes: 5 steps: - name: "Checkout code" - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - name: "Run test coverage check" run: | make test-coverage @@ -99,7 +207,7 @@ jobs: timeout-minutes: 5 steps: - name: "Checkout code" - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: fetch-depth: 0 # Full history is needed to improving relevancy of reporting - name: "Perform static analysis" diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml new file mode 100644 index 00000000..d7634c19 --- /dev/null +++ b/docker-compose.ci.yml @@ -0,0 +1,11 @@ +# Used only in CI (COMPOSE_FILE=docker-compose.yml:docker-compose.ci.yml) to pin +# pre-built image names so tests use the cached images instead of rebuilding. +# Not loaded when running docker compose locally. + +services: + web: + image: ${COMPOSE_PROJECT_NAME}_web:latest + pull_policy: never + asset_builder: + image: ${COMPOSE_PROJECT_NAME}_asset_builder:latest + pull_policy: never From 690af05b027357a56ea71dc175ef3faac2980a85 Mon Sep 17 00:00:00 2001 From: Andy Mitchell <326561+Themitchell@users.noreply.github.com> Date: Fri, 6 Mar 2026 17:53:56 +0000 Subject: [PATCH 3/4] Only run build stage after test stage is complete --- .github/workflows/cicd-1-pull-request.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index c1ba910a..5c8a2a03 100644 --- a/.github/workflows/cicd-1-pull-request.yaml +++ b/.github/workflows/cicd-1-pull-request.yaml @@ -89,7 +89,7 @@ jobs: secrets: inherit build-stage: name: 'Build stage' - needs: [metadata] + needs: [metadata, test-stage] uses: ./.github/workflows/stage-3-build.yaml with: build_datetime: '${{ needs.metadata.outputs.build_datetime }}' From c9ed319e3006eae26389f2d392474d3ed1b2832c Mon Sep 17 00:00:00 2001 From: Andy Mitchell <326561+Themitchell@users.noreply.github.com> Date: Fri, 6 Mar 2026 18:03:18 +0000 Subject: [PATCH 4/4] Shrink docker build cache size --- .github/workflows/stage-2-test.yaml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/stage-2-test.yaml b/.github/workflows/stage-2-test.yaml index 1060e33e..97536989 100644 --- a/.github/workflows/stage-2-test.yaml +++ b/.github/workflows/stage-2-test.yaml @@ -51,7 +51,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_asset_builder:latest cache-from: type=gha,scope=compose-asset - cache-to: type=gha,scope=compose-asset,mode=max + cache-to: type=gha,scope=compose-asset,mode=min - name: "Build web image for cache" uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 with: @@ -61,7 +61,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_web:latest cache-from: type=gha,scope=compose-web - cache-to: type=gha,scope=compose-web,mode=max + cache-to: type=gha,scope=compose-web,mode=min test-unit: name: "Unit tests" @@ -82,7 +82,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_asset_builder:latest cache-from: type=gha,scope=compose-asset - cache-to: type=gha,scope=compose-asset,mode=max + cache-to: type=gha,scope=compose-asset,mode=min - name: "Build web image from cache" uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 with: @@ -92,7 +92,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_web:latest cache-from: type=gha,scope=compose-web - cache-to: type=gha,scope=compose-web,mode=max + cache-to: type=gha,scope=compose-web,mode=min - name: "Run unit test suite" env: COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml @@ -101,8 +101,8 @@ jobs: cp .env.example .env make test-unit - name: "Save the result of fast test suite" - run: | - echo "Nothing to save" + run: echo "Nothing to save" + test-lint: name: "Linting" needs: [build-compose-cache] @@ -122,7 +122,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_asset_builder:latest cache-from: type=gha,scope=compose-asset - cache-to: type=gha,scope=compose-asset,mode=max + cache-to: type=gha,scope=compose-asset,mode=min - name: "Build web image from cache" uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 with: @@ -132,7 +132,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_web:latest cache-from: type=gha,scope=compose-web - cache-to: type=gha,scope=compose-web,mode=max + cache-to: type=gha,scope=compose-web,mode=min - name: "Run linting" env: COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml @@ -141,8 +141,8 @@ jobs: cp .env.example .env make test-lint - name: "Save the linting result" - run: | - echo "Nothing to save" + run: echo "Nothing to save" + test-features: name: "Feature tests" needs: [build-compose-cache] @@ -162,7 +162,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_asset_builder:latest cache-from: type=gha,scope=compose-asset - cache-to: type=gha,scope=compose-asset,mode=max + cache-to: type=gha,scope=compose-asset,mode=min - name: "Build web image from cache" uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 with: @@ -172,7 +172,7 @@ jobs: load: true tags: ${{ github.event.repository.name }}_web:latest cache-from: type=gha,scope=compose-web - cache-to: type=gha,scope=compose-web,mode=max + cache-to: type=gha,scope=compose-web,mode=min - name: "Run feature tests" env: COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml @@ -181,8 +181,8 @@ jobs: cp .env.example .env make test-features - name: "Save result" - run: | - echo "Nothing to save" + run: echo "Nothing to save" + test-coverage: name: "Test coverage" needs: [test-unit]