Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 87 additions & 23 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
push:
branches:
- master
tags:
- latest-stable
workflow_dispatch:
inputs:
web:
Expand Down Expand Up @@ -59,8 +61,6 @@ jobs:
RUSTC_WRAPPER: /usr/bin/sccache
CARGO_INCREMENTAL: 0
SCCACHE_DIR: /var/lib/github-actions/.cache
INDEX_HTML_HEAD_REPLACEMENT: <script defer data-domain="dev.graphite.art" data-api="https://graphite.art/visit/event" src="https://graphite.art/visit/script.hash.js"></script>

steps:
- name: 📥 Clone repository
uses: actions/checkout@v6
Expand Down Expand Up @@ -90,9 +90,20 @@ jobs:
rustflags: ""
target: wasm32-unknown-unknown

- name: ✂ Replace template in <head> of index.html
- name: 🔀 Choose production deployment environment and insert template
id: production-env
if: github.event_name == 'push'
run: sed -i "s|<!-- INDEX_HTML_HEAD_REPLACEMENT -->|$INDEX_HTML_HEAD_REPLACEMENT|" frontend/index.html
run: |
if [[ "${{ github.ref }}" == "refs/tags/latest-stable" ]]; then
echo "cf_project=graphite-editor" >> $GITHUB_OUTPUT
DOMAIN="editor.graphite.art"
else
echo "cf_project=graphite-dev" >> $GITHUB_OUTPUT
DOMAIN="dev.graphite.art"
fi
TEMPLATE="<script defer data-domain=\"$DOMAIN\" data-api=\"https://graphite.art/visit/event\" src=\"https://graphite.art/visit/script.hash.js\"></script>"
echo "template=$TEMPLATE" >> $GITHUB_OUTPUT
sed -i "s|<!-- INDEX_HTML_HEAD_REPLACEMENT -->|$TEMPLATE|" frontend/index.html

- name: 🌐 Build Graphite web code
env:
Expand All @@ -105,28 +116,70 @@ jobs:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: |
MAX_ATTEMPTS=5
DELAY=30
if [ -z "$CLOUDFLARE_API_TOKEN" ]; then
echo "No Cloudflare API token available (fork PR), skipping deploy."
exit 0
fi
MAX_ATTEMPTS=8
DELAY=15
for ATTEMPT in $(seq 1 $MAX_ATTEMPTS); do
echo "Attempt $ATTEMPT of $MAX_ATTEMPTS..."
if OUTPUT=$(npx wrangler@3 pages deploy "frontend/dist" --project-name="graphite-dev" --commit-dirty=true 2>&1); then
URL=$(echo "$OUTPUT" | grep -oP 'https://[^\s]+\.pages\.dev' | head -1)
npx wrangler@3 pages deploy "frontend/dist" --project-name="${{ steps.production-env.outputs.cf_project || 'graphite-dev' }}" --commit-dirty=true 2>&1 | tee /tmp/wrangler_output
if [ ${PIPESTATUS[0]} -eq 0 ]; then
URL=$(grep -oP 'https://[^\s]+\.pages\.dev' /tmp/wrangler_output | head -1)
echo "url=$URL" >> "$GITHUB_OUTPUT"
echo "Published successfully: $URL"
exit 0
fi
echo "Attempt $ATTEMPT failed:"
echo "$OUTPUT"
echo "Attempt $ATTEMPT failed."
if [ "$ATTEMPT" -lt "$MAX_ATTEMPTS" ]; then
echo "Retrying in ${DELAY}s..."
sleep $DELAY
DELAY=$((DELAY * 3))
DELAY=$((DELAY * 2))
fi
done
echo "All $MAX_ATTEMPTS Cloudflare Pages publish attempts failed."
exit 1

- name: 🚀 Create a GitHub environment deployment
if: inputs.checkout_repo == '' || inputs.checkout_repo == github.repository
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CF_URL: ${{ steps.cloudflare.outputs.url }}
run: |
if [ -z "$CF_URL" ]; then
echo "No Cloudflare URL available, skipping deployment."
exit 0
fi
if [ "${{ github.ref }}" = "refs/tags/latest-stable" ]; then
REF="latest-stable"
ENVIRONMENT="graphite-editor (Production)"
elif [ "${{ github.event_name }}" = "push" ]; then
REF="master"
ENVIRONMENT="graphite-dev (Production)"
else
REF="${{ inputs.checkout_ref || github.head_ref || github.ref_name }}"
ENVIRONMENT="graphite-dev (Preview)"
fi
DEPLOY_ID=$(gh api \
-X POST \
-H "Accept: application/vnd.github+json" \
repos/${{ github.repository }}/deployments \
--input - \
--jq '.id' <<EOF
{"ref":"$REF","environment":"$ENVIRONMENT","auto_merge":false,"required_contexts":[]}
EOF
)
gh api \
-X POST \
-H "Accept: application/vnd.github+json" \
repos/${{ github.repository }}/deployments/$DEPLOY_ID/statuses \
-f state=success \
-f environment_url="$CF_URL" \
-f log_url="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

- name: 💬 Comment with the build link
if: github.event_name != 'pull_request' && github.event_name != 'merge_group'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CF_URL: ${{ steps.cloudflare.outputs.url }}
Expand All @@ -140,15 +193,18 @@ jobs:
|-|
| $CF_URL |"

if [ "${{ github.event_name }}" = "push" ]; then
# Comment on the commit hash page
if [ "${{ github.ref }}" = "refs/tags/latest-stable" ]; then
# Push tag: skip commenting (commit was already commented on master merge)
echo "Tag push, skipping comment."
elif [ "${{ github.event_name }}" = "push" ]; then
# Push master: comment on the commit hash page
gh api \
-X POST \
-H "Accept: application/vnd.github+json" \
repos/${{ github.repository }}/commits/$(git rev-parse HEAD)/comments \
-f body="$COMMENT_BODY"
else
# Comment on the PR (use provided PR number from !build, or look it up by branch name)
elif [ "${{ github.event_name }}" != "pull_request" ] && [ "${{ github.event_name }}" != "merge_group" ]; then
# Manual trigger (workflow_dispatch, !build): comment on the PR
PR_NUMBER="${{ inputs.pr_number }}"
if [ -z "$PR_NUMBER" ]; then
BRANCH=$(git rev-parse --abbrev-ref HEAD)
Expand All @@ -162,18 +218,26 @@ jobs:
fi
fi

- name: ✂ Strip analytics script from built output for clean artifact
- name: ✂ Strip template from completed build for a clean artifact
if: github.event_name == 'push'
run: sed -i "s|$INDEX_HTML_HEAD_REPLACEMENT||" frontend/dist/index.html
run: sed -i "s|${{ steps.production-env.outputs.template }}||" frontend/dist/index.html
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated

- name: 📦 Upload web bundle artifact
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v6
with:
name: graphite-web-bundle
path: frontend/dist

- name: 👕 Lint Graphite web formatting
env:
NODE_ENV: production
run: |
cd frontend
npm run check

- name: 📃 Trigger website rebuild if auto-generated code docs are stale
if: github.event_name == 'push'
if: github.event_name == 'push' && github.ref != 'refs/tags/latest-stable'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Expand All @@ -184,7 +248,7 @@ jobs:
|| gh workflow run website.yml --ref master

windows:
if: github.event_name == 'push' || inputs.windows
if: (github.event_name == 'push' && github.ref != 'refs/tags/latest-stable') || inputs.windows
runs-on: windows-latest
permissions:
contents: read
Expand Down Expand Up @@ -214,8 +278,8 @@ jobs:
uses: actions/cache@v5
with:
path: |
${{ env.USERPROFILE }}\.cargo\registry
${{ env.USERPROFILE }}\.cargo\git
~/.cargo/registry
~/.cargo/git
target
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}

Expand Down Expand Up @@ -376,7 +440,7 @@ jobs:
path: target/artifacts

mac:
if: github.event_name == 'push' || inputs.mac
if: (github.event_name == 'push' && github.ref != 'refs/tags/latest-stable') || inputs.mac
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why, I would expect it to also build on pushing the tag.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That build already occurs when we originally push the commit. We haven't yet set up GitHub Releases deployments, but this clause will be removed when we do that.

