mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-29 12:57:46 +00:00 
			
		
		
		
	Add some utilities to automate CC:T releases
Not sure how useful this'll be, but we'll see.
This commit is contained in:
		
							
								
								
									
										12
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| root = true | ||||
|  | ||||
| [*] | ||||
| indent_style = space | ||||
| indent_size = 4 | ||||
| end_of_line = lf | ||||
| charset = utf-8 | ||||
| trim_trailing_whitespace = true | ||||
| insert_final_newline = true | ||||
|  | ||||
| [*.md] | ||||
| trim_trailing_whitespace = false | ||||
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| /mc-* | ||||
| /.idea | ||||
| /.gradle | ||||
| /logs | ||||
| /gradle* | ||||
| /*.gradle | ||||
							
								
								
									
										30
									
								
								LICENCE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								LICENCE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| Copyright (c) 2021 SquidDev | ||||
|  | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
|  | ||||
|     * Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|  | ||||
|     * Redistributions in binary form must reproduce the above | ||||
|       copyright notice, this list of conditions and the following | ||||
|       disclaimer in the documentation and/or other materials provided | ||||
|       with the distribution. | ||||
|  | ||||
|     * Neither the name of squiddev nor the names of other contributors | ||||
|       may be used to endorse or promote products derived from this | ||||
|       software without specific prior written permission. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										24
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| # CC: Tweaked build scripts | ||||
|  | ||||
| You probably don't want this branch - check out [the main repository][cct] | ||||
| instead! | ||||
|  | ||||
| As CC: Tweaked targets multiple Minecraft versions, releasing updates can be a | ||||
| bit of a pain. This branch provides a script to set up a development environment | ||||
| and semi-automate releases. | ||||
|  | ||||
| ## Usage | ||||
| ```bash | ||||
| > git clone git@github.com:SquidDev-CC/CC-Tweaked.git | ||||
| > cd CC-Tweaked | ||||
| > git checkout build-tools | ||||
|  | ||||
| # Set up the various worktrees. | ||||
| > ./gfi setup | ||||
| # Merge branches and publish a release. You probably don't want this unless you | ||||
| # have all my secret keys. | ||||
| > ./gfi release | ||||
| ``` | ||||
|  | ||||
|  | ||||
| [cct]: https://github.com/SquidDev-CC/CC-Tweaked/ | ||||
							
								
								
									
										160
									
								
								gfi
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										160
									
								
								gfi
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| #!/usr/bin/env python3 | ||||
|  | ||||
| """ | ||||
| The main build script for CC: Tweaked. | ||||
|  | ||||
| This sets up work trees for each branch, ensures they are up-to-date with the | ||||
| remotes and then merges the primary branch (mc-1.15.x) into each other branch. | ||||
|  | ||||
| We then build each branch, push changes, and upload all versions. | ||||
| """ | ||||
|  | ||||
| import argparse | ||||
| import subprocess | ||||
| import shutil | ||||
| import sys | ||||
| import os.path | ||||
| from dataclasses import dataclass | ||||
| from typing import List, Tuple, Optional | ||||
|  | ||||
|  | ||||
| @dataclass | ||||
| class Branch: | ||||
|     name: str | ||||
|     parent: Optional[str] = None | ||||
|  | ||||
|  | ||||
| BRANCHES: List[Branch] = [ | ||||
|     Branch('mc-1.15.x'), | ||||
|     Branch('mc-1.16.x', parent='mc-1.15.x'), | ||||
| ] | ||||
|  | ||||
|  | ||||
| def log(msg: str, *args) -> None: | ||||
|     """Print a format string to the console""" | ||||
|     print("\033[32m" + msg % tuple(args) + "\033[0m") | ||||
|  | ||||
|  | ||||
| def git_in(branch: Branch, *cmd: str, **kwargs) -> subprocess.CompletedProcess: | ||||
|     """Run a git command on a specific branch.""" | ||||
|     return subprocess.run(["git", "-C", branch.name, *cmd], **kwargs) | ||||
|  | ||||
|  | ||||
| def run_in(branch: Branch, *cmd: str, **kwargs) -> subprocess.CompletedProcess: | ||||
|     """Run a command within the context of a specific branch.""" | ||||
|     return subprocess.run(cmd, cwd=branch.name, **kwargs) | ||||
|  | ||||
|  | ||||
| def setup() -> None: | ||||
|     """ | ||||
|     Setup the repository suitable for working with multiple versions. Namely: | ||||
|     - Register all remotes. | ||||
|     - Copy gradle files from the default branch. | ||||
|     """ | ||||
|     # Update git remote. | ||||
|     log("Updating from remotes") | ||||
|     subprocess.check_call(["git", "fetch", "origin"]) | ||||
|  | ||||
|     # Setup git repository. | ||||
|     for branch in BRANCHES: | ||||
|         if not os.path.isdir(branch.name): | ||||
|             log(f"Creating worktree for {branch.name}") | ||||
|             subprocess.check_call(["git", "worktree", "add", branch.name, branch.name]) | ||||
|  | ||||
|     # Setup gradle. | ||||
|     log("Setting up gradle project") | ||||
|     for file in ["gradle", "gradlew", "gradlew.bat"]: | ||||
|         src = f"{BRANCHES[0].name}/{file}" | ||||
|         if os.path.isdir(src): | ||||
|             shutil.copytree(src, file, dirs_exist_ok=True) | ||||
|         else: | ||||
|             shutil.copy2(src, file) | ||||
|  | ||||
|     with open("settings.gradle", "w") as h: | ||||
|         h.write("rootProject.name = 'cc-tweaked'\n") | ||||
|         for branch in BRANCHES: | ||||
|             h.write(f"include '{branch.name}'\n") | ||||
|  | ||||
|     with open("build.gradle", "w") as h: | ||||
|         pass | ||||
|  | ||||
|  | ||||
| def build() -> None: | ||||
|     """ | ||||
|     Ensure the git repository is in a clean state. | ||||
|     """ | ||||
|     setup() | ||||
|  | ||||
|     # Ensure every tree is clean. | ||||
|     ok = True | ||||
|     for branch in BRANCHES: | ||||
|         status = git_in(branch, "status", "--porcelain", check=True, stdout=subprocess.PIPE).stdout | ||||
|         if len(status.strip()) > 0: | ||||
|             log(f"{branch.name} has changes. Build will not continue.") | ||||
|             ok = False | ||||
|     if not ok: | ||||
|         sys.exit(1) | ||||
|  | ||||
|     # Ensure every tree is up-to-date. | ||||
|     primary = BRANCHES[0] | ||||
|     for branch in BRANCHES: | ||||
|         if git_in(branch, "merge-base", "--is-ancestor", f"origin/{branch.name}", branch.name).returncode != 0: | ||||
|             log(f"{branch.name} is not up-to-date with remote.") | ||||
|             # TODO: We should possibly attempt to merge/rebase here instead of aborting. | ||||
|             sys.exit(1) | ||||
|  | ||||
|         if ( | ||||
|             branch.parent is not None and | ||||
|             git_in(branch, "merge-base", "--is-ancestor", branch.parent, branch.name).returncode != 0 | ||||
|         ): | ||||
|             log(f"{branch.name} is not up-to-date with {branch.parent}.") | ||||
|             ret = git_in(branch, "merge", "--no-edit", branch.parent).returncode | ||||
|             if ret != 0: | ||||
|                 log(f"Merge {branch.parent} -> {branch.name} failed. Aborting.") | ||||
|                 sys.exit(ret) | ||||
|  | ||||
|     log("Git state is up-to-date. Preparing to build - you might want to make a cup of tea.") | ||||
|  | ||||
|     for branch in BRANCHES: | ||||
|         log(f"Building {branch.name}") | ||||
|         ret = run_in(branch, "./gradlew", "build", "--no-daemon").returncode | ||||
|         if ret != 0: | ||||
|             log(f"Build failed") | ||||
|             sys.exit(ret) | ||||
|  | ||||
|  | ||||
| def release() -> None: | ||||
|     """Publish releases for each version.""" | ||||
|     build() | ||||
|  | ||||
|     check = input("Are you sure you want to release? Make sure you've performed some manual checks first! [y/N]").lower() | ||||
|     if check != "y": | ||||
|         sys.exit(1) | ||||
|  | ||||
|     subprocess.check_call(["git", "push", "--all", "origin"]) | ||||
|     for branch in BRANCHES: | ||||
|         log(f"Uploading {branch.name}") | ||||
|         ret = run_in(branch, "./gradlew", "uploadAll", "--no-daemon").returncode | ||||
|         if ret != 0: | ||||
|             log(f"Upload failed. Good luck in recovering from this!") | ||||
|             sys.exit(ret) | ||||
|  | ||||
|     log(f"Finished. Well done, you may now enjoy your tea!") | ||||
|  | ||||
|  | ||||
| def main() -> None: | ||||
|     # Validate arguments. | ||||
|     parser = argparse.ArgumentParser(description="Build scripts for CC: Tweaked") | ||||
|     subparsers = parser.add_subparsers( | ||||
|         description="The subcommand to run. Subcommands implicitly run their dependencies.", | ||||
|         dest="subcommand", | ||||
|         required=True, | ||||
|     ) | ||||
|     subparsers.add_parser("setup", help="Setup the git repository and build environment.").set_defaults(func=setup) | ||||
|     subparsers.add_parser("build", help="Merge and build all branches.").set_defaults(func=build) | ||||
|     subparsers.add_parser("release", help="Publish a release.").set_defaults(func=release) | ||||
|  | ||||
|     parser.parse_args().func() | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates