Loading .github/workflows/shippable_builds.yml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,10 @@ jobs: let skipThunderbird = process.env.skipThunderbird == "true"; let skipThunderbird = process.env.skipThunderbird == "true"; let skipK9Mail = process.env.skipK9Mail == "true"; let skipK9Mail = process.env.skipK9Mail == "true"; if (!matrix.every(item => !!item.appName && !!item.packageFormat)) { core.setFailed("MATRIX_INCLUDE is missing appName or packageFormat"); } let matrixFull = matrix.filter(item => { let matrixFull = matrix.filter(item => { return !((item.appName == "k9mail" && skipK9Mail) || return !((item.appName == "k9mail" && skipK9Mail) || (item.appName == "thunderbird" && skipThunderbird)); (item.appName == "thunderbird" && skipThunderbird)); Loading scripts/setup_release_automation +79 −108 Original line number Original line Diff line number Diff line #!/usr/bin/env python #!/usr/bin/env python # See docs/CI/Release_Automation.md for more details # See docs/CI/Release_Automation.md for more details # Run this from the .signing directory with all the keys and properties files in it. # python -m venv venv; source venv/bin/activate; pip install requests, pynacl # python -m venv venv; source venv/bin/activate; pip install requests, pynacl Loading Loading @@ -75,46 +76,38 @@ CHANNEL_ENVIRONMENTS = { SIGNING_ENVIRONMENTS = { SIGNING_ENVIRONMENTS = { "k9mail_release_default": [ "k9mail_release_default": { "k9.release.signing.properties", "props": "k9.release.signing.properties", "k9-release-signing.jks", "branch": "release", "release", }, ], "k9mail_beta_default": { "k9mail_beta_default": [ "props": "k9.release.signing.properties", "k9.release.signing.properties", "branch": "beta", "k9-release-signing.jks", }, "beta", "thunderbird_daily_foss": { ], "props": "tb.daily.signing.properties", "thunderbird_daily_foss": [ "branch": "main", "tb.daily.signing.properties", }, "tb-daily-signing.jks", "thunderbird_daily_full": { "daily", "props": "tb.daily.upload.properties", ], "branch": "main", "thunderbird_daily_full": [ }, "tb.daily.upload.properties", "thunderbird_beta_foss": { "tb-daily-upload-01.jks", "props": "tb.beta.signing.properties", "daily", "branch": "beta", ], }, "thunderbird_beta_foss": [ "thunderbird_beta_full": { "tb.beta.signing.properties", "props": "tb.beta.upload.properties", "tb-beta-signing.jks", "branch": "beta", "beta", }, ], "thunderbird_release_foss": { "thunderbird_beta_full": [ "props": "tb.release.signing.properties", "tb.beta.upload.properties", "branch": "release", "tb-beta-upload-01.jks", }, "beta", "thunderbird_release_full": { ], "props": "tb.release.upload.properties", "thunderbird_release_foss": [ "branch": "release", "tb.release.signing.properties", }, "tb-release-signing.jks", "release", ], "thunderbird_release_full": [ "tb.release.upload.properties", "tb-release-upload-01.jks", "release", ], } } Loading Loading @@ -306,7 +299,7 @@ def create_approver_environment(repo, environment_name, approvers): ) ) def create_signing_environment(repo, environment, branch, props_file, jks_file): def create_signing_environment(repo, environment, branch, props_file): # Read the key.properties file # Read the key.properties file key_props = read_key_properties(props_file) key_props = read_key_properties(props_file) Loading @@ -321,7 +314,7 @@ def create_signing_environment(repo, environment, branch, props_file, jks_file): return return # Base64 encode the JKS file to create SIGNING_KEY # Base64 encode the JKS file to create SIGNING_KEY SIGNING_KEY = encode_jks_file(jks_file) SIGNING_KEY = encode_jks_file(key_props.get("storeFile")) # Create the environment if it doesn't exist # Create the environment if it doesn't exist create_github_environment(repo, environment, branch=branch) create_github_environment(repo, environment, branch=branch) Loading Loading @@ -356,17 +349,6 @@ def main(): parser = argparse.ArgumentParser( parser = argparse.ArgumentParser( description="Set GitHub environment secrets for specific or all environments." description="Set GitHub environment secrets for specific or all environments." ) ) parser.add_argument( "--props", "-p", help="Path to the key.properties file (for single environment).", ) parser.add_argument( "--jks", "-j", help="Path to the .jks keystore file (for single environment)." ) parser.add_argument( "--environment", "-e", help="GitHub environment name (for single environment)." ) parser.add_argument( parser.add_argument( "--repo", "--repo", "-r", "-r", Loading @@ -374,14 +356,10 @@ def main(): help="GitHub repository in the format 'owner/repo'.", help="GitHub repository in the format 'owner/repo'.", ) ) parser.add_argument( parser.add_argument( "--all-environments", "--skip", "-s", action="append", help="Skip this named environment" "-a", action="store_true", help="Create all environments based on predefined paths and rules.", ) ) parser.add_argument("--branch", "-b", help="Branch to limit the environment to") parser.add_argument( parser.add_argument( "--skip", "-s", action="append", help="In all mode, skip this environment", default=[] "--only", "-o", action="append", help="Only include this named environment" ) ) args = parser.parse_args() args = parser.parse_args() Loading @@ -393,60 +371,53 @@ def main(): "GITHUB_TOKEN environment variable is not set. Please set it before running the script." "GITHUB_TOKEN environment variable is not set. Please set it before running the script." ) ) if args.all_environments: if args.skip and args.only: skipset = set(args.skip) print("Error: Cannot supply both skip and only") # All environments creation mode return if "publish_hold" in skipset: print("Skipping environment publish_hold") includeset = set( else: list(CHANNEL_ENVIRONMENTS.keys()) + list(SIGNING_ENVIRONMENTS.keys()) + list( "publish_hold", ) ) if args.skip: for skip in args.skip: includeset.remove(skip) if args.only: includeset = set(args.only) # Publish hold environment if "publish_hold" in includeset: create_github_environment( create_github_environment( args.repo, "publish_hold", approvers=PUBLISH_APPROVERS args.repo, "publish_hold", approvers=PUBLISH_APPROVERS ) ) # Channel environments # Channel environments for environment_name, data in CHANNEL_ENVIRONMENTS.items(): for environment_name, data in CHANNEL_ENVIRONMENTS.items(): if environment_name in skipset: if environment_name not in includeset: print(f"Skipping channel environment {environment_name}") continue continue create_github_environment( create_github_environment(args.repo, environment_name, branch=data["branch"]) args.repo, environment_name, branch=data["branch"] ) for name, value in data["variables"].items(): for name, value in data["variables"].items(): if isinstance(value, dict) or isinstance(value, list): if isinstance(value, dict) or isinstance(value, list): value = json.dumps(value) value = json.dumps(value) set_github_environment_variable( set_github_environment_variable(args.repo, name, value, environment_name) args.repo, name, value, environment_name ) # Signing environments # Signing environments for environment_name, paths in SIGNING_ENVIRONMENTS.items(): for environment_name, data in SIGNING_ENVIRONMENTS.items(): if environment_name in skipset: if environment_name not in includeset: print(f"Skipping signing environment {environment_name}") continue continue props_file, jks_file, branch = paths if not os.path.exists(data["props"]): print(f"Skipping {environment_name}: Missing key .properties file") if not os.path.exists(props_file) or not os.path.exists(jks_file): print( f"Skipping {environment_name}: Missing key.properties or .jks file." ) continue continue create_signing_environment( create_signing_environment( args.repo, environment_name, branch, props_file, jks_file args.repo, environment_name, data["branch"], data["props"] ) else: # Single environment creation mode if not all([args.props, args.jks, args.environment, args.branch]): print( "Error: You must provide --props, --jks, and --environment for single environment creation." ) return create_signing_environment( args.repo, args.environment, args.branch, args.props, args.jks ) ) Loading Loading
.github/workflows/shippable_builds.yml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,10 @@ jobs: let skipThunderbird = process.env.skipThunderbird == "true"; let skipThunderbird = process.env.skipThunderbird == "true"; let skipK9Mail = process.env.skipK9Mail == "true"; let skipK9Mail = process.env.skipK9Mail == "true"; if (!matrix.every(item => !!item.appName && !!item.packageFormat)) { core.setFailed("MATRIX_INCLUDE is missing appName or packageFormat"); } let matrixFull = matrix.filter(item => { let matrixFull = matrix.filter(item => { return !((item.appName == "k9mail" && skipK9Mail) || return !((item.appName == "k9mail" && skipK9Mail) || (item.appName == "thunderbird" && skipThunderbird)); (item.appName == "thunderbird" && skipThunderbird)); Loading
scripts/setup_release_automation +79 −108 Original line number Original line Diff line number Diff line #!/usr/bin/env python #!/usr/bin/env python # See docs/CI/Release_Automation.md for more details # See docs/CI/Release_Automation.md for more details # Run this from the .signing directory with all the keys and properties files in it. # python -m venv venv; source venv/bin/activate; pip install requests, pynacl # python -m venv venv; source venv/bin/activate; pip install requests, pynacl Loading Loading @@ -75,46 +76,38 @@ CHANNEL_ENVIRONMENTS = { SIGNING_ENVIRONMENTS = { SIGNING_ENVIRONMENTS = { "k9mail_release_default": [ "k9mail_release_default": { "k9.release.signing.properties", "props": "k9.release.signing.properties", "k9-release-signing.jks", "branch": "release", "release", }, ], "k9mail_beta_default": { "k9mail_beta_default": [ "props": "k9.release.signing.properties", "k9.release.signing.properties", "branch": "beta", "k9-release-signing.jks", }, "beta", "thunderbird_daily_foss": { ], "props": "tb.daily.signing.properties", "thunderbird_daily_foss": [ "branch": "main", "tb.daily.signing.properties", }, "tb-daily-signing.jks", "thunderbird_daily_full": { "daily", "props": "tb.daily.upload.properties", ], "branch": "main", "thunderbird_daily_full": [ }, "tb.daily.upload.properties", "thunderbird_beta_foss": { "tb-daily-upload-01.jks", "props": "tb.beta.signing.properties", "daily", "branch": "beta", ], }, "thunderbird_beta_foss": [ "thunderbird_beta_full": { "tb.beta.signing.properties", "props": "tb.beta.upload.properties", "tb-beta-signing.jks", "branch": "beta", "beta", }, ], "thunderbird_release_foss": { "thunderbird_beta_full": [ "props": "tb.release.signing.properties", "tb.beta.upload.properties", "branch": "release", "tb-beta-upload-01.jks", }, "beta", "thunderbird_release_full": { ], "props": "tb.release.upload.properties", "thunderbird_release_foss": [ "branch": "release", "tb.release.signing.properties", }, "tb-release-signing.jks", "release", ], "thunderbird_release_full": [ "tb.release.upload.properties", "tb-release-upload-01.jks", "release", ], } } Loading Loading @@ -306,7 +299,7 @@ def create_approver_environment(repo, environment_name, approvers): ) ) def create_signing_environment(repo, environment, branch, props_file, jks_file): def create_signing_environment(repo, environment, branch, props_file): # Read the key.properties file # Read the key.properties file key_props = read_key_properties(props_file) key_props = read_key_properties(props_file) Loading @@ -321,7 +314,7 @@ def create_signing_environment(repo, environment, branch, props_file, jks_file): return return # Base64 encode the JKS file to create SIGNING_KEY # Base64 encode the JKS file to create SIGNING_KEY SIGNING_KEY = encode_jks_file(jks_file) SIGNING_KEY = encode_jks_file(key_props.get("storeFile")) # Create the environment if it doesn't exist # Create the environment if it doesn't exist create_github_environment(repo, environment, branch=branch) create_github_environment(repo, environment, branch=branch) Loading Loading @@ -356,17 +349,6 @@ def main(): parser = argparse.ArgumentParser( parser = argparse.ArgumentParser( description="Set GitHub environment secrets for specific or all environments." description="Set GitHub environment secrets for specific or all environments." ) ) parser.add_argument( "--props", "-p", help="Path to the key.properties file (for single environment).", ) parser.add_argument( "--jks", "-j", help="Path to the .jks keystore file (for single environment)." ) parser.add_argument( "--environment", "-e", help="GitHub environment name (for single environment)." ) parser.add_argument( parser.add_argument( "--repo", "--repo", "-r", "-r", Loading @@ -374,14 +356,10 @@ def main(): help="GitHub repository in the format 'owner/repo'.", help="GitHub repository in the format 'owner/repo'.", ) ) parser.add_argument( parser.add_argument( "--all-environments", "--skip", "-s", action="append", help="Skip this named environment" "-a", action="store_true", help="Create all environments based on predefined paths and rules.", ) ) parser.add_argument("--branch", "-b", help="Branch to limit the environment to") parser.add_argument( parser.add_argument( "--skip", "-s", action="append", help="In all mode, skip this environment", default=[] "--only", "-o", action="append", help="Only include this named environment" ) ) args = parser.parse_args() args = parser.parse_args() Loading @@ -393,60 +371,53 @@ def main(): "GITHUB_TOKEN environment variable is not set. Please set it before running the script." "GITHUB_TOKEN environment variable is not set. Please set it before running the script." ) ) if args.all_environments: if args.skip and args.only: skipset = set(args.skip) print("Error: Cannot supply both skip and only") # All environments creation mode return if "publish_hold" in skipset: print("Skipping environment publish_hold") includeset = set( else: list(CHANNEL_ENVIRONMENTS.keys()) + list(SIGNING_ENVIRONMENTS.keys()) + list( "publish_hold", ) ) if args.skip: for skip in args.skip: includeset.remove(skip) if args.only: includeset = set(args.only) # Publish hold environment if "publish_hold" in includeset: create_github_environment( create_github_environment( args.repo, "publish_hold", approvers=PUBLISH_APPROVERS args.repo, "publish_hold", approvers=PUBLISH_APPROVERS ) ) # Channel environments # Channel environments for environment_name, data in CHANNEL_ENVIRONMENTS.items(): for environment_name, data in CHANNEL_ENVIRONMENTS.items(): if environment_name in skipset: if environment_name not in includeset: print(f"Skipping channel environment {environment_name}") continue continue create_github_environment( create_github_environment(args.repo, environment_name, branch=data["branch"]) args.repo, environment_name, branch=data["branch"] ) for name, value in data["variables"].items(): for name, value in data["variables"].items(): if isinstance(value, dict) or isinstance(value, list): if isinstance(value, dict) or isinstance(value, list): value = json.dumps(value) value = json.dumps(value) set_github_environment_variable( set_github_environment_variable(args.repo, name, value, environment_name) args.repo, name, value, environment_name ) # Signing environments # Signing environments for environment_name, paths in SIGNING_ENVIRONMENTS.items(): for environment_name, data in SIGNING_ENVIRONMENTS.items(): if environment_name in skipset: if environment_name not in includeset: print(f"Skipping signing environment {environment_name}") continue continue props_file, jks_file, branch = paths if not os.path.exists(data["props"]): print(f"Skipping {environment_name}: Missing key .properties file") if not os.path.exists(props_file) or not os.path.exists(jks_file): print( f"Skipping {environment_name}: Missing key.properties or .jks file." ) continue continue create_signing_environment( create_signing_environment( args.repo, environment_name, branch, props_file, jks_file args.repo, environment_name, data["branch"], data["props"] ) else: # Single environment creation mode if not all([args.props, args.jks, args.environment, args.branch]): print( "Error: You must provide --props, --jks, and --environment for single environment creation." ) return create_signing_environment( args.repo, args.environment, args.branch, args.props, args.jks ) ) Loading