Repository navigation
fix(mobile): show Check for updates in Settings #30
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: Fork CI | |
| # The commands of ci.yml on GitHub-hosted runners. ci.yml uses upstream's | |
| # Blacksmith runners, which this fork does not have, so the fork disables it. | |
| # Limit: this file copies the ci.yml commands by hand. When upstream changes | |
| # them, update this file. A failure on main calls the repair agent. See docs/fork/operations.md "Fork CI". | |
| # | |
| # The heavy jobs run only when the push or pull request changes code. The changes job | |
| # compares a push with the last green run, so a cancelled or failed run never hides a | |
| # change. It compares a pull request with its base. | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| notify_agent: | |
| description: Call the agent webhook if this run fails. The agent sets false on its own retries. | |
| type: boolean | |
| default: true | |
| permissions: | |
| contents: read | |
| # A newer push to the same branch or pull request cancels the older run. A manual run waits instead. | |
| concurrency: | |
| group: fork-ci-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name != 'workflow_dispatch' }} | |
| jobs: | |
| changes: | |
| name: Changes | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| permissions: | |
| actions: read | |
| contents: read | |
| outputs: | |
| code: ${{ steps.classify.outputs.code }} | |
| files: ${{ steps.classify.outputs.files }} | |
| machine_map: ${{ steps.classify.outputs.machine_map }} | |
| steps: | |
| - name: Classify the changed files | |
| id: classify | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| set -euo pipefail | |
| code() { echo "code=true" >>"$GITHUB_OUTPUT"; echo "$1: the heavy jobs run."; exit 0; } | |
| head="$GITHUB_SHA" | |
| case "$GITHUB_EVENT_NAME" in | |
| push) | |
| base="$(gh run list --repo "$GITHUB_REPOSITORY" --workflow fork-ci.yml --branch "$GITHUB_REF_NAME" \ | |
| --event push --status success --limit 1 --json headSha --jq '.[0].headSha // empty')" | |
| [[ -n "$base" ]] || code "No green run to compare with" | |
| ;; | |
| pull_request) | |
| base="$PR_BASE_SHA" | |
| head="$PR_HEAD_SHA" | |
| ;; | |
| *) code "Manual run" ;; | |
| esac | |
| # The compare API lists at most 300 files. A longer list counts as code. | |
| files="$(gh api "repos/$GITHUB_REPOSITORY/compare/$base...$head" --jq '.files[].filename')" || | |
| code "The compare with $base failed" | |
| (($(wc -l <<<"$files") < 300)) || code "300 or more changed files" | |
| while IFS= read -r file; do | |
| [[ -n "$file" ]] || continue | |
| case "$file" in | |
| docs/* | *.md) ;; | |
| apps/machine-map/*) echo "machine_map=true" >>"$GITHUB_OUTPUT" ;; | |
| *) code "$file changed since $base" ;; | |
| esac | |
| done <<<"$files" | |
| echo "code=false" >>"$GITHUB_OUTPUT" | |
| { echo "files<<EOF"; echo "$files"; echo "EOF"; } >>"$GITHUB_OUTPUT" | |
| echo "Only docs, markdown or apps/machine-map changed since $base: only lint and the machine map job run." | |
| # The heavy jobs also cover apps/machine-map. This job checks it alone when nothing else changed. | |
| machine_map: | |
| name: Machine map | |
| needs: changes | |
| if: needs.changes.outputs.code == 'false' && needs.changes.outputs.machine_map == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: | | |
| - args: ["--filter", "@t3tools/machine-map...", "--filter", "@t3tools/monorepo"] | |
| - run: vp run --filter @t3tools/machine-map typecheck | |
| - run: vp run --filter @t3tools/machine-map test | |
| lint: | |
| name: Lint | |
| needs: changes | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: true | |
| - if: needs.changes.outputs.code == 'true' | |
| run: vp run --filter @t3tools/desktop ensure:electron | |
| - if: needs.changes.outputs.code == 'true' | |
| run: vp run knip:check | |
| - if: needs.changes.outputs.code == 'true' | |
| run: vp check | |
| - name: Check the changed files | |
| if: needs.changes.outputs.code != 'true' | |
| env: | |
| FILES: ${{ needs.changes.outputs.files }} | |
| run: | | |
| existing=() | |
| scripts=() | |
| while IFS= read -r file; do | |
| [[ -f "$file" ]] || continue | |
| existing+=("$file") | |
| case "$file" in *.ts | *.tsx | *.js | *.jsx | *.mjs | *.cjs) scripts+=("$file") ;; esac | |
| done <<<"$FILES" | |
| # vp check fails when no file is lintable, so markdown gets only the format check. | |
| if ((${#existing[@]} > 0)); then vp fmt --check "${existing[@]}"; fi | |
| if ((${#scripts[@]} > 0)); then vp check "${scripts[@]}"; fi | |
| # On both paths, because a code change can rename a file that a doc links to. | |
| - name: Check the links of the fork docs | |
| run: node scripts/fork-check-doc-links.ts | |
| typecheck: | |
| name: Typecheck | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: true | |
| - run: vp run --filter @t3tools/desktop ensure:electron | |
| - run: vpr typecheck | |
| build: | |
| name: Build | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - run: sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config | |
| - uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: true | |
| - run: vp run --filter @t3tools/desktop ensure:electron | |
| - run: vp run build:desktop | |
| - run: node apps/desktop/scripts/verify-preload-bundle.mjs | |
| test: | |
| name: Test ${{ matrix.group }} | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| # Two runners: on one runner, the slowest packages wait for each other. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - group: apps | |
| filters: --filter @t3tools/mobile --filter @t3tools/desktop --filter @t3tools/oxlint-plugin-t3code | |
| - group: packages | |
| filters: >- | |
| --filter '!t3' --filter '!@t3tools/monorepo' --filter '!@t3tools/web' | |
| --filter '!@t3tools/mobile' --filter '!@t3tools/desktop' --filter '!@t3tools/oxlint-plugin-t3code' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential libsecret-1-dev pkg-config | |
| - uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: true | |
| - run: vp run --filter @t3tools/desktop ensure:electron | |
| - if: matrix.group == 'packages' | |
| run: python3 -B .github/scripts/stage-preview-bundle.test.py | |
| - if: matrix.group == 'packages' | |
| run: node --test .github/scripts/check-nightly-release.test.cjs | |
| - run: vp run --parallel --concurrency-limit 4 ${{ matrix.filters }} test | |
| test_web: | |
| name: Test Web | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: true | |
| # The browser project runs React tests in headless Chromium. | |
| - run: node apps/web/node_modules/playwright/cli.js install --with-deps --only-shell chromium | |
| - run: vp run --filter @t3tools/web test | |
| test_server: | |
| name: Test Server ${{ matrix.shard }} | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [1, 2, 3, 4, 5, 6, 7, 8] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: true | |
| - run: node apps/server/node_modules/playwright-core/cli.js install --with-deps --only-shell chromium | |
| - run: vp run --filter t3 test --shard ${{ matrix.shard }}/${{ strategy.job-total }} | |
| rust: | |
| name: Rust | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| /* | |
| !/.repos/ | |
| sparse-checkout-cone-mode: false | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| - name: Check formatting and test | |
| run: | | |
| for crate in resource-monitor kde-snap-shot hyprland-snap-shot; do | |
| cargo fmt --manifest-path "native/$crate/Cargo.toml" -- --check | |
| cargo test --locked --manifest-path "native/$crate/Cargo.toml" | |
| done | |
| # The one check that branch protection requires. A skipped job counts as passed, | |
| # so the docs-only path passes too. A cancelled job counts as failed. | |
| result: | |
| name: Fork CI result | |
| needs: [changes, lint, machine_map, typecheck, build, test, test_web, test_server, rust] | |
| if: always() | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Check the job results | |
| if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') | |
| env: | |
| NEEDS_JSON: ${{ toJSON(needs) }} | |
| run: | | |
| jq -r 'to_entries[] | "\(.key): \(.value.result)"' <<<"$NEEDS_JSON" | |
| exit 1 | |
| # Starts the repair agent, like Fork Sync and Fork Release. Without it, a red | |
| # main goes unnoticed. Off until the T3_AGENT_WEBHOOK_URL secret is set. | |
| # A pull request never calls it: its author sees the failed check. | |
| notify_agent: | |
| name: Notify repair agent | |
| needs: [changes, lint, machine_map, typecheck, build, test, test_web, test_server, rust] | |
| if: failure() && github.event_name != 'pull_request' && github.event.inputs.notify_agent != 'false' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| permissions: | |
| actions: read | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: scripts/fork-notify-agent.sh | |
| sparse-checkout-cone-mode: false | |
| - name: Call agent webhook | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| WEBHOOK_URL: ${{ secrets.T3_AGENT_WEBHOOK_URL }} | |
| CF_ACCESS_CLIENT_ID: ${{ secrets.CF_ACCESS_CLIENT_ID }} | |
| CF_ACCESS_CLIENT_SECRET: ${{ secrets.CF_ACCESS_CLIENT_SECRET }} | |
| NEEDS_JSON: ${{ toJSON(needs) }} | |
| run: scripts/fork-notify-agent.sh |