Add real two-server coverage for sync sources #4
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Cross-repo wire-format verify | |
| # Runs on every PR (no path filter at trigger level — branch-protection rules can require | |
| # these checks without GitHub leaving them pending on path-skipped PRs). The relevance | |
| # check happens inside the job, and irrelevant PRs early-exit with success. | |
| # | |
| # Sister workflow: app-main's .github/workflows/cross-repo-verify.yml (A3) fires the same | |
| # shape from its direction. Each producer's PRs trigger the matching consumer suites | |
| # against this PR's HEAD via INTEROP_FIXTURE_OVERRIDES. | |
| on: | |
| pull_request: | |
| branches: [ main ] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: cross-repo-verify-${{ github.workflow }}-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| env: | |
| # Path prefixes that can affect the bytes octi-web puts on the wire AND that are | |
| # actually exercised by the consumer fixtures in src/__interop__/published/. Entries | |
| # ending in `/` match any file under that prefix; bare file entries must match exactly. | |
| # Keep this allowlist tight — over-firing turns into "every PR pays the cross-repo CI | |
| # cost for changes that can't actually break consumers". | |
| ALLOWLIST: | | |
| src/modules/ | |
| src/__interop__/published/ | |
| src/protocol/connector-id.ts | |
| src/util/base64.ts | |
| tools/generate-fixtures.ts | |
| .github/workflows/cross-repo-verify.yml | |
| jobs: | |
| verify-octi: | |
| name: Verify app-main decodes this PR's wire bytes | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout this repo at PR head | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| path: octi-web | |
| # Full history so `git merge-base` finds the PR's branch point on main. | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Detect wire-format-relevant changes | |
| id: changed | |
| working-directory: octi-web | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| base="${{ github.event.pull_request.base.sha }}" | |
| head="${{ github.event.pull_request.head.sha }}" | |
| merge_base="$(git merge-base "$base" "$head")" | |
| matches_allowlist() { | |
| local path="$1" prefix | |
| while IFS= read -r prefix; do | |
| prefix="${prefix#"${prefix%%[![:space:]]*}"}" | |
| [[ -z "$prefix" ]] && continue | |
| if [[ "$prefix" == */ ]]; then | |
| [[ "$path" == "$prefix"* ]] && return 0 | |
| else | |
| [[ "$path" == "$prefix" ]] && return 0 | |
| fi | |
| done <<< "$ALLOWLIST" | |
| return 1 | |
| } | |
| relevant=false | |
| while IFS= read -r -d '' path; do | |
| if matches_allowlist "$path"; then | |
| echo "relevant: $path" | |
| relevant=true | |
| fi | |
| done < <(git diff --name-only --no-renames -z "$merge_base" "$head" --) | |
| echo "relevant=$relevant" >> "$GITHUB_OUTPUT" | |
| if [[ "$relevant" == "false" ]]; then | |
| echo "no wire-format-relevant paths changed; consumer verify will be skipped." | |
| fi | |
| - name: Checkout app-main | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| repository: d4rken-org/octi | |
| persist-credentials: false | |
| path: app-main | |
| - name: Setup JDK 21 | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 | |
| with: | |
| java-version: '21' | |
| distribution: 'temurin' | |
| - name: Cache Gradle wrapper | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 | |
| with: | |
| path: | | |
| ~/.gradle/wrapper | |
| !~/.gradle/wrapper/dists/**/gradle*.zip | |
| # Cache keys are namespaced per consumer repo so the two jobs don't restore each | |
| # other's incompatible caches across runs. | |
| key: ${{ runner.os }}-app-main-gradle-wrapper-${{ hashFiles('app-main/**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-app-main-gradle-wrapper- | |
| - name: Cache Gradle dependencies | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| key: ${{ runner.os }}-app-main-gradle-caches-${{ hashFiles('app-main/**/*.gradle*', 'app-main/**/gradle-wrapper.properties', 'app-main/buildSrc/**/*.kt') }} | |
| restore-keys: | | |
| ${{ runner.os }}-app-main-gradle-caches- | |
| - name: Run app-main module tests with fixture override | |
| if: steps.changed.outputs.relevant == 'true' | |
| working-directory: app-main | |
| env: | |
| # Override app-main's pin of d4rken-org/octi-web with this PR's HEAD SHA. The | |
| # multi-source resolver drops the committed manifest_sha256 trust anchor for this | |
| # source; per-file sha256s in the freshly-fetched manifest stay as the anchor. | |
| INTEROP_FIXTURE_OVERRIDES: '{"d4rken-org/octi-web":"${{ github.event.pull_request.head.sha }}"}' | |
| run: | | |
| echo "Running app-main module tests against this PR's octi-web HEAD (${{ github.event.pull_request.head.sha }})" | |
| chmod +x ./gradlew | |
| # Only the modules that consume octi-web's fixtures need to run — the full :test | |
| # graph would build app + UI variants that don't exercise this contract and would | |
| # waste ~10 minutes per PR. | |
| ./gradlew :modules-meta:testDebugUnitTest :modules-clipboard:testDebugUnitTest :modules-files:testDebugUnitTest | |
| verify-desktop: | |
| name: Verify octi-desktop decodes this PR's wire bytes | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout this repo at PR head | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| path: octi-web | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Detect wire-format-relevant changes | |
| id: changed | |
| working-directory: octi-web | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| base="${{ github.event.pull_request.base.sha }}" | |
| head="${{ github.event.pull_request.head.sha }}" | |
| merge_base="$(git merge-base "$base" "$head")" | |
| matches_allowlist() { | |
| local path="$1" prefix | |
| while IFS= read -r prefix; do | |
| prefix="${prefix#"${prefix%%[![:space:]]*}"}" | |
| [[ -z "$prefix" ]] && continue | |
| if [[ "$prefix" == */ ]]; then | |
| [[ "$path" == "$prefix"* ]] && return 0 | |
| else | |
| [[ "$path" == "$prefix" ]] && return 0 | |
| fi | |
| done <<< "$ALLOWLIST" | |
| return 1 | |
| } | |
| relevant=false | |
| while IFS= read -r -d '' path; do | |
| if matches_allowlist "$path"; then | |
| echo "relevant: $path" | |
| relevant=true | |
| fi | |
| done < <(git diff --name-only --no-renames -z "$merge_base" "$head" --) | |
| echo "relevant=$relevant" >> "$GITHUB_OUTPUT" | |
| if [[ "$relevant" == "false" ]]; then | |
| echo "no wire-format-relevant paths changed; consumer verify will be skipped." | |
| fi | |
| - name: Checkout octi-desktop | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| repository: d4rken-org/octi-desktop | |
| persist-credentials: false | |
| path: octi-desktop | |
| - name: Setup JDK 21 | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 | |
| with: | |
| java-version: '21' | |
| distribution: 'temurin' | |
| - name: Cache Gradle wrapper | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 | |
| with: | |
| path: | | |
| ~/.gradle/wrapper | |
| !~/.gradle/wrapper/dists/**/gradle*.zip | |
| key: ${{ runner.os }}-octi-desktop-gradle-wrapper-${{ hashFiles('octi-desktop/**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-octi-desktop-gradle-wrapper- | |
| - name: Cache Gradle dependencies | |
| if: steps.changed.outputs.relevant == 'true' | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| key: ${{ runner.os }}-octi-desktop-gradle-caches-${{ hashFiles('octi-desktop/**/*.gradle*', 'octi-desktop/**/gradle-wrapper.properties', 'octi-desktop/buildSrc/**/*.kt') }} | |
| restore-keys: | | |
| ${{ runner.os }}-octi-desktop-gradle-caches- | |
| - name: Run octi-desktop tests with fixture override | |
| if: steps.changed.outputs.relevant == 'true' | |
| working-directory: octi-desktop | |
| env: | |
| INTEROP_FIXTURE_OVERRIDES: '{"d4rken-org/octi-web":"${{ github.event.pull_request.head.sha }}"}' | |
| run: | | |
| echo "Running octi-desktop tests against this PR's octi-web HEAD (${{ github.event.pull_request.head.sha }})" | |
| chmod +x ./gradlew | |
| ./gradlew test |