From ac8a365c59d4568d77ffa309857cbc9b51ce46d8 Mon Sep 17 00:00:00 2001 From: Todd Anderson Date: Fri, 23 Oct 2026 10:19:07 -0400 Subject: [PATCH] ci: add nightly contract tests with long-running tests enabled The test harness gates its RETRY-conformance and FDv2 long-running tests behind -enable-long-running-tests. Per-PR CI does not pass that flag, so none of them have ever run for this SDK, even though the contract test service declares both retry-conformance-fdv1-streaming and retry-conformance-fdv1-polling. Adds a nightly workflow that enables them, plus an enable_long_running_tests input on the contract-tests action to carry the flag. The input defaults to false, so per-PR CI for the server and client SDKs renders identical params to today. The job is expected to fail on three FDv2 tests until those are addressed separately: streaming/fdv2/recoverable fallback to secondary synchronizer streaming/fdv2/recoverable fallback with recovery streaming/fdv2/permanent fallback with recovery --- .github/actions/contract-tests/action.yml | 8 +++- .github/workflows/sdk-server-nightly.yml | 48 +++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/sdk-server-nightly.yml diff --git a/.github/actions/contract-tests/action.yml b/.github/actions/contract-tests/action.yml index 17eaf4026..c64639cc5 100644 --- a/.github/actions/contract-tests/action.yml +++ b/.github/actions/contract-tests/action.yml @@ -15,6 +15,10 @@ inputs: description: 'Whether to run contract tests from the latest v3 release' required: false default: 'false' + enable_long_running_tests: + description: 'Whether to run harness tests that wait on real backoff timing. These add about an hour, so only the nightly enables them.' + required: false + default: 'false' runs: using: composite @@ -54,7 +58,7 @@ runs: enable_persistence_tests: 'false' # Leave the service up for the FDv2 run that follows. stop_service: ${{ inputs.run_fdv2_tests == 'true' && 'false' || 'true' }} - extra_params: '-status-timeout=360 -skip-from=${{ env.SUPPRESSION_FILE }}' + extra_params: "-status-timeout=360 -skip-from=${{ env.SUPPRESSION_FILE }}${{ inputs.enable_long_running_tests == 'true' && ' -enable-long-running-tests' || '' }}" token: ${{ inputs.token }} - name: Run Contract Tests FDv2 Flavor @@ -65,7 +69,7 @@ runs: version: 'v3' debug_logging: 'true' enable_persistence_tests: 'false' - extra_params: '-status-timeout=360 -skip-from=${{ env.SUPPRESSION_FILE_FDV2 }}' + extra_params: "-status-timeout=360 -skip-from=${{ env.SUPPRESSION_FILE_FDV2 }}${{ inputs.enable_long_running_tests == 'true' && ' -enable-long-running-tests' || '' }}" token: ${{ inputs.token }} - name: Upload test service log on failure diff --git a/.github/workflows/sdk-server-nightly.yml b/.github/workflows/sdk-server-nightly.yml new file mode 100644 index 000000000..bc19821c0 --- /dev/null +++ b/.github/workflows/sdk-server-nightly.yml @@ -0,0 +1,48 @@ +name: LaunchDarkly.ServerSdk Nightly Contract Tests + +on: + schedule: + - cron: '0 4 * * *' # every day at 4am UTC + workflow_dispatch: + inputs: + branch: + description: 'Branch to run contract tests on' + required: false + default: '' + +permissions: + contents: read + +jobs: + nightly-contract-tests: + runs-on: ubuntu-latest + # The long-running tests are almost entirely wall-clock waiting, so this job runs + # roughly an hour. A regression that stops retrying makes each scenario burn its + # full timeout instead of returning early, so leave headroom -- while staying well + # under the 6-hour default that would otherwise apply. + timeout-minutes: 120 + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch || github.ref }} + + - name: Setup Env from project's Env file + shell: bash + run: cat pkgs/sdk/server/github_actions.env >> "$GITHUB_ENV" + + - uses: ./.github/actions/contract-tests + with: + service_project_file: ${{ env.CONTRACT_TEST_PROJECT_FILE }} + service_dll_file: ${{ env.CONTRACT_TEST_DLL_FILE }} + token: ${{ secrets.GITHUB_TOKEN }} + run_fdv2_tests: 'true' + enable_long_running_tests: 'true' + + - name: Upload test service log + if: always() + uses: actions/upload-artifact@v4 + with: + name: contract-test-service-log + path: test-service.log + if-no-files-found: warn