diff --git a/manifest.json b/manifest.json deleted file mode 100644 index d7e871aa2..000000000 --- a/manifest.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "project_name": "ACRE", - "build": { - "addon_folder": "@acre2", - "key_name": "acre", - "prefix": "acre", - "pbo_name_prefix": "acre_", - "signature_blacklist": [], - "build_copy": [ - { - "src": "" - } - ] - }, - "publish": { - "release": { - "destinations": [ - { - "type": "steam", - "cred_file": "acre_release_steam.json", - "project_id": 751965892, - "release_dir": "P:\\idi\\acre\\release\\@acre2", - "steam_changelog": "Version {major}.{minor}.{patch}.{build} - See changelog on GitHub: https://github.com/IDI-Systems/acre2/releases" - }, - { - "type": "steam", - "cred_file": "acre_release_steam.json", - "project_id": 1740990569, - "release_dir": "P:\\idi\\acre\\release\\@acre2\\optionals\\@acre_sys_gm", - "steam_changelog": "Version {major}.{minor}.{patch}.{build} - See changelog on GitHub: https://github.com/IDI-Systems/acre2/releases" - }, - { - "type": "sftp", - "cred_file": "acre_release_sftp.json", - "hostname": "dev.idi-systems.com", - "local_path": "P:\\idi\\acre\\release\\acre2_{major}.{minor}.{patch}.{build}.zip", - "remote_path": "dev.idi-systems.com/release/acre2_{major}.{minor}.{patch}.{build}.zip" - }, - { - "type": "sftp", - "cred_file": "acre_release_sftp.json", - "hostname": "dev.idi-systems.com", - "local_path": "P:\\idi\\acre\\release\\acre2_{major}.{minor}.{patch}.{build}_symbols.zip", - "remote_path": "dev.idi-systems.com/symbols/acre2_{major}.{minor}.{patch}.{build}_symbols.zip" - }, - { - "type": "github", - "cred_file": "acre_release_github.json", - "account": "IDI-Systems/acre2", - "tag_name": "v{major}.{minor}.{patch}.{build}", - "branch": "release-build", - "name": "ACRE2 v{major}.{minor}.{patch}.{build}", - "body_file": "P:\\idi\\acre\\release\\@acre2\\README.md", - "local_path": "P:\\idi\\acre\\release\\acre2_{major}.{minor}.{patch}.{build}.zip", - "asset_name": "acre2_{major}.{minor}.{patch}.{build}.zip", - "prerelease": false - } - ] - }, - "steam-test": { - "destinations": [ - { - "type": "steam", - "cred_file": "test_acre_release_steam.json", - "project_id": 522695873, - "release_dir": "P:\\idi\\acre\\release\\@acre2", - "steam_changelog": "Version {major}.{minor}.{patch}.{build} - See changelog on GitHub: https://github.com/IDI-Systems/acre2/releases" - } - ] - }, - "development": { - "destinations": [ - { - "type": "steam", - "cred_file": "acre_release_steam.json", - "project_id": 774084145, - "release_dir": "P:\\idi\\acre\\release\\@acre2", - "steam_changelog": "Version {major}.{minor}.{patch}.{build} - See changelog on GitHub: https://github.com/IDI-Systems/acre2/commits/master" - }, - { - "type": "sftp", - "cred_file": "acre_release_sftp.json", - "hostname": "dev.idi-systems.com", - "local_path": "P:\\idi\\acre\\release\\acre2_{major}.{minor}.{patch}.{build}.zip", - "remote_path": "dev.idi-systems.com/dev/acre2_{major}.{minor}.{patch}.{build}.zip" - }, - { - "type": "sftp", - "cred_file": "acre_release_sftp.json", - "hostname": "dev.idi-systems.com", - "local_path": "P:\\idi\\acre\\release\\acre2_{major}.{minor}.{patch}.{build}_symbols.zip", - "remote_path": "dev.idi-systems.com/symbols/acre2_{major}.{minor}.{patch}.{build}_symbols.zip" - } - ] - } - } - -} diff --git a/tools/jenkins.py b/tools/jenkins.py deleted file mode 100644 index c2d8b3358..000000000 --- a/tools/jenkins.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python - -import sys -import subprocess -import argparse -import os -import json -import re - -def get_project_version(version_file): - majorText = "" - minorText = "" - patchText = "" - buildText = "" - try: - if os.path.isfile(version_file): - f = open(version_file, "r") - hpptext = f.read() - f.close() - - if hpptext: - majorText = re.search(r"#define MAJOR (.*\b)", hpptext).group(1) - minorText = re.search(r"#define MINOR (.*\b)", hpptext).group(1) - patchText = re.search(r"#define PATCHLVL (.*\b)", hpptext).group(1) - buildText = re.search(r"#define BUILD (.*\b)", hpptext).group(1) - - else: - print_error("A Critical file seems to be missing or inaccessible: {}".format(version_file)) - raise FileNotFoundError("File Not Found: {}".format(version_file)) - - except Exception as e: - raise Exception("Check the integrity of the file: {}".format(version_file)) - - return [majorText, minorText, patchText, buildText] - -def do_action(args, error_msg, error_handler=None, error_args=None, ignore_failure=False): - if(subprocess.call(args) != 0): - print("Error: {}".format(error_msg)) - if(error_handler != None): - error_handler(error_args) - # Return if ignoring failure, otherwise terminate the build - if(ignore_failure): - return False - else: - sys.exit(1) - return True - -def create_pull_request(args): - repository = args[0] - current = args[1] - target = args[2] - token = args[3] - - pull = { - 'title': 'Jenkins Automatic Merge Failure {} to {}!'.format(current, target), - 'head': current, - 'base': target, - 'body': "An automatic merge from the Jenkins build system has failed. This needs to be resolved as soon as possible." - } - - pull_string = json.dumps(pull, separators=(',',':')).replace('"','\\"') - - curl_string = ' '.join(["curl", '-H "Authorization: token {}"'.format(token), "--request POST", "--data \"{}\"".format(pull_string), "https://api.github.com/repos/{}/pulls".format(repository)]) - print(curl_string) - subprocess.call(curl_string) - - -# Arguments -parser = argparse.ArgumentParser(description="Jenkins CI System for Arma Projects Will execute a build and commit changes back into the current and target branches.") -parser.add_argument('repository', type=str, help='repository name in format owner/repo') -parser.add_argument('current_branch', type=str, help='the name of the current branch, can be supplied with a remote, ie: origin/release') -parser.add_argument('-t', '--target_branch', type=str, help="the targeted branch for merging changes during build, defaults to 'master'", default="master") -parser.add_argument('-r', '--release_target', type=str, help="the name of the release target in the manifest file.", default="release") -parser.add_argument('-m', '--make_arg', help="a list of args for make", action="append") -parser.add_argument('-p', '--publish', action="store_true", help="publish or not to publish") - - -args = parser.parse_args() - -repository = args.repository -current_branch = os.path.basename(args.current_branch) -target_branch = args.target_branch -release_target = args.release_target -make_args = ["python", "-u", "make.py"] -if(args.make_arg != None): - make_args.extend(args.make_arg) - -# Credentials (GitHub OAuth token) -# TODO Improve flow, this is copy from publish.py (bad!) -if(not "CBA_PUBLISH_CREDENTIALS_PATH" in os.environ): - raise Exception("CBA_PUBLISH_CREDENTIALS_PATH is not set in the environment") -credentials_path = os.environ["CBA_PUBLISH_CREDENTIALS_PATH"] - -manifest = json.load(open("..\\manifest.json")) - -for destination in manifest['publish']['release']['destinations']: - if(destination["type"] == "github"): - cred_file = json.load(open(os.path.join(credentials_path, destination["cred_file"]))) - if("github_oauth_token" in cred_file): - github_token = cred_file["github_oauth_token"] - else: - raise Exception("Credentials file did not specify a username and password for SFTP login") - -if github_token is None: - raise Exception("GitHub OAuth Token not found!") - -# Prepare -do_action(["git", "checkout", target_branch], "Failed to prepare checkout of target branch '{}'".format(target_branch)) - -# Build -do_action(["git", "checkout", current_branch], "Failed to checkout back into checked out branch '{}'".format(current_branch)) -do_action(make_args, "Make failed") - -# Publish -if args.publish: - # Get previous README.md if we are not building release (so GitHub front-page always has link to latest release) - if current_branch != "release-build": - print("Reverting README.md on non-release branch") - do_action(["git", "checkout", "../README.md"], "Failed to checkout previous README.md version.", ignore_failure=True) - - version = get_project_version("..\\addons\\\main\\script_version.hpp") - version_str = "{}.{}.{}.{}".format(version[0],version[1],version[2],version[3]) - commit_message = "v{} - Build {}".format(version_str,os.environ["BUILD_NUMBER"]) - - do_action(["git", "commit", "-am", commit_message], "Failed to commit changes back into branch '{}'".format(current_branch)) - do_action(["git", "push", "origin", current_branch], "Failed to push changes back into branch 'origin/{}'".format(current_branch)) - do_action(["git", "checkout", target_branch], "Failed to checkout target branch '{}'".format(target_branch)) - do_action(["git", "pull"], "Failed to update target branch from '{}'".format(target_branch)) - - status_ok = do_action(["git", "merge", current_branch], "Failed to merge '{}' into '{}', conflict exists.".format(current_branch, target_branch), create_pull_request, [repository, current_branch, target_branch, github_token], True) - if(status_ok): # Only diff and push if merge was successful - do_action(["git", "diff"], "Diff failed to resolve '{}' and '{}' cleanly, conflict exists.".format(current_branch, target_branch)) - do_action(["git", "push", "origin", target_branch], "Failed to push changes back into branch 'origin/{}'".format(target_branch), ignore_failure=True) - - # Pass version in case merge failed above (publish.py would try to read pre-merge file) - do_action(["python", "-u", "publish.py", "..\\manifest.json", "-r", release_target, "-v", version_str], "Publish failed.") - -sys.exit(0) diff --git a/tools/publish.py b/tools/publish.py deleted file mode 100644 index 1fc25f272..000000000 --- a/tools/publish.py +++ /dev/null @@ -1,322 +0,0 @@ -#!/usr/bin/env python3 - -# Author: PabstMirror - -# Uploads ace relases to workshop -# Will slice up compats to their own folders - -import sys - -if sys.version_info[0] == 2: - print("Python 3 is required.") - sys.exit(1) - -import os -import os.path -import shutil -import platform -import glob -import subprocess -import hashlib -import configparser -import json -import traceback -import time -import timeit -import re -import fnmatch -import argparse -import psutil # pip -import pysftp # pip -import tempfile - -from uritemplate import URITemplate, expand # pip - -if sys.platform == "win32": - import winreg - -def get_project_version(version_file): - majorText = "" - minorText = "" - patchText = "" - buildText = "" - try: - if os.path.isfile(version_file): - f = open(version_file, "r") - hpptext = f.read() - f.close() - - if hpptext: - majorText = re.search(r"#define MAJOR (.*\b)", hpptext).group(1) - minorText = re.search(r"#define MINOR (.*\b)", hpptext).group(1) - patchText = re.search(r"#define PATCHLVL (.*\b)", hpptext).group(1) - buildText = re.search(r"#define BUILD (.*\b)", hpptext).group(1) - - else: - print_error("A Critical file seems to be missing or inaccessible: {}".format(version_file)) - raise FileNotFoundError("File Not Found: {}".format(version_file)) - - except Exception as e: - raise Exception("Check the integrity of the file: {}".format(version_file)) - - return [majorText, minorText, patchText, buildText] - -def find_steam_exe(): - reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) - try: - k = winreg.OpenKey(reg, r"Software\Valve\Steam") - steam_path = winreg.QueryValueEx(k, "SteamExe")[0] - winreg.CloseKey(k) - return steam_path.replace("/", "\\") - except: - raise Exception("BadSteam","Steam path could not be located! Please make sure that Steam is properly installed.") - -def start_steam_with_user(username, password): - PROCNAME = "Steam.exe" - steam_path = find_steam_exe() - for proc in psutil.process_iter(): - if proc.name().lower() == PROCNAME.lower(): - print(proc.exe()) - steam_path = proc.exe() - print("Shutting down Steam...") - subprocess.call([steam_path, "-shutdown"]) - - steam_running = True - while steam_running: - steam_running = False - for proc in psutil.process_iter(): - if proc.name() == PROCNAME: - steam_running = True - - print("Steam shutdown.") - - print("Starting Steam...") - print(steam_path) - os.system("start \"\" \"{}\" -silent -noverifyfiles -login {} {}".format(steam_path, username, password)) - -def close_steam(): - PROCNAME = "Steam.exe" - steam_path = find_steam_exe() - for proc in psutil.process_iter(): - if proc.name().lower() == PROCNAME.lower(): - print(proc.exe()) - steam_path = proc.exe() - print("Shutting down Steam...") - subprocess.call([steam_path, "-shutdown"]) - - steam_running = True - while steam_running: - steam_running = False - for proc in psutil.process_iter(): - if proc.name() == PROCNAME: - steam_running = True - - print("Steam shutdown.") - -def find_bi_publisher(): - reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) - try: - k = winreg.OpenKey(reg, r"Software\bohemia interactive\arma 3 tools") - arma3tools_path = winreg.QueryValueEx(k, "path")[0] - winreg.CloseKey(k) - except: - raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") - - publisher_path = os.path.join(arma3tools_path, "Publisher", "PublisherCmd.exe") - - if os.path.isfile(publisher_path): - return publisher_path - else: - raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") - -def steam_publish_folder(folder, mod_id, version, steam_changelog): - change_notes = steam_changelog.format(major=version[0], minor=version[1], patch=version[2], build=version[3]) - steam_changelog_filepath = "steam_changelog.txt" - steam_changelog_file = open(steam_changelog_filepath, "w") - steam_changelog_file.write(change_notes) - steam_changelog_file.close() - cmd = [find_bi_publisher(), "update", "/id:{}".format(mod_id), "/changeNoteFile:{}".format(steam_changelog_filepath), "/path:{}".format(folder)] - - print ("running: {}".format(" ".join(cmd))) - - print("") - print("Publishing folder {} to workshop ID {}".format(folder,mod_id)) - print("") - - ret = 17 - while ret != 0: - if ret == 17 or ret == 19: - print("Waiting for Steam to initialize...") - time.sleep(30) - else: - print("publisher failed with code {}".format(ret)) - raise Exception("Publisher","Publisher had problems") - ret = subprocess.call(cmd) - print("Publisher Status: {}".format(ret)) - os.remove(steam_changelog_filepath) - - - - -def main(argv): - try: - parser = argparse.ArgumentParser(description="Arma Automatic Publishing Script") - parser.add_argument('manifest', type=argparse.FileType('r'), help='manifest json file') - parser.add_argument('-r', '--release_target', type=str, help="the name of the release target in the manifest file.", default="release") - parser.add_argument('-v', '--version', type=str, help="the version of the release archive.", default="") - - args = parser.parse_args() - - manifest_file = args.manifest - release_target = args.release_target - version = args.version.split(".") - - manifest = json.load(manifest_file) - if version == "": - version = get_project_version("..\\addons\\\main\\script_version.hpp") - - if(not "CBA_PUBLISH_CREDENTIALS_PATH" in os.environ): - raise Exception("CBA_PUBLISH_CREDENTIALS_PATH is not set in the environment") - - credentials_path = os.environ["CBA_PUBLISH_CREDENTIALS_PATH"] - - - for destination in manifest['publish'][release_target]['destinations']: - - if(destination["type"] == "steam"): - cred_file = json.load(open(os.path.join(credentials_path, destination["cred_file"]))) - if("username" in cred_file and "password" in cred_file): - steam_username = cred_file["username"] - steam_password = cred_file["password"] - - start_steam_with_user(steam_username, steam_password) - else: - raise Exception("Credentials file did not specify a username and password for Steam login") - if(not "project_id" in destination): - raise Exception("Steam Publish","No project ID defined in manifest for Steam publish") - project_id = destination["project_id"] - - if(not "release_dir" in destination): - raise Exception("Steam Publish","No release directory defined in manifest for Steam publish") - release_dir = destination["release_dir"] - - if(not "steam_changelog" in destination): - raise Exception("Steam Publish","No steam changelog defined in manifest for Steam publish") - steam_changelog = destination["steam_changelog"] - - steam_publish_folder(release_dir, project_id, version, steam_changelog) - close_steam() - if(destination["type"] == "sftp"): - cred_file = json.load(open(os.path.join(credentials_path, destination["cred_file"]))) - if("username" in cred_file and "password" in cred_file): - sftp_username = cred_file["username"] - sftp_password = cred_file["password"] - else: - raise Exception("Credentials file did not specify a username and password for SFTP login") - - if(not "hostname" in destination): - raise Exception("SFTP Publish","No hostname was defined for the SFTP site.") - hostname = destination["hostname"] - - if(not "local_path" in destination): - raise Exception("SFTP Publish","No local path was defined for the SFTP upload.") - local_path = destination["local_path"] - - if(not "remote_path" in destination): - raise Exception("SFTP Publish","No remote path was defined for the SFTP upload.") - remote_path = destination["remote_path"] - - - cnopts = pysftp.CnOpts() - cnopts.hostkeys = None - sftp = pysftp.Connection(host=hostname, username=sftp_username, password=sftp_password, cnopts=cnopts) - - local_path = local_path.format(major=version[0], minor=version[1], patch=version[2], build=version[3]) - remote_path = remote_path.format(major=version[0], minor=version[1], patch=version[2], build=version[3]) - - print("SFTP: Publishing {} to remote {}:{}".format(local_path, hostname, remote_path)) - - sftp.put(local_path, remotepath=remote_path) - print("SFTP: Upload Complete!") - if(destination["type"] == "github"): - cred_file = json.load(open(os.path.join(credentials_path, destination["cred_file"]))) - if("github_oauth_token" in cred_file): - github_token = cred_file["github_oauth_token"] - else: - raise Exception("Credentials file did not specify a username and password or OAuth token for GitHub login") - - account = destination["account"] - tag_name = destination["tag_name"] - branch = destination["branch"] - name = destination["name"] - body_file = destination["body_file"] - local_path = destination["local_path"] - prerelease = destination["prerelease"] - asset_name = destination["asset_name"] - - - tag_name = tag_name.format(major=version[0], minor=version[1], patch=version[2], build=version[3]) - name = name.format(major=version[0], minor=version[1], patch=version[2], build=version[3]) - asset_name = asset_name.format(major=version[0], minor=version[1], patch=version[2], build=version[3]) - local_path = local_path.format(major=version[0], minor=version[1], patch=version[2], build=version[3]) - - release_text_file = open(body_file, mode='r') - release_text = release_text_file.read() - release_text_file.close() - - - create_request = { - "tag_name": tag_name, - "target_commitish": branch, - "name": name, - "body": release_text, - "draft": False, - "prerelease": prerelease - } - - release_string = json.dumps(create_request, separators=(',',':')) - - temp_dir = tempfile.mkdtemp() - tmpname = os.path.join(temp_dir,"jsonpost") - temp_file = open(tmpname, 'w') - temp_file.write(release_string) - temp_file.close() - curl_string = ' '.join(["curl", '-s', '-H "Authorization: token {}"'.format(github_token), '-H "Content-Type: application/json"', "--request POST", "--data", '"@{}"'.format(tmpname).replace('\\','\\\\'), "https://api.github.com/repos/{}/releases".format(account)]) - - print("Creating Github Release...") - response = subprocess.check_output(curl_string) - response_json = json.loads(response.decode("ascii")) - shutil.rmtree(temp_dir) - if("id" in response_json): - print("Github Release Created @ {}".format(response_json["url"])) - release_id = response_json["id"] - upload_url = response_json["upload_url"] - - t = URITemplate(upload_url) - upload_url = t.expand(name=asset_name) - - - curl_string = ' '.join(["curl", '-s', '-H "Authorization: token {}"'.format(github_token), - '-H "Content-Type: application/zip"', - "--data-binary", - '"@{}"'.format(local_path), - upload_url]) - print("Attaching Asset...") - response = subprocess.check_output(curl_string) - response_json = json.loads(response.decode("ascii")) - if("browser_download_url" in response_json): - print("Asset Attached @ {}".format(response_json["browser_download_url"])) - else: - print(response_json) - raise Exception("Github Publish","Failed to Attach Asset") - - else: - print(response_json) - raise Exception("Github Publish","Failed to Create Release") - - except Exception as e: - print(e) - sys.exit(1) - -if __name__ == "__main__": - main(sys.argv)