From ca87f518e80ddf6925c90f98e43a64b190fa9724 Mon Sep 17 00:00:00 2001 From: Lucian Behind The Scenes Date: Sun, 2 Aug 2026 21:47:39 +0300 Subject: [PATCH 1/2] fix: provision every documented autorelease environment --- docs/repository-settings.md | 4 ++- scripts/configure-github-autorelease | 48 ++++++++++++++++++---------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/docs/repository-settings.md b/docs/repository-settings.md index db8e3d4..4a04b37 100644 --- a/docs/repository-settings.md +++ b/docs/repository-settings.md @@ -74,5 +74,7 @@ The normal verification commands are: ./scripts/configure-github-autorelease \ --repo bigpixelrocket/php-bin \ --owner loadinglucian \ - --required-check "Script checks" + --required-check "Script checks" \ + --environment php-autorelease-publish \ + --environment php-autorelease-canary ``` diff --git a/scripts/configure-github-autorelease b/scripts/configure-github-autorelease index 5699ab3..64fee64 100755 --- a/scripts/configure-github-autorelease +++ b/scripts/configure-github-autorelease @@ -45,6 +45,16 @@ parser = argparse.ArgumentParser() parser.add_argument("--repo", required=True) parser.add_argument("--owner", required=True) parser.add_argument("--required-check", required=True) +# Environments are GitHub configuration rather than repository files, so a +# source-only rename cannot move them. Naming each one at the call site keeps +# the provisioned set and the reviewed docs/admin-state snapshot in step. +parser.add_argument( + "--environment", + action="append", + required=True, + metavar="NAME", + help="Protected environment to create. Repeat once per environment.", +) args = parser.parse_args() try: @@ -116,24 +126,27 @@ try: gh("variable", "set", "AUTORELEASE_OWNER", "--repo", args.repo, "--body", args.owner) ensure_label(args.repo, "autorelease", "1d76db", "Autorelease event") ensure_label(args.repo, "attention-required", "d73a4a", "Owner action is required") - environment = json.loads(gh( - "api", - f"repos/{args.repo}/environments/php-autorelease-publish", - "--method", - "PUT", - input_value={ - "wait_timer": 0, - "prevent_self_review": False, - "reviewers": [], - "can_admins_bypass": False, - "deployment_branch_policy": { - "protected_branches": True, - "custom_branch_policies": False, + for environment_name in args.environment: + environment = json.loads(gh( + "api", + f"repos/{args.repo}/environments/{environment_name}", + "--method", + "PUT", + input_value={ + "wait_timer": 0, + "prevent_self_review": False, + "reviewers": [], + "can_admins_bypass": False, + "deployment_branch_policy": { + "protected_branches": True, + "custom_branch_policies": False, + }, }, - }, - )) - if environment.get("can_admins_bypass") is not False: - raise RuntimeError("GitHub did not disable administrator environment bypass") + )) + if environment.get("can_admins_bypass") is not False: + raise RuntimeError( + f"GitHub did not disable administrator environment bypass for {environment_name}" + ) protection = { "required_status_checks": { "strict": True, @@ -172,6 +185,7 @@ try: "repo": args.repo, "owner": args.owner, "requiredCheck": args.required_check, + "environments": args.environment, "unavailableSecurityFeatures": unavailable_security, } ) From a78e5b8d5bbd71264e8035793785dfdfcb942699 Mon Sep 17 00:00:00 2001 From: Lucian Behind The Scenes Date: Sun, 2 Aug 2026 22:01:06 +0300 Subject: [PATCH 2/2] fix: url-encode environment names in the provisioner api path --- scripts/configure-github-autorelease | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/configure-github-autorelease b/scripts/configure-github-autorelease index 64fee64..4ff563e 100755 --- a/scripts/configure-github-autorelease +++ b/scripts/configure-github-autorelease @@ -7,6 +7,7 @@ import pathlib import subprocess import sys import tempfile +import urllib.parse def gh(*arguments: str, input_value: dict | None = None) -> str: @@ -129,7 +130,8 @@ try: for environment_name in args.environment: environment = json.loads(gh( "api", - f"repos/{args.repo}/environments/{environment_name}", + # A name may contain a slash, which must stay one path segment. + f"repos/{args.repo}/environments/{urllib.parse.quote(environment_name, safe='')}", "--method", "PUT", input_value={