1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-08 08:20:29 +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:
Jonathan Coates 2021-01-09 18:25:24 +00:00
commit 10d2ea6fba
5 changed files with 232 additions and 0 deletions

12
.editorconfig Normal file
View 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
View File

@ -0,0 +1,6 @@
/mc-*
/.idea
/.gradle
/logs
/gradle*
/*.gradle

30
LICENCE Normal file
View 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
View 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
View 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()