Skip to content

Update Upstream (Canvas) #122

Update Upstream (Canvas)

Update Upstream (Canvas) #122

Workflow file for this run

name: Update Upstream (Canvas)
on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:
inputs:
canvas-branch:
type: string
required: false
description: "Canvas branch to update from (overrides gradle.properties canvasBranch)"
env:
PLUGIN_ID: "io.canvasmc.weaver.patcher"
FILE_PATH: "build.gradle.kts"
permissions:
contents: write
issues: write
jobs:
update-upstream:
name: Update Upstream
runs-on: self-hosted
environment: update-upstream
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
- name: Checkout repo
uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Authenticate
run: |
git config --global user.name "surf-canvas-upstream-bot[bot]"
git config --global user.email "surf-canvas-upstream-bot[bot]@users.noreply.github.com"
- name: Resolve Canvas branch
run: |
if [ -n "${{ inputs.canvas-branch }}" ]; then
CANVAS_BRANCH="${{ inputs.canvas-branch }}"
else
CANVAS_BRANCH=$(grep '^canvasBranch' gradle.properties | awk -F '=' '{print $2}' | tr -d '[:space:]\r')
fi
if [ -z "$CANVAS_BRANCH" ]; then
echo "No canvasBranch found in gradle.properties and no input provided." >&2
exit 1
fi
echo "CANVAS_BRANCH=$CANVAS_BRANCH" >> $GITHUB_ENV
echo "Using Canvas branch: $CANVAS_BRANCH"
- name: Check if update is needed
run: |
OPEN_ISSUE=$(curl -s \
-H "Authorization: Bearer ${{ steps.app-token.outputs.token }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues?state=open&labels=upstream-update&per_page=1" \
| jq -r '.[0].number // empty')
CURRENT_COMMIT=$(grep '^canvasCommit' gradle.properties | awk -F '=' '{print $2}' | tr -d '[:space:]\r')
LATEST_COMMIT=$(curl -s \
-H "Authorization: Bearer ${{ steps.app-token.outputs.token }}" \
"https://api.github.com/repos/CraftCanvasMC/Canvas/commits/$CANVAS_BRANCH" \
| jq -r '.sha' | tr -d '[:space:]\r')
echo "OPEN_ISSUE=$OPEN_ISSUE" >> $GITHUB_ENV
echo "CURRENT_COMMIT=$CURRENT_COMMIT" >> $GITHUB_ENV
echo "LATEST_COMMIT=$LATEST_COMMIT" >> $GITHUB_ENV
echo "Current commit: $CURRENT_COMMIT"
echo "Latest commit: $LATEST_COMMIT"
if [ -n "$OPEN_ISSUE" ] || [ "$CURRENT_COMMIT" = "$LATEST_COMMIT" ]; then
echo "SKIP=true" >> $GITHUB_ENV
if [ -n "$OPEN_ISSUE" ]; then
echo "Skipping: open upstream-update issue #$OPEN_ISSUE already exists."
else
echo "Skipping: already up-to-date."
fi
else
echo "SKIP=false" >> $GITHUB_ENV
fi
- name: Update Weaver patcher version
if: env.SKIP == 'false'
run: |
UPSTREAM_GRADLE=$(curl -s \
"https://raw.githubusercontent.com/CraftCanvasMC/Canvas/$CANVAS_BRANCH/build.gradle.kts")
UPSTREAM_WEAVER=$(echo "$UPSTREAM_GRADLE" | grep "$PLUGIN_ID" | sed -E 's/.*version "([^"]+)".*/\1/' | tr -d '[:space:]\r' | head -n1)
LOCAL_WEAVER=$(grep "$PLUGIN_ID" "$FILE_PATH" | sed -E 's/.*version "([^"]+)".*/\1/' | tr -d '[:space:]\r' | head -n1)
echo "Local Weaver version: $LOCAL_WEAVER"
echo "Upstream Weaver version: $UPSTREAM_WEAVER"
if [ -n "$UPSTREAM_WEAVER" ] && [ "$LOCAL_WEAVER" != "$UPSTREAM_WEAVER" ]; then
echo "Updating weaver-patcher from $LOCAL_WEAVER to $UPSTREAM_WEAVER"
sed -i -E "s/(id\\(\"$PLUGIN_ID\"\\)[^\"]*version \")[^\"]+(\")/\1$UPSTREAM_WEAVER\2/" "$FILE_PATH"
fi
- name: Update canvas refs in gradle.properties
if: env.SKIP == 'false'
run: |
UPSTREAM_PROPS=$(curl -s \
"https://raw.githubusercontent.com/CraftCanvasMC/Canvas/$CANVAS_BRANCH/gradle.properties")
UPSTREAM_MC=$(echo "$UPSTREAM_PROPS" | grep '^mcVersion' | awk -F '=' '{print $2}' | tr -d ' \r')
UPSTREAM_API=$(echo "$UPSTREAM_PROPS" | grep '^apiVersion' | awk -F '=' '{print $2}' | tr -d ' \r')
echo "Updating canvasCommit to $LATEST_COMMIT"
sed -i -E "s/^(canvasCommit=).*$/\1$LATEST_COMMIT/" gradle.properties
CURRENT_MC=$(grep '^mcVersion' gradle.properties | awk -F '=' '{print $2}' | tr -d ' \r')
CURRENT_API=$(grep '^apiVersion' gradle.properties | awk -F '=' '{print $2}' | tr -d ' \r')
if [ "$CURRENT_MC" != "$UPSTREAM_MC" ]; then
echo "Updating mcVersion from $CURRENT_MC to $UPSTREAM_MC"
sed -i -E "s/^(mcVersion=).*$/\1$UPSTREAM_MC/" gradle.properties
echo "Updating apiVersion from $CURRENT_API to $UPSTREAM_API"
sed -i -E "s/^(apiVersion=).*$/\1$UPSTREAM_API/" gradle.properties
else
echo "mcVersion unchanged ($CURRENT_MC)"
fi
- name: Set up GraalVM JDK 25
if: env.SKIP == 'false'
uses: actions/setup-java@v5
with:
java-version: "25"
distribution: "graalvm"
- name: Set up Gradle
if: env.SKIP == 'false'
uses: gradle/actions/setup-gradle@v6
with:
allow-snapshot-wrappers: true
- name: Make gradlew executable
if: env.SKIP == 'false'
run: chmod +x ./gradlew
- name: Apply patches (with fuzzy fallback)
if: env.SKIP == 'false'
run: |
./gradlew applyAllPatches || ./gradlew applyCanvasSingleFilePatchesFuzzy || echo "APPLY_FAILED=true" >> $GITHUB_ENV
./gradlew rebuildCanvasSingleFilePatches
./gradlew applyAllPatches || echo "APPLY_FAILED=true" >> $GITHUB_ENV
./gradlew rebuildPaperApiPatches
./gradlew rebuildAllServerPatches
./gradlew compileJava || echo "BUILD_FAILED=true" >> $GITHUB_ENV
continue-on-error: true
- name: Rebuild patches
if: env.SKIP == 'false' && env.APPLY_FAILED != 'true'
run: |
./gradlew rebuildPatches --no-scan --stacktrace || echo "REBUILD_FAILED=true" >> $GITHUB_ENV
continue-on-error: true
- name: Compile check
if: env.SKIP == 'false' && env.APPLY_FAILED != 'true'
run: |
./gradlew compileJava --no-scan --stacktrace || echo "BUILD_FAILED=true" >> $GITHUB_ENV
continue-on-error: true
- name: Open issue on apply failure
if: env.APPLY_FAILED == 'true' && env.SKIP == 'false'
run: |
curl -s -X POST \
-H "Authorization: Bearer ${{ steps.app-token.outputs.token }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues" \
-d "{
\"title\": \"[BOT] Failed to apply patches after Canvas update\",
\"body\": \"Failed to apply surf-canvas patches after updating Canvas to [\`$LATEST_COMMIT\`](https://github.com/CraftCanvasMC/Canvas/commit/$LATEST_COMMIT) on branch \`$CANVAS_BRANCH\`.\",
\"labels\": [\"upstream-update\"]
}"
- name: Open issue on build failure
if: env.BUILD_FAILED == 'true' && env.APPLY_FAILED != 'true' && env.SKIP == 'false'
run: |
curl -s -X POST \
-H "Authorization: Bearer ${{ steps.app-token.outputs.token }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues" \
-d "{
\"title\": \"[BOT] Build failed after Canvas update\",
\"body\": \"Patches applied successfully but compilation failed after updating Canvas to [\`$LATEST_COMMIT\`](https://github.com/CraftCanvasMC/Canvas/commit/$LATEST_COMMIT) on branch \`$CANVAS_BRANCH\`.\",
\"labels\": [\"upstream-update\"]
}"
- name: Generate commit message
if: env.BUILD_FAILED != 'true' && env.APPLY_FAILED != 'true' && env.SKIP == 'false'
run: |
UPDATES=$(curl -s \
-H "Authorization: Bearer ${{ steps.app-token.outputs.token }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/CraftCanvasMC/Canvas/compare/$CURRENT_COMMIT...$LATEST_COMMIT" \
| jq -r '.commits[] | "CraftCanvasMC/Canvas@\(.sha[:7]) - \(.commit.message | split("\n")[0])"')
DISCLAIMER="Upstream has released updates that appear to apply and compile correctly."$'\n'"The changes in this commit are automated, meaning there might be things missing."
printf "Updated upstream (Canvas)\n\n%s\n\nCanvas Changes:\n%s\n" "$DISCLAIMER" "$UPDATES" > commit_message.txt
- name: Commit and push
if: env.BUILD_FAILED != 'true' && env.APPLY_FAILED != 'true' && env.SKIP == 'false'
env:
APP_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
git add .
git restore --staged commit_message.txt
git diff --cached --quiet && {
echo "No changes to commit."
exit 0
}
git commit -F commit_message.txt
git remote set-url origin "https://x-access-token:${APP_TOKEN}@github.com/${{ github.repository }}.git"
git push origin HEAD:master