Repository navigation
Simplify node graph runtime scheduling #3203
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: "Check" | |
| on: | |
| pull_request: {} | |
| merge_group: {} | |
| # Checking each master commit also fills the compilation cache, which only master pushes may write to | |
| push: | |
| branches: | |
| - master | |
| # Cancel a PR's in-progress checks once a newer commit is pushed to it (other runs are keyed by their commit, so those never cancel each other) | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: true | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| # Skip a merge queue run's checks when another Check run already passed them on the exact same content (Git tree) | |
| skip-check: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| # Read the trees of the merge queue commit and of the commits other runs tested | |
| contents: read | |
| # Find the head commit of the PR being merged | |
| pull-requests: read | |
| # List this workflow's other runs | |
| actions: read | |
| outputs: | |
| skip: ${{ steps.check.outputs.skip }} | |
| steps: | |
| - name: 🚦 Check if CI can be skipped | |
| id: check | |
| # A failed or hung step leaves the output unset, which runs the checks | |
| continue-on-error: true | |
| timeout-minutes: 2 | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| MERGE_GROUP_HEAD_REF: ${{ github.event.merge_group.head_ref }} | |
| MERGE_GROUP_HEAD_SHA: ${{ github.event.merge_group.head_sha }} | |
| run: | | |
| if [ "$GITHUB_EVENT_NAME" != "merge_group" ]; then | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| echo "Not a merge queue run, so the checks will run" | |
| exit 0 | |
| fi | |
| # Records the decision and shows its reason on the run's summary page | |
| decide() { | |
| echo "skip=$1" >> "$GITHUB_OUTPUT" | |
| echo "::notice::$2" | |
| exit 0 | |
| } | |
| # Prints the tree of a commit, which is the hash of its exact file content | |
| tree_of() { | |
| local tree | |
| tree=$(gh api "$repository_api/git/commits/$1" --jq '.tree.sha') && [[ "$tree" =~ ^[0-9a-f]{40}$ ]] && echo "$tree" | |
| } | |
| repository_api="repos/$GITHUB_REPOSITORY" | |
| workflow_path="${GITHUB_WORKFLOW_REF%%@*}" | |
| workflow_runs_api="$repository_api/actions/workflows/${workflow_path##*/}/runs" | |
| merge_queue_branch="${MERGE_GROUP_HEAD_REF#refs/heads/}" | |
| merge_group_tree=$(tree_of "$MERGE_GROUP_HEAD_SHA") || decide false "Running the checks since the merge queue commit $MERGE_GROUP_HEAD_SHA couldn't be read" | |
| echo "The merge queue commit $MERGE_GROUP_HEAD_SHA has tree $merge_group_tree" | |
| [[ "$merge_queue_branch" =~ ^gh-readonly-queue/.+/pr-([0-9]+)-[0-9a-f]+$ ]] || decide false "Running the checks since the merge queue branch '$merge_queue_branch' doesn't name a PR" | |
| pr_number="${BASH_REMATCH[1]}" | |
| pr_head_sha=$(gh api "$repository_api/pulls/$pr_number" --jq '.head.sha') || decide false "Running the checks since PR #$pr_number couldn't be read" | |
| # The PR's own runs check out the PR merged into its base branch at that moment, which matches this content if the PR was up to date or its base hasn't moved since. | |
| # Each run records the commit it loaded the local build.yml from (called by the build job below), and that is the merge commit it checked out. | |
| export PR_MERGE_REF="refs/pull/$pr_number/merge" | |
| pr_run=$(gh api -X GET "$workflow_runs_api" -f event=pull_request -f head_sha="$pr_head_sha" -f exclude_pull_requests=true -f per_page=100 --jq ' | |
| [.workflow_runs[] | select(.conclusion != "cancelled")] | max_by(.created_at) // empty | |
| | "\(.html_url) \(.conclusion // .status) \([.referenced_workflows[]? | select(.ref == $ENV.PR_MERGE_REF) | .sha] | first // "unknown")" | |
| ') || decide false "Running the checks since the Check runs of PR #$pr_number couldn't be listed" | |
| if [ -z "$pr_run" ]; then | |
| echo "PR #$pr_number's head commit $pr_head_sha has no Check run that wasn't cancelled" | |
| else | |
| read -r pr_run_url pr_run_result pr_tested_sha <<< "$pr_run" | |
| echo "The newest Check run of PR #$pr_number's head commit $pr_head_sha is $pr_run_url ($pr_run_result), which tested commit $pr_tested_sha" | |
| if [ "$pr_run_result" != "success" ]; then | |
| echo "That run hasn't succeeded" | |
| elif ! pr_tested_tree=$(tree_of "$pr_tested_sha"); then | |
| echo "The commit that run tested couldn't be read" | |
| elif [ "$pr_tested_tree" = "$merge_group_tree" ]; then | |
| decide true "Skipping the checks since $pr_run_url already passed on commit $pr_tested_sha, which has this exact content" | |
| else | |
| echo "That run tested different content (tree $pr_tested_tree)" | |
| fi | |
| fi | |
| # A merge queue branch name pairs the PR with the commit it's built on, so an earlier run with this name may have passed on the same content before the PR was queued again | |
| earlier_runs=$(gh api -X GET "$workflow_runs_api" -f event=merge_group -f status=success -f branch="$merge_queue_branch" -f exclude_pull_requests=true -f per_page=100 --jq ' | |
| .workflow_runs[] | select(.id | tostring != $ENV.GITHUB_RUN_ID) | "\(.head_sha) \(.html_url)" | |
| ') || decide false "Running the checks since the earlier merge queue runs couldn't be listed" | |
| while read -r earlier_sha earlier_url; do | |
| [ -n "$earlier_sha" ] || continue | |
| if earlier_tree=$(tree_of "$earlier_sha") && [ "$earlier_tree" = "$merge_group_tree" ]; then | |
| decide true "Skipping the checks since $earlier_url already passed on merge queue commit $earlier_sha, which has this exact content" | |
| fi | |
| done <<< "$earlier_runs" | |
| decide false "Running the checks since no successful Check run has tested this exact content" | |
| # Build the web app via the shared build workflow | |
| build: | |
| needs: skip-check | |
| # Always called with the skip decision passed in, since a skipped caller job reports only as `build` and leaves the required `build / web` check missing. | |
| # Like the jobs below, the checks still run if `skip-check` itself fails, since a skipped job counts as passing for required checks. | |
| # Master pushes are left out because `build.yml` builds and deploys those itself. | |
| if: ${{ !cancelled() && github.event_name != 'push' }} | |
| uses: ./.github/workflows/build.yml | |
| # The called workflow's jobs can only narrow these, so this grants the union of what they request | |
| permissions: | |
| actions: write | |
| contents: write | |
| deployments: write | |
| id-token: write | |
| pull-requests: write | |
| secrets: inherit | |
| with: | |
| web: ${{ needs.skip-check.outputs.skip != 'true' }} | |
| merge_queue: ${{ github.event_name == 'merge_group' }} | |
| # Run the Rust tests | |
| test: | |
| needs: skip-check | |
| if: ${{ !cancelled() && needs.skip-check.outputs.skip != 'true' }} | |
| # Fork PRs always run on GitHub's own runners, while the `LINUX_RUNNER` repo variable can point the rest at another provider | |
| runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || vars.LINUX_RUNNER || 'ubuntu-latest' }} | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_INCREMENTAL: 0 | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: "true" | |
| # Only master pushes write to the compilation cache, so unmerged code can't plant entries that later master builds reuse | |
| SCCACHE_GHA_RW_MODE: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/master') && 'READ_WRITE' || 'READ_ONLY' }} | |
| # NOTICE: keep in sync with the web job in `build.yml` | |
| SCCACHE_VERSION: "v0.19.0" | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| - name: 🦀 Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 | |
| with: | |
| toolchain: stable | |
| override: true | |
| cache: false | |
| rustflags: "" | |
| - name: 📦 Install sccache | |
| uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 | |
| with: | |
| version: ${{ env.SCCACHE_VERSION }} | |
| - name: 🦀 Fetch Rust dependencies | |
| run: cargo fetch --locked | |
| - name: 🧪 Run Rust tests | |
| env: | |
| # `--cfg=web_sys_unstable_apis` mirrors the `[build]` section of `.cargo/config.toml` | |
| RUSTFLAGS: "-Dwarnings --cfg=web_sys_unstable_apis" | |
| run: cargo test --all-features | |
| # The plain `cargo test` above only covers the workspace's default members, which leave these out | |
| - name: 🧪 Run document migration tests | |
| env: | |
| RUSTFLAGS: "-Dwarnings --cfg=web_sys_unstable_apis" | |
| run: >- | |
| cargo test --all-features | |
| --package migration-core | |
| --package migration-runner | |
| --package migration-formats | |
| --package migration-nodes | |
| --package migration-snapshot | |
| --package document-graph-storage | |
| --package document-format | |
| --package graphene-cli | |
| --package regression | |
| # Render the documents of the regression corpus and compare them with their reference images | |
| regression-corpus: | |
| needs: skip-check | |
| if: ${{ !cancelled() && needs.skip-check.outputs.skip != 'true' }} | |
| runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || vars.LINUX_RUNNER || 'ubuntu-latest' }} | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_INCREMENTAL: 0 | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: "true" | |
| # Only master pushes write to the compilation cache, so unmerged code can't plant entries that later master builds reuse | |
| SCCACHE_GHA_RW_MODE: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/master') && 'READ_WRITE' || 'READ_ONLY' }} | |
| # NOTICE: keep in sync with the test job above and the web job in `build.yml` | |
| SCCACHE_VERSION: "v0.19.0" | |
| RUSTFLAGS: "-Dwarnings --cfg=web_sys_unstable_apis" | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| - name: 📥 Clone regression corpus | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| repository: tagtraumen/graphite-corpus | |
| path: target/regression-corpus | |
| lfs: true | |
| - name: 🦀 Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 | |
| with: | |
| toolchain: stable | |
| override: true | |
| cache: false | |
| rustflags: "" | |
| - name: 📦 Install sccache | |
| uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 | |
| with: | |
| version: ${{ env.SCCACHE_VERSION }} | |
| # GitHub's runners have no GPU, so rendering falls back to Mesa's software Vulkan driver | |
| - name: 🎮 Install a software Vulkan driver | |
| run: sudo apt-get update && sudo apt-get install --yes mesa-vulkan-drivers | |
| - name: 🖼️ Check the corpus renders against its references | |
| run: cargo run --package regression -- --corpus target/regression-corpus check --output target/regression | |
| - name: 📤 Upload the renders and diffs of mismatches | |
| if: ${{ failure() }} | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 | |
| with: | |
| name: regression-mismatches | |
| path: target/regression | |
| if-no-files-found: ignore | |
| # Stored types, node version lineages, and node APIs against the base commit. Only needs the snapshot tool, so it runs on a GitHub runner | |
| migrations: | |
| needs: skip-check | |
| # Master pushes are left out because they have no base commit, and the PR and merge queue runs already compared against it | |
| if: ${{ !cancelled() && needs.skip-check.outputs.skip != 'true' && github.event_name != 'push' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha }} | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| - name: 🦀 Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 | |
| with: | |
| toolchain: stable | |
| override: true | |
| cache: false | |
| rustflags: "" | |
| - name: 📥 Fetch the base commit | |
| run: git fetch --depth=1 origin "$BASE_SHA" | |
| - name: 🔬 Check migrations against the base commit | |
| run: cargo run --locked --package migration-snapshot -- check --baseline "$BASE_SHA" | |
| # Rust format check on GitHub runner | |
| rust-fmt: | |
| needs: skip-check | |
| if: ${{ !cancelled() && needs.skip-check.outputs.skip != 'true' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| - name: 🦀 Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 | |
| with: | |
| toolchain: stable | |
| override: true | |
| cache: false | |
| rustflags: "" | |
| components: rustfmt | |
| - name: 🔬 Check Rust formatting | |
| run: cargo fmt --all -- --check | |
| # License compatibility check on GitHub runner | |
| check-licenses: | |
| needs: skip-check | |
| if: ${{ !cancelled() && needs.skip-check.outputs.skip != 'true' }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 📥 Clone repository | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| - name: 📜 Check crate license compatibility for root workspace | |
| uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2.1.1 | |
| with: | |
| command: check bans licenses sources | |
| - name: 📜 Check crate license compatibility for /libraries/rawkit | |
| uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2.1.1 | |
| with: | |
| command: check bans licenses sources | |
| manifest-path: libraries/rawkit/Cargo.toml |