From 160955c69e01fbf3341a89eb1bb804e79ae6ee8a Mon Sep 17 00:00:00 2001 From: Alexander01998 Date: Thu, 17 Oct 2024 13:26:38 +0200 Subject: [PATCH] Add experimental Auto Snapshot Update workflow --- .github/workflows/auto_snapshot_update.yml | 119 +++++++++++++++++++++ scripts/update_version_constants.py | 85 +++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 .github/workflows/auto_snapshot_update.yml create mode 100644 scripts/update_version_constants.py diff --git a/.github/workflows/auto_snapshot_update.yml b/.github/workflows/auto_snapshot_update.yml new file mode 100644 index 0000000000..c03fa193c8 --- /dev/null +++ b/.github/workflows/auto_snapshot_update.yml @@ -0,0 +1,119 @@ +# Experimental workflow to automate updating to a new Minecraft snapshot. + +# Currently this is very similar to the semi-automatic scripts I already use, +# but moving them to GitHub Actions means I don't have to be around to start +# them. This should allow for further automation in the future. + +# TODO: +# - Add more thorough automated testing where it runs the game, creates a test +# world and takes screenshots, similar to what Fabric API does in their +# GitHub Actions workflow. +# - Set up a server to trigger this workflow when a new snapshot is out and +# Fabric has updated to it. This might end up running twice per snapshot, +# because there is no way to know ahead of time if the previous Fabric API +# build still works or if we have to wait for a new build made specifically +# for the new snapshot. +# - Add a step to automatically release the new snapshot build if all tests +# have passed. This will only ever run on small snapshots that don't break +# anything, but should save a ton of time at the end of each snapshot cycle +# when Mojang is spamming tiny pre-releases every day. + +# In case it isn't obvious, these todos are very ambitious and might not end +# up working as planned. + +name: Auto Snapshot Update + +on: + workflow_dispatch: + inputs: + mc_version: + description: 'Minecraft version to update to' + required: true + yarn_mappings: + description: 'Yarn mappings version' + required: true + fabric_loader: + description: 'Fabric Loader version' + required: true + fapi_version: + description: 'Fabric API version' + required: true + +permissions: + contents: write + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # so that we can see all branches + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Set up Java 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'microsoft' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + build-scan-publish: true + build-scan-terms-of-use-url: "https://gradle.com/help/legal-terms-of-use" + build-scan-terms-of-use-agree: "yes" + + - name: Create and checkout new snapshot branch + run: | + BRANCH_NAME="${{ github.event.inputs.mc_version }}" + CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + + if [ "$CURRENT_BRANCH" = "$BRANCH_NAME" ]; then + echo "Already on branch $BRANCH_NAME. Skipping branch creation." + elif git show-ref --quiet refs/heads/$BRANCH_NAME; then + echo "Branch $BRANCH_NAME already exists but is not currently checked out. Failing the workflow." + exit 1 + else + git checkout -b $BRANCH_NAME + echo "Created and checked out new branch: $BRANCH_NAME" + fi + shell: bash + + - name: Run migrateMappings task + run: | + ./gradlew migrateMappings --mappings ${{ github.event.inputs.yarn_mappings }} + shell: bash + + - name: Replace src/main/java with remapped files + run: | + rm -rf ./src/main/java + mv ./remappedSrc ./src/main/java + shell: bash + + - name: Update version constants + run: | + python scripts/update_version_constants.py "${{ github.event.inputs.mc_version }}" "${{ github.event.inputs.yarn_mappings }}" "${{ github.event.inputs.fabric_loader }}" "${{ github.event.inputs.fapi_version }}" + shell: bash + + # To fix any style issues that the migration scripts might cause + - name: Run spotlessApply task + run: ./gradlew spotlessApply + + - name: Commit and push changes + run: | + git config --global user.name 'Wurst-Bot' + git config --global user.email 'contact.wurstimperium@gmail.com' + git add . + git commit -m "[Wurst-Bot] Update to ${{ github.event.inputs.mc_version }}" + git push + shell: bash diff --git a/scripts/update_version_constants.py b/scripts/update_version_constants.py new file mode 100644 index 0000000000..543b48cedb --- /dev/null +++ b/scripts/update_version_constants.py @@ -0,0 +1,85 @@ +import argparse +import re + + +def update_gradle_properties(mc_version, yarn_mappings, fabric_loader, fapi_version): + print("Updating gradle.properties...") + + # Read gradle.properties + with open("gradle.properties", "r") as f: + lines = f.readlines() + + # Define replacements + replacements = { + "minecraft_version": lambda v: mc_version, + "yarn_mappings": lambda v: yarn_mappings, + "loader_version": lambda v: fabric_loader, + "fabric_version": lambda v: fapi_version, + "mod_version": lambda v: v[: v.index("MC") + 2] + mc_version, + } + + # Update lines + for i, line in enumerate(lines): + if line.startswith("#"): + continue + parts = line.split("=") + if len(parts) != 2: + continue + key = parts[0] + if key.strip() not in replacements: + continue + old_value = parts[1] + new_value = replacements[key.strip()](old_value) + print(f"{key}={old_value} -> {new_value}") + lines[i] = f"{key}={new_value}\n" + + # Save modified gradle.properties + with open("gradle.properties", "w") as f: + f.writelines(lines) + print("gradle.properties updated.") + + +def update_mc_version_constant(mc_version): + print(f"Updating MC_VERSION constant to {mc_version}...") + + # Read WurstClient.java + with open("src/main/java/net/wurstclient/WurstClient.java", "r") as f: + lines = f.readlines() + + # Update lines + pattern = re.compile(r"(public static final String MC_VERSION = \")([^\"]+)(\";)") + found = False + for i, line in enumerate(lines): + match = pattern.search(line) + if match: + lines[i] = pattern.sub(r"\g<1>" + mc_version + r"\g<3>", line) + found = True + break + + # Save modified WurstClient.java + with open("src/main/java/net/wurstclient/WurstClient.java", "w") as f: + f.writelines(lines) + + if found: + print("MC_VERSION constant updated.") + else: + print("Couldn't find MC_VERSION constant in WurstClient.java.") + exit(1) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("mc_version", help="Minecraft version") + parser.add_argument("yarn_mappings", help="Yarn mappings version") + parser.add_argument("fabric_loader", help="Fabric Loader version") + parser.add_argument("fapi_version", help="Fabric API version") + args = parser.parse_args() + + update_gradle_properties( + args.mc_version, + args.yarn_mappings, + args.fabric_loader, + args.fapi_version, + ) + + update_mc_version_constant(args.mc_version)