From ca1a0ff8b063994ae78b2f7082a526d9185c554f Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Tue, 25 Aug 2026 11:32:37 +0200 Subject: [PATCH 1/3] ci: run full integration tests weekly --- .github/workflows/integration_tests.yml | 8 ++++---- Tests/Integration/README.md | 10 +++++----- Tests/Integration/Server.Integration.Tests.ps1 | 2 +- Tests/README.md | 2 +- Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 | 10 ++++++++++ 5 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 69ca426af..6baa4d445 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -1,18 +1,18 @@ name: Integration Tests # Cloud track + Server (Data Center, Dockerized) track. The two jobs share -# this workflow's nightly cron and dispatch but are otherwise independent: +# this workflow's weekly cron and dispatch but are otherwise independent: # Cloud runs against a live Jira Cloud instance via shared org credentials, # Server boots moveworkforward/atlas-run-standalone:jira-11 with # docker-compose and provisions the fixture project + user from scratch. # # Per-PR Cloud coverage is the smoke_tests job in ci.yml; per-PR Server # coverage is the Server-tagged unit tests in ci.yml. The full suites here -# only run on the cron and on explicit dispatch because the Cloud full +# only run weekly and on explicit dispatch because the Cloud full # suite burns API quota and the Server cold boot is ~25 min. on: schedule: - - cron: "0 5 * * *" + - cron: "0 5 * * 0" workflow_dispatch: inputs: track: @@ -79,7 +79,7 @@ jobs: # # Because this workflow only runs on the cron + manual dispatch, the # Server job is intentionally NOT marked continue-on-error: a red - # nightly is a real signal that either the upstream image has drifted + # weekly run is a real signal that either the upstream image has drifted # or a Server-track regression has slipped in, and we want that noise. # Boot budget: pulling the ~1.2 GB image (~1 min on a warm runner), Maven # dependency verification (~3 min), Tomcat 10.1.44 startup + jira.war diff --git a/Tests/Integration/README.md b/Tests/Integration/README.md index 15610e973..eb8231598 100644 --- a/Tests/Integration/README.md +++ b/Tests/Integration/README.md @@ -72,8 +72,8 @@ If `TestIntegrationServer` fails before teardown, it captures `jira-container.lo | Workflow / Job | Trigger | Notes | | ---------------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ci.yml` → `smoke_tests` (Cloud) | every PR + every push to `master` | Skipped on fork / Dependabot PRs (no secrets); gates `release.yml` via the `CI Result` aggregator (`workflow_conclusion: success`) | -| `integration_tests.yml` → `cloud_integration_tests` | `0 5 * * *` + manual `workflow_dispatch` | Full Cloud suite — scheduled + manual only; PR-level coverage is the smoke job above | -| `integration_tests.yml` → `server_integration_tests` | `0 5 * * *` + manual `workflow_dispatch` | Never on PRs — ~25 min cold boot is too expensive to gate every PR on; PR-level Server coverage comes from the Server-tagged unit tests in `ci.yml`. Jira boot dominates wall time | +| `integration_tests.yml` → `cloud_integration_tests` | `0 5 * * 0` + manual `workflow_dispatch` | Full Cloud suite — weekly + manual only; PR-level coverage is the smoke job above | +| `integration_tests.yml` → `server_integration_tests` | `0 5 * * 0` + manual `workflow_dispatch` | Never on PRs — ~25 min cold boot is too expensive to gate every PR on; PR-level Server coverage comes from the Server-tagged unit tests in `ci.yml`. Jira boot dominates wall time | ## Prerequisites @@ -400,7 +400,7 @@ Context "Write Operations" -Skip:($fixtures.ReadOnly) { ## CI/CD -Cloud smoke runs as part of the standard `.github/workflows/ci.yml` pipeline; the full Cloud suite and the full Server (Data Center, Dockerized) suite share `.github/workflows/integration_tests.yml`, which fires on a nightly cron and on manual dispatch. +Cloud smoke runs as part of the standard `.github/workflows/ci.yml` pipeline; the full Cloud suite and the full Server (Data Center, Dockerized) suite share `.github/workflows/integration_tests.yml`, which runs weekly and on manual dispatch. ### Workflow Triggers @@ -409,7 +409,7 @@ Cloud smoke runs as part of the standard `.github/workflows/ci.yml` pipeline; th | Pull Request (first-party) | ✅ | ❌ — use `workflow_dispatch` to opt in | ❌ — use `workflow_dispatch` to opt in | | Pull Request (fork / Dependabot) | ⚪ skipped (no secrets) | ❌ | ❌ | | Push to `master` | ✅ | ❌ | ❌ | -| Nightly (5 AM UTC) | — | ✅ | ✅ | +| Weekly (Sunday at 5 AM UTC) | — | ✅ | ✅ | | Manual (`workflow_dispatch`) | re-run via Actions UI | ✅ — pass `track=cloud` (or `both`) | ✅ — pass `track=server` (or `both`) | ### Required Secrets @@ -447,7 +447,7 @@ For **first-party PR branches** (those on `AtlassianPS/JiraPS` itself), the bran - **No build required**: tests run directly against source for speed. - **Parallel execution**: Cloud uses `ThrottleLimit=6`; Server uses `ThrottleLimit=2` (halved because the AMPS/H2 backend serialises Lucene write commits — see the inline comment on the `server_integration_tests` job for the contention details). -- **Concurrency control**: nightly + dispatched runs share one concurrency group with `cancel-in-progress: false`, so an in-flight run is never killed by the next cron tick or a dispatch retry. +- **Concurrency control**: weekly + dispatched runs share one concurrency group with `cancel-in-progress: false`, so an in-flight run is never killed by a dispatch retry. - **NUnit results artifacts**: `Cloud-Integration-Tests` and `Server-Integration-Tests` (each containing `Test-Integration.xml`); the Server job additionally uploads `Server-Jira-Container-Logs` for post-mortem on failures. ## Troubleshooting diff --git a/Tests/Integration/Server.Integration.Tests.ps1 b/Tests/Integration/Server.Integration.Tests.ps1 index aef73d387..b8212cab7 100644 --- a/Tests/Integration/Server.Integration.Tests.ps1 +++ b/Tests/Integration/Server.Integration.Tests.ps1 @@ -17,7 +17,7 @@ .NOTES Tagged 'Integration', 'Smoke', 'Server' - this IS the smoke test for the Server track and is the first thing the `server_integration_tests` job in - integration_tests.yml runs (nightly + manual workflow_dispatch only; the + integration_tests.yml runs (weekly + manual workflow_dispatch only; the Server job is not wired up to PRs because the ~25 min cold-boot cost is too expensive to gate every PR on). #> diff --git a/Tests/README.md b/Tests/README.md index 2df418458..afde9898b 100644 --- a/Tests/README.md +++ b/Tests/README.md @@ -595,7 +595,7 @@ Cloud integration coverage is split across two workflows: - **Smoke tests** (`ci.yml`, `smoke_tests` job): Run on every first-party PR + every push to `master`. Skipped on fork / Dependabot PRs (no secrets). Gates `release.yml` via the `CI Result` sentinel. - **Full integration tests** (`integration_tests.yml`): two parallel jobs — `cloud_integration_tests` and `server_integration_tests` (Dockerized Jira DC). Run on: - - Nightly schedule (5 AM UTC) — both jobs. + - Weekly schedule (Sunday at 5 AM UTC) — both jobs. - Manual trigger (`workflow_dispatch`) — use this to run the full suite against an in-flight PR branch; pass `track=cloud`, `track=server`, or `track=both` (default `both`). Required GitHub Secrets: diff --git a/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 new file mode 100644 index 000000000..3a74c0d97 --- /dev/null +++ b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 @@ -0,0 +1,10 @@ +#requires -modules @{ ModuleName = "Pester"; ModuleVersion = "5.7"; MaximumVersion = "5.999" } + +Describe 'GitHub Actions workflow triggers' -Tag Unit { + It 'runs integration tests weekly and on demand' { + $workflow = Get-Content "$PSScriptRoot/../../.github/workflows/integration_tests.yml" -Raw + + $workflow | Should -Match 'cron:\s*"0 5 \* \* 0"' + $workflow | Should -Match 'workflow_dispatch:' + } +} From 81d08e6ad27902b97f2c9ce162bd39e04304064c Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Tue, 25 Aug 2026 13:04:29 +0200 Subject: [PATCH 2/3] style(tests): apply repository file format --- Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 index 3a74c0d97..246b42a02 100644 --- a/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 +++ b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 @@ -1,4 +1,4 @@ -#requires -modules @{ ModuleName = "Pester"; ModuleVersion = "5.7"; MaximumVersion = "5.999" } +#requires -modules @{ ModuleName = "Pester"; ModuleVersion = "5.7"; MaximumVersion = "5.999" } Describe 'GitHub Actions workflow triggers' -Tag Unit { It 'runs integration tests weekly and on demand' { From 589620b8ff7ac9a437fa16625c16653b9be735d1 Mon Sep 17 00:00:00 2001 From: Oliver Lipkau Date: Tue, 25 Aug 2026 13:09:27 +0200 Subject: [PATCH 3/3] test: resolve workflows from repository root --- Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 index 246b42a02..8bed4e32a 100644 --- a/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 +++ b/Tests/Tools/WorkflowTriggers.Unit.Tests.ps1 @@ -1,8 +1,13 @@ #requires -modules @{ ModuleName = "Pester"; ModuleVersion = "5.7"; MaximumVersion = "5.999" } Describe 'GitHub Actions workflow triggers' -Tag Unit { + BeforeAll { + . "$PSScriptRoot/../Helpers/TestTools.ps1" + $script:workflowRoot = Join-Path (Resolve-ProjectRoot) '.github/workflows' + } + It 'runs integration tests weekly and on demand' { - $workflow = Get-Content "$PSScriptRoot/../../.github/workflows/integration_tests.yml" -Raw + $workflow = Get-Content (Join-Path $script:workflowRoot 'integration_tests.yml') -Raw $workflow | Should -Match 'cron:\s*"0 5 \* \* 0"' $workflow | Should -Match 'workflow_dispatch:'