From 3a02118213e0aa62ce28613a4909c5b8d5e8d49a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Rubinstein?= Date: Fri, 26 Dec 2025 14:11:20 +0100 Subject: [PATCH 1/2] Log Actions perms and pin app installation --- .github/workflows/tests.yml | 1 + tests/get_github_app_token.py | 32 +++++++++++++++++++++++++++++++- tests/test_e2e.sh | 8 +++++--- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6cf395c..65d7ad6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,6 +32,7 @@ jobs: - name: Run e2e tests env: GH_APP_ID: ${{ vars.GH_APP_ID }} + GH_APP_INSTALLATION_ID: ${{ vars.GH_APP_INSTALLATION_ID }} GH_APP_PRIVATE_KEY_PEM_B64: ${{ secrets.GH_APP_PRIVATE_KEY_PEM_B64 }} PRESERVE_ON_FAILURE: "1" run: | diff --git a/tests/get_github_app_token.py b/tests/get_github_app_token.py index 62dcf13..48b910f 100755 --- a/tests/get_github_app_token.py +++ b/tests/get_github_app_token.py @@ -132,8 +132,38 @@ def generate_installation_token(): print("Error: No installations found for this GitHub App", file=sys.stderr) sys.exit(1) + installation_id_env = os.getenv("GH_APP_INSTALLATION_ID") + if installation_id_env: + try: + desired_id = int(installation_id_env) + except ValueError: + print("Error: GH_APP_INSTALLATION_ID must be an integer", file=sys.stderr) + sys.exit(1) + installation = next((i for i in installations if i.get("id") == desired_id), None) + if not installation: + available_ids = [i.get("id") for i in installations if "id" in i] + print( + f"Error: GH_APP_INSTALLATION_ID {desired_id} not found. " + f"Available installation IDs: {available_ids}", + file=sys.stderr, + ) + sys.exit(1) + else: + installation = installations[0] + available = ", ".join( + f"{i.get('id')}:{i.get('account', {}).get('login', 'unknown')}" + for i in installations + ) + print(f"Available installations: {available}", file=sys.stderr) + + installation_id = installation["id"] + account_login = installation.get("account", {}).get("login", "unknown") + print( + f"Using installation id {installation_id} (account {account_login})", + file=sys.stderr, + ) + # Create installation token - installation_id = installations[0]['id'] url = f"https://api.github.com/app/installations/{installation_id}/access_tokens" response = requests.post(url, headers=headers) response.raise_for_status() diff --git a/tests/test_e2e.sh b/tests/test_e2e.sh index 2045d27..3688442 100755 --- a/tests/test_e2e.sh +++ b/tests/test_e2e.sh @@ -459,9 +459,11 @@ echo >&2 "2. Creating remote GitHub repository: $REPO_FULL_NAME" log_cmd gh repo create "$REPO_FULL_NAME" --description "Temporary E2E test repo for update-pr-stack action" --public echo >&2 "Successfully created $REPO_FULL_NAME" -# Enable GitHub Actions on the new repository (may be disabled by default in CI environments) -echo >&2 "Enabling GitHub Actions on the repository..." -log_cmd gh api -X PUT "/repos/$REPO_FULL_NAME/actions/permissions" --input - <<< '{"enabled":true,"allowed_actions":"all"}' +# Log default GitHub Actions permissions (repo inherits org/user defaults) +echo >&2 "Checking repository Actions permissions..." +if ! log_cmd gh api "/repos/$REPO_FULL_NAME/actions/permissions"; then + echo >&2 "Warning: unable to read Actions permissions for $REPO_FULL_NAME" +fi # 3. Push initial state echo >&2 "3. Pushing initial state to remote..." From e0470b451c8f623e670fe4dda2e75dc09af771ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Rubinstein?= Date: Fri, 26 Dec 2025 14:22:48 +0100 Subject: [PATCH 2/2] Drop app installation pinning --- .github/workflows/tests.yml | 1 - tests/get_github_app_token.py | 31 +------------------------------ 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 65d7ad6..6cf395c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,6 @@ jobs: - name: Run e2e tests env: GH_APP_ID: ${{ vars.GH_APP_ID }} - GH_APP_INSTALLATION_ID: ${{ vars.GH_APP_INSTALLATION_ID }} GH_APP_PRIVATE_KEY_PEM_B64: ${{ secrets.GH_APP_PRIVATE_KEY_PEM_B64 }} PRESERVE_ON_FAILURE: "1" run: | diff --git a/tests/get_github_app_token.py b/tests/get_github_app_token.py index 48b910f..b0e39d0 100755 --- a/tests/get_github_app_token.py +++ b/tests/get_github_app_token.py @@ -132,36 +132,7 @@ def generate_installation_token(): print("Error: No installations found for this GitHub App", file=sys.stderr) sys.exit(1) - installation_id_env = os.getenv("GH_APP_INSTALLATION_ID") - if installation_id_env: - try: - desired_id = int(installation_id_env) - except ValueError: - print("Error: GH_APP_INSTALLATION_ID must be an integer", file=sys.stderr) - sys.exit(1) - installation = next((i for i in installations if i.get("id") == desired_id), None) - if not installation: - available_ids = [i.get("id") for i in installations if "id" in i] - print( - f"Error: GH_APP_INSTALLATION_ID {desired_id} not found. " - f"Available installation IDs: {available_ids}", - file=sys.stderr, - ) - sys.exit(1) - else: - installation = installations[0] - available = ", ".join( - f"{i.get('id')}:{i.get('account', {}).get('login', 'unknown')}" - for i in installations - ) - print(f"Available installations: {available}", file=sys.stderr) - - installation_id = installation["id"] - account_login = installation.get("account", {}).get("login", "unknown") - print( - f"Using installation id {installation_id} (account {account_login})", - file=sys.stderr, - ) + installation_id = installations[0]['id'] # Create installation token url = f"https://api.github.com/app/installations/{installation_id}/access_tokens"