mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-09 17:00:30 +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