diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 16cb5017d6a154..4e72256cb8715e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -41,22 +41,31 @@ jobs: - name: Package client run: dotnet run --project Content.Packaging client --no-wipe-release - - name: Upload build artifact - id: artifact-upload-step - uses: actions/upload-artifact@v4 + - name: Update Build Info + run: Tools/gen_build_info.py + + - name: Shuffle files around + run: | + mkdir "release/${{ github.sha }}" + mv release/*.zip "release/${{ github.sha }}" + + - name: Upload files to centcomm + uses: appleboy/scp-action@master with: - name: build - path: release/*.zip - compression-level: 0 - retention-days: 0 + host: centcomm.spacestation14.io + username: wizards-build-push + key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }} + source: "release/${{ github.sha }}" + target: "/home/wizards-build-push/builds_dir/builds/" + strip_components: 1 - - name: Publish version - run: Tools/publish_github_artifact.py - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }} - ARTIFACT_ID: ${{ steps.artifact-upload-step.outputs.artifact-id }} - GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }} + - name: Update manifest JSON + uses: appleboy/ssh-action@master + with: + host: centcomm.spacestation14.io + username: wizards-build-push + key: ${{ secrets.CENTCOMM_WIZARDS_BUILDS_PUSH_KEY }} + script: /home/wizards-build-push/push.ps1 ${{ github.sha }} - name: Publish changelog (Discord) run: Tools/actions_changelogs_since_last_run.py @@ -68,8 +77,3 @@ jobs: run: Tools/actions_changelog_rss.py env: CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }} - - - uses: geekyeggo/delete-artifact@v5 - if: always() - with: - name: build diff --git a/SpaceStation14.sln b/SpaceStation14.sln index 0e00fe5b12ff9f..b91f78d55308d7 100644 --- a/SpaceStation14.sln +++ b/SpaceStation14.sln @@ -62,6 +62,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{806ED41A-411B-4B3B-BEB6-DEC6DCA4C205}" ProjectSection(SolutionItems) = preProject Tools\generate_hashes.ps1 = Tools\generate_hashes.ps1 + Tools\gen_build_info.py = Tools\gen_build_info.py EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Robust.Shared.Scripting", "RobustToolbox\Robust.Shared.Scripting\Robust.Shared.Scripting.csproj", "{41B450C0-A361-4CD7-8121-7072B8995CFC}" diff --git a/Tools/gen_build_info.py b/Tools/gen_build_info.py new file mode 100755 index 00000000000000..0207f568dd72f0 --- /dev/null +++ b/Tools/gen_build_info.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +# Generates build info and injects it into the server zip files. + +import codecs +import hashlib +import io +import json +import os +import subprocess +from zipfile import ZipFile, ZIP_DEFLATED + +FILE = "SS14.Client.zip" + +SERVER_FILES = [ + "SS14.Server_linux-x64.zip", + "SS14.Server_linux-arm64.zip", + "SS14.Server_win-x64.zip", + "SS14.Server_osx-x64.zip" +] + +VERSION = os.environ['GITHUB_SHA'] +FORK_ID = "wizards" +BUILD_URL = f"https://cdn.centcomm.spacestation14.com/builds/wizards/builds/{{FORK_VERSION}}/{FILE}" +MANIFEST_URL = f"https://cdn.centcomm.spacestation14.com/cdn/version/{{FORK_VERSION}}/manifest" +MANIFEST_DOWNLOAD_URL = f"https://cdn.centcomm.spacestation14.com/cdn/version/{{FORK_VERSION}}/download" + +def main() -> None: + client_file = os.path.join("release", FILE) + manifest = generate_build_json(client_file) + + for server in SERVER_FILES: + inject_manifest(os.path.join("release", server), manifest) + + +def inject_manifest(zip_path: str, manifest: str) -> None: + with ZipFile(zip_path, "a", compression=ZIP_DEFLATED) as z: + z.writestr("build.json", manifest) + + +def generate_build_json(file: str) -> str: + # Env variables set by Jenkins. + + hash = sha256_file(file) + engine_version = get_engine_version() + manifest_hash = generate_manifest_hash(file) + + return json.dumps({ + "download": BUILD_URL, + "hash": hash, + "version": VERSION, + "fork_id": FORK_ID, + "engine_version": engine_version, + "manifest_url": MANIFEST_URL, + "manifest_download_url": MANIFEST_DOWNLOAD_URL, + "manifest_hash": manifest_hash + }) + +def generate_manifest_hash(file: str) -> str: + zip = ZipFile(file) + infos = zip.infolist() + infos.sort(key=lambda i: i.filename) + + bytesIO = io.BytesIO() + writer = codecs.getwriter("UTF-8")(bytesIO) + writer.write("Robust Content Manifest 1\n") + + for info in infos: + if info.filename[-1] == "/": + continue + + bytes = zip.read(info) + hash = hashlib.blake2b(bytes, digest_size=32).hexdigest().upper() + writer.write(f"{hash} {info.filename}\n") + + manifestHash = hashlib.blake2b(bytesIO.getbuffer(), digest_size=32) + + return manifestHash.hexdigest().upper() + +def get_engine_version() -> str: + proc = subprocess.run(["git", "describe","--tags", "--abbrev=0"], stdout=subprocess.PIPE, cwd="RobustToolbox", check=True, encoding="UTF-8") + tag = proc.stdout.strip() + assert tag.startswith("v") + return tag[1:] # Cut off v prefix. + + +def sha256_file(path: str) -> str: + with open(path, "rb") as f: + h = hashlib.sha256() + for b in iter(lambda: f.read(4096), b""): + h.update(b) + + return h.hexdigest() + +if __name__ == '__main__': + main()