From f04ddead8362b4ae2fa3d0ee8dd205c885f6a6af Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Fri, 30 Oct 2026 19:07:26 +0100 Subject: [PATCH 1/2] ci: Keep a copy of run-spec.yml for Depot CI Depot CI only calls reusable workflows from `.depot/workflows/`, and rejects symlinks, so keep an identical copy there. A check fails pull requests that change one copy without the other. --- .depot/workflows/run-spec.yml | 136 +++++++++++++++++++++++++++++++ .github/workflows/depot-copy.yml | 30 +++++++ README.md | 2 + 3 files changed, 168 insertions(+) create mode 100644 .depot/workflows/run-spec.yml create mode 100644 .github/workflows/depot-copy.yml diff --git a/.depot/workflows/run-spec.yml b/.depot/workflows/run-spec.yml new file mode 100644 index 0000000..f5a99b0 --- /dev/null +++ b/.depot/workflows/run-spec.yml @@ -0,0 +1,136 @@ +# Reusable workflow: runs the behavioural spec at `spec-ref` against the calling SDK. +# +# Usage from an SDK repository: +# +# jobs: +# sdk-spec: +# uses: Flagsmith/sdk-spec/.github/workflows/run-spec.yml@v0.3.0 +# with: +# spec-ref: v0.3.0 +# language: python +name: Run SDK spec + +on: + workflow_call: + inputs: + spec-ref: + description: Spec tag (or commit) to run. Keep it in sync with the ref in `uses:`. + type: string + required: true + spec-repository: + description: Repository holding the spec. + type: string + default: Flagsmith/sdk-spec + tags: + description: >- + pytest marker expression selecting scenarios by Gherkin tag, e.g. "core and not realtime". + Empty runs every scenario. + type: string + default: '' + language: + description: Harness to build the SDK image with, i.e. a directory under `harness/` in the spec. + type: string + required: true + dockerfile: + description: Path to the SDK's spec Dockerfile, relative to the SDK repository root. + type: string + default: sdk-spec/Dockerfile + context: + description: Docker build context for the SDK image, relative to the SDK repository root. + type: string + default: . + sdk-repository: + description: SDK repository to test. Defaults to the calling repository. + type: string + default: '' + sdk-ref: + description: SDK ref to test. Defaults to the triggering ref. + type: string + default: '' + flagsmith-image: + description: Override the Flagsmith image the spec is pinned to. + type: string + default: '' + missing-steps: + description: >- + `fail` or `xfail`. With `xfail`, scenarios using a step the SDK does not implement are expected + failures and keep the job green; the steps are reported as warnings. + type: string + default: fail + results-name: + description: Name of the uploaded JUnit results artifact. Must be unique per workflow run. + type: string + default: sdk-spec-results + +permissions: + contents: read + +jobs: + spec: + name: Spec ${{ inputs.spec-ref }} + runs-on: ubuntu-latest + timeout-minutes: 20 + env: + SDK_IMAGE: sdk-spec-sdk:local + FLAGSMITH_IMAGE: ${{ inputs.flagsmith-image }} + steps: + - name: Check out SDK + uses: actions/checkout@v7 + with: + repository: ${{ inputs.sdk-repository || github.repository }} + ref: ${{ inputs.sdk-ref }} + path: sdk + + - name: Check out spec + uses: actions/checkout@v7 + with: + repository: ${{ inputs.spec-repository }} + ref: ${{ inputs.spec-ref }} + path: spec + + - name: Build SDK image + working-directory: sdk + env: + DOCKERFILE: ${{ inputs.dockerfile }} + CONTEXT: ${{ inputs.context }} + HARNESS: ${{ github.workspace }}/spec/harness/${{ inputs.language }} + run: | + if [ ! -d "$HARNESS" ]; then + echo "::error::No harness for language '$(basename "$HARNESS")' in the spec" + exit 1 + fi + docker build --tag "$SDK_IMAGE" --file "$DOCKERFILE" --build-context harness="$HARNESS" "$CONTEXT" + + - name: Start Flagsmith + working-directory: spec + run: | + [ -n "$FLAGSMITH_IMAGE" ] || unset FLAGSMITH_IMAGE + docker compose up --detach --wait --wait-timeout 300 + + - uses: astral-sh/setup-uv@v10.3.0 + with: + working-directory: spec/runner + + - name: Run spec + working-directory: spec/runner + env: + FLAGSMITH_URL: http://localhost:8000 + FLAGSMITH_SDK_URL: http://flagsmith:8000 + SDK_COMMAND: docker run --interactive --rm --network sdk-spec_default ${{ env.SDK_IMAGE }} + TAGS: ${{ inputs.tags }} + MISSING_STEPS: ${{ inputs.missing-steps }} + run: | + uv run pytest -v --junitxml="$GITHUB_WORKSPACE/spec-results.xml" ${TAGS:+-m "$TAGS"} + + - name: Show container logs + if: failure() + working-directory: spec + run: docker compose logs + + - name: Upload results + if: always() + uses: actions/upload-artifact@v7 + with: + name: ${{ inputs.results-name }} + path: spec-results.xml + if-no-files-found: ignore diff --git a/.github/workflows/depot-copy.yml b/.github/workflows/depot-copy.yml new file mode 100644 index 0000000..351eb97 --- /dev/null +++ b/.github/workflows/depot-copy.yml @@ -0,0 +1,30 @@ +# Depot CI only calls reusable workflows from `.depot/workflows/`, and does not follow symlinks, +# so `run-spec.yml` is kept there as a copy. +name: Depot copy + +on: + pull_request: + paths: + - .github/workflows/run-spec.yml + - .depot/workflows/run-spec.yml + push: + branches: [main] + paths: + - .github/workflows/run-spec.yml + - .depot/workflows/run-spec.yml + +permissions: + contents: read + +jobs: + check: + name: run-spec.yml in sync + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + - name: Compare copies + run: | + diff -u .github/workflows/run-spec.yml .depot/workflows/run-spec.yml \ + || { echo "::error::Copy .github/workflows/run-spec.yml to .depot/workflows/run-spec.yml"; exit 1; } diff --git a/README.md b/README.md index f511df1..05d3a51 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ executed against every SDK. - [`harness/`](harness) — one harness per language, running an SDK's steps file ([`HARNESS.md`](HARNESS.md)). - [`.github/workflows/run-spec.yml`](.github/workflows/run-spec.yml) — reusable workflow SDKs call. + [`.depot/workflows/run-spec.yml`](.depot/workflows/run-spec.yml) is an identical copy for SDKs on + Depot CI, which calls reusable workflows from `.depot/workflows/` only. Change both together. - [`.github/workflows/compatibility.yml`](.github/workflows/compatibility.yml) — runs the spec against every onboarded SDK on pull requests and nightly. From db22fdd4f96b558992541126d4a2e0f414926b4d Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Fri, 30 Oct 2026 19:13:52 +0100 Subject: [PATCH 2/2] ci: Keep the spec job green when its results cannot be uploaded --- .depot/workflows/run-spec.yml | 2 ++ .github/workflows/run-spec.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.depot/workflows/run-spec.yml b/.depot/workflows/run-spec.yml index f5a99b0..9ff8838 100644 --- a/.depot/workflows/run-spec.yml +++ b/.depot/workflows/run-spec.yml @@ -129,6 +129,8 @@ jobs: - name: Upload results if: always() + # Depot CI disables artifact writes in reusable workflows called from another repository. + continue-on-error: true uses: actions/upload-artifact@v7 with: name: ${{ inputs.results-name }} diff --git a/.github/workflows/run-spec.yml b/.github/workflows/run-spec.yml index f5a99b0..9ff8838 100644 --- a/.github/workflows/run-spec.yml +++ b/.github/workflows/run-spec.yml @@ -129,6 +129,8 @@ jobs: - name: Upload results if: always() + # Depot CI disables artifact writes in reusable workflows called from another repository. + continue-on-error: true uses: actions/upload-artifact@v7 with: name: ${{ inputs.results-name }}