runs-on: macos-latest
permissions:
contents: read
Expand Down Expand Up @@ -554,7 +618,7 @@ jobs:
path: target/artifacts

linux:
if: github.event_name == 'push' || inputs.linux
if: (github.event_name == 'push' && github.ref != 'refs/tags/latest-stable') || inputs.linux
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down
79 changes: 6 additions & 73 deletions .github/workflows/ci.yml → .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "CI"
name: "Check"

on:
pull_request: {}
Expand All @@ -8,78 +8,12 @@ env:
CARGO_TERM_COLOR: always

jobs:
# Build the web app on the self-hosted wasm runner
# Build the web app via the shared build workflow
build:
runs-on: [self-hosted, target/wasm]
permissions:
contents: write
deployments: write
pull-requests: write
actions: write
env:
RUSTC_WRAPPER: /usr/bin/sccache
CARGO_INCREMENTAL: 0
SCCACHE_DIR: /var/lib/github-actions/.cache

steps:
- name: 📥 Clone repository
uses: actions/checkout@v6

- name: 🚦 Check if CI can be skipped
id: skip-check
uses: cariad-tech/merge-queue-ci-skipper@main

- name: 🗑 Clear wasm-bindgen cache
if: steps.skip-check.outputs.skip-check != 'true'
run: rm -r ~/.cache/.wasm-pack || true

- name: 🟢 Install Node.js
if: steps.skip-check.outputs.skip-check != 'true'
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

- name: 🚧 Install build dependencies
if: steps.skip-check.outputs.skip-check != 'true'
run: |
cd frontend
npm run setup

- name: 🦀 Install Rust
if: steps.skip-check.outputs.skip-check != 'true'
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
override: true
cache: false
rustflags: ""
target: wasm32-unknown-unknown

- name: 🦀 Fetch Rust dependencies
if: steps.skip-check.outputs.skip-check != 'true'
run: cargo fetch --locked

- name: 🌐 Build Graphite web code
if: steps.skip-check.outputs.skip-check != 'true'
env:
NODE_ENV: production
run: mold -run cargo run build web

- name: 📤 Publish to Cloudflare Pages
if: steps.skip-check.outputs.skip-check != 'true'
continue-on-error: true
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
run: npx wrangler@3 pages deploy "frontend/dist" --project-name="graphite-dev" --commit-dirty=true

- name: 👕 Lint Graphite web formatting
if: steps.skip-check.outputs.skip-check != 'true'
env:
NODE_ENV: production
run: |
cd frontend
npm run check
uses: ./.github/workflows/build.yml
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
secrets: inherit
with:
web: true
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

# Run the Rust tests on the self-hosted native runner
test:
Expand All @@ -88,7 +22,6 @@ jobs:
RUSTC_WRAPPER: /usr/bin/sccache
CARGO_INCREMENTAL: 0
SCCACHE_DIR: /var/lib/github-actions/.cache

steps:
- name: 📥 Clone repository
uses: actions/checkout@v6
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/comment-clippy-warnings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
fi

- name: Delete previous comments
uses: actions/github-script@v6
uses: actions/github-script@v8
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
Expand All @@ -76,7 +76,7 @@ jobs:

- name: Comment PR
if: steps.clippy.outputs.CLIPPY_ISSUES_FOUND == 'true'
uses: actions/github-script@v6
uses: actions/github-script@v8
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/comment-profiling-changes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ jobs:
- name: Make old comments collapsed by default
# Only run if we have write permissions (not a fork)
if: github.event.pull_request.head.repo.full_name == github.repository
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
Expand All @@ -124,7 +124,7 @@ jobs:

- name: Analyze profiling changes
id: analyze
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
Expand Down Expand Up @@ -183,7 +183,7 @@ jobs:

- name: Comment PR
if: github.event.pull_request.head.repo.full_name == github.repository
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
Expand Down Expand Up @@ -333,7 +333,7 @@ jobs:

- name: Fail on significant regressions
if: steps.analyze.outputs.has-significant-changes == 'true'
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const regressionDetails = JSON.parse('${{ steps.analyze.outputs.regression-details }}');
Expand Down
Loading
Loading