diff --git a/.github/workflows/accessibility-tests.yml b/.github/workflows/accessibility-tests.yml index 529ddfadd..fef1c8f1a 100644 --- a/.github/workflows/accessibility-tests.yml +++ b/.github/workflows/accessibility-tests.yml @@ -11,7 +11,12 @@ permissions: {} jobs: tests: name: Tests - runs-on: xcode-27 + # HealthChat: skip in this fork. It runs nightly Mon-Fri and fails at checkout, because + # permissions: {} leaves a metadata-only token that cannot read an INTERNAL repo. Gated rather + # than deleted so the file keeps rebasing cleanly. Run locally with + # `swift run tools ci accessibility-tests`. + if: github.repository == 'element-hq/element-x-ios' + runs-on: macos-26 timeout-minutes: 150 concurrency: @@ -31,7 +36,7 @@ jobs: run: swift run -q tools ci accessibility-tests - name: Archive artifacts - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: failure() with: name: Results diff --git a/.github/workflows/compound-ios.yml b/.github/workflows/compound-ios.yml index 35abf3a4d..7e8d19bd9 100644 --- a/.github/workflows/compound-ios.yml +++ b/.github/workflows/compound-ios.yml @@ -20,8 +20,13 @@ permissions: {} jobs: tests: - runs-on: xcode-27 - timeout-minutes: 25 + # HealthChat: skip in this fork. It only triggers on changes under compound-ios/, which this fork + # has never edited, so it would only ever fire on an upstream sync and go red at checkout — + # permissions: {} leaves a metadata-only token that cannot read an INTERNAL repo. Gated rather + # than deleted so the file keeps rebasing cleanly. + if: github.repository == 'element-hq/element-x-ios' + runs-on: macos-26 + timeout-minutes: 15 concurrency: # When running on develop, use the sha to allow all runs of this workflow to run concurrently. @@ -34,8 +39,8 @@ jobs: with: persist-credentials: false - - name: Configure Xcode 27 - run: sudo xcode-select -s /Applications/Xcode_27.app + - name: Configure Xcode 26 + run: sudo xcode-select -s /Applications/Xcode_26.5.app - name: Install sourcery run: brew install sourcery @@ -45,11 +50,11 @@ jobs: run: sourcery --config Tools/Sourcery/PreviewTestsConfig.yml - name: Create simulator - run: xcrun simctl create "Snapshots" "iPhone SE (3rd generation)" "com.apple.CoreSimulator.SimRuntime.iOS-27-0" + run: xcrun simctl create "Snapshots" "iPhone SE (3rd generation)" "com.apple.CoreSimulator.SimRuntime.iOS-26-5" - name: Run tests working-directory: compound-ios - run: set -o pipefail && xcodebuild test -scheme 'Compound' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=Snapshots,OS=27.0' -skipPackagePluginValidation -resultBundlePath Logs/CompoundTests.xcresult | xcbeautify --renderer github-actions + run: set -o pipefail && xcodebuild test -scheme 'Compound' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=Snapshots,OS=26.5' -skipPackagePluginValidation -resultBundlePath Logs/CompoundTests.xcresult | xcbeautify --renderer github-actions - name: Zip artifacts if: failure() # We only care about artefacts if the tests fail @@ -57,7 +62,7 @@ jobs: run: zip -r Logs/CompoundTests.xcresult.zip Logs/CompoundTests.xcresult/ - name: Archive artifacts - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: failure() # We only care about artefacts if the tests fail with: name: test-results @@ -66,7 +71,7 @@ jobs: if-no-files-found: ignore - name: Upload coverage to Codecov - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: fail_ci_if_error: false token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 0fe579d3a..ac563cc90 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -11,7 +11,14 @@ permissions: {} jobs: integration_tests: name: Integration Tests - runs-on: xcode-27 + # HealthChat: skip in this fork. It runs nightly Mon-Fri and fails at checkout, and it is the one + # job that still calls out to Element's Codecov — its upload guard is true on schedule events, so + # it POSTs slug/branch/SHA every night with continue-on-error hiding the failure. Fixing it would + # need a real healthchat.ch test account and three new secrets, and would still not work: + # HealthChatAppSettingsHook sets allowOtherAccountProviders: false, hiding the change-server UI + # these tests drive. Gated rather than deleted so the file keeps rebasing cleanly. + if: github.repository == 'element-hq/element-x-ios' + runs-on: macos-26 timeout-minutes: 45 concurrency: @@ -35,7 +42,7 @@ jobs: INTEGRATION_TESTS_PASSWORD: ${{ secrets.INTEGRATION_TESTS_PASSWORD }} - name: Archive artifacts - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # We only care about artefacts if the tests fail if: failure() with: @@ -49,7 +56,7 @@ jobs: - name: Upload coverage to Codecov # Skip if not successful and in forks if: ${{ success() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: report_type: coverage files: test_output/integration-cobertura.xml @@ -61,7 +68,7 @@ jobs: - name: Upload test results to Codecov # Skip if cancelled and in forks if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 continue-on-error: true with: report_type: test_results diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index f9b8d01a5..76fcac3a7 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -15,7 +15,13 @@ permissions: {} jobs: tests: name: Tests - runs-on: xcode-27 + # HealthChat: skip in this fork. It runs nightly Mon-Fri and fails at checkout, because + # permissions: {} leaves a metadata-only token that cannot read an INTERNAL repo. Fixing the + # permission would not help: the rebrand changed the start screen without re-recording any + # UITests snapshot, so it would fail on content instead. Gated rather than deleted so the file + # keeps rebasing cleanly. Run locally with `swift run tools ci ui-tests`. + if: github.repository == 'element-hq/element-x-ios' + runs-on: macos-26 timeout-minutes: 90 strategy: fail-fast: false @@ -46,7 +52,7 @@ jobs: GITHUB_EVENT_INPUTS_TEST_NAME: ${{ github.event.inputs.test_name }} - name: Archive artifacts - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # We only care about artefacts if the tests fail if: failure() with: @@ -58,7 +64,7 @@ jobs: - name: Upload coverage to Codecov # Skip if not successful and in forks if: ${{ success() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: report_type: coverage files: test_output/ui-cobertura.xml @@ -70,7 +76,7 @@ jobs: - name: Upload test results to Codecov # Skip if cancelled and in forks if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 continue-on-error: true with: report_type: test_results diff --git a/.github/workflows/unit-tests-enterprise.yml b/.github/workflows/unit-tests-enterprise.yml index fd97fe0c4..c881c8fb5 100644 --- a/.github/workflows/unit-tests-enterprise.yml +++ b/.github/workflows/unit-tests-enterprise.yml @@ -17,7 +17,14 @@ jobs: timeout-minutes: 60 # Skip in forks - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + # HealthChat: this job can never pass in this fork — it needs + # secrets.ELEMENT_BOT_TOKEN (Element's bot, absent here) and recursively + # checks out the private element-hq/element-ios-enterprise submodule, which + # Novaloop cannot obtain. The guard below only asks whether the PR comes + # FROM a fork, not whether this repo IS one, so it does not skip us. Gate on + # the upstream repo as post-release.yml does. Gated rather than deleted so + # the file keeps rebasing cleanly against upstream. + if: ${{ github.repository == 'element-hq/element-x-ios' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} concurrency: # Only allow a single run of this workflow on each branch, automatically cancelling older runs. diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 6685c042b..85f4ab9f3 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -13,8 +13,18 @@ permissions: {} jobs: tests: name: Tests - runs-on: xcode-27 - timeout-minutes: 80 + # HealthChat: GitHub-hosted macos-26 could not finish this job inside + # timeout-minutes: 60 (two attempts: 51m42s, then killed at 60m44s), and macOS + # minutes bill at 10x. novaloop-mac-studio-001 is the org's Mac Studio, already + # used by the release pipeline; its labels are [self-hosted, macOS, ARM64]. + runs-on: [self-hosted, macOS] + # Upstream's 60 is kept: with previews skipped (see Run tests) the build plus unit tests measured + # ~16 min here. A run approaching this budget is a signal, not normal — the earlier 60m timeouts + # were preview tests, not the build. + timeout-minutes: 60 + + permissions: + contents: read # HealthChat: this fork is INTERNAL, so a metadata-only token 404s on checkout (and on git lfs pull). Upstream is public, hence permissions: {} there. concurrency: # Only allow a single run of this workflow on each branch, automatically cancelling older runs. @@ -22,12 +32,44 @@ jobs: cancel-in-progress: true steps: + # HealthChat: upstream passes persist-credentials: false here, which the + # composite forwards to actions/checkout — stripping the auth header before + # its separate "Git LFS Pull" step runs. Upstream can afford that because + # its repo is public and git lfs pull works anonymously; this fork is + # INTERNAL, so the LFS batch endpoint would 404. Keep the composite's own + # default (true) so the pull is authenticated with GITHUB_TOKEN. - uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - with: - persist-credentials: false - - name: Setup environment - run: source ci_scripts/ci_common.sh && setup_github_actions_environment + # HealthChat: verify only — never provision. Upstream's + # setup_github_actions_environment cannot run on this runner: it calls + # `sudo xcode-select -s /Applications/Xcode_26.5.0.app`, but the runner has no + # passwordless sudo and no such path (only /Applications/Xcode.app exists), and + # it calls `brew update && brew install ...` — novaloop-mac-studio-001 is the + # shared release machine, so a per-run `brew update` could upgrade xcodegen + # underneath the release pipeline. These tools are installed once by hand; CI + # only asserts they are present and fails loudly, naming the fix, if not. + - name: Verify environment + run: | + set -eu + missing="" + formulae="" + for tool in xcodegen swiftlint swiftformat xcbeautify xcresultparser pkl git-lfs; do + if ! command -v "$tool" >/dev/null 2>&1; then + missing="$missing $tool" + case "$tool" in + # Not in homebrew-core; only this tap ships it. + xcresultparser) formulae="$formulae a7ex/homebrew-formulae/xcresultparser" ;; + *) formulae="$formulae $tool" ;; + esac + fi + done + if [ -n "$missing" ]; then + echo "::error::Missing on self-hosted runner:${missing}. Install by hand on novaloop-mac-studio-001, then re-run: brew install${formulae}" + exit 1 + fi + # The Xcode version is no longer pinned anywhere, so this is the only record + # of which Xcode built a given run. + xcodebuild -version - name: Restore compilation cache uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 @@ -37,7 +79,12 @@ jobs: restore-keys: compilation-cache-unit-tests- - name: Run tests - run: swift run -q tools ci unit-tests + # HealthChat: previews are skipped. PreviewTests renders a snapshot for every preview in the + # app and was the entire reason this job could not fit in an hour — it never once finished, + # on either runner. Unit tests alone take ~16 min here. Upstream skips them the same way in + # unit-tests-enterprise.yml. Cost: preview snapshot regressions are not caught in CI, so + # re-record and check them locally when changing UI. + run: swift run -q tools ci unit-tests --skip-previews - name: Save compilation cache # Only develop populates the cache, all of the other runs simply read from it. @@ -48,7 +95,7 @@ jobs: key: compilation-cache-unit-tests-${{ github.sha }} - name: Archive artifacts - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # We only care about artefacts if the tests fail if: failure() with: @@ -59,8 +106,12 @@ jobs: - name: Upload coverage to Codecov # Skip if not successful and in forks - if: ${{ success() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 + # HealthChat: the existing guard only asks whether the PR comes FROM a + # fork, not whether this repo IS one, so it is true here and the step + # runs without a CODECOV_TOKEN — which fails the job via + # fail_ci_if_error. Gate on the upstream repo as post-release.yml does. + if: ${{ success() && github.repository == 'element-hq/element-x-ios' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: report_type: coverage files: test_output/unit-cobertura.xml,test_output/preview-cobertura.xml @@ -71,8 +122,10 @@ jobs: - name: Upload test results to Codecov # Skip if cancelled and in forks - if: ${{ !cancelled() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 + # HealthChat: gated on the upstream repo for the same reason as the + # coverage step above — no CODECOV_TOKEN exists in this fork. + if: ${{ !cancelled() && github.repository == 'element-hq/element-x-ios' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 continue-on-error: true with: report_type: test_results diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 308554586..253127675 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -14,6 +14,8 @@ jobs: runs-on: ubuntu-latest permissions: security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. + contents: read # HealthChat: this fork is INTERNAL, so a metadata-only token 404s on checkout. Upstream is public, hence permissions: {} there. + actions: read # HealthChat: upload-sarif additionally needs this on private/internal repos; public upstream does not. steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1