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:
commit
10d2ea6fba
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()
|
Loading…
Reference in New Issue
Block a user