From 972eacf7550a88caa621915e534fcd632cc88ca9 Mon Sep 17 00:00:00 2001 From: Paul O'Fallon Date: Wed, 15 Oct 2025 22:23:44 -0400 Subject: [PATCH 01/15] Add ARM64 Linux support to CI/CD pipeline - Add ubuntu-24.04-arm runner for native ARM64 builds - Update build, integration-tests, and release-validation jobs - Add apm-linux-arm64 binary to release artifacts - Remove cross-compilation complexity in favor of native builds --- .github/workflows/build-release.yml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index da600796..ea191b15 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -104,6 +104,10 @@ jobs: platform: linux arch: x86_64 binary_name: apm-linux-x86_64 + - os: ubuntu-24.04-arm + platform: linux + arch: arm64 + binary_name: apm-linux-arm64 - os: macos-13 platform: darwin arch: x86_64 @@ -179,6 +183,10 @@ jobs: arch: x86_64 platform: linux binary_name: apm-linux-x86_64 + - os: ubuntu-24.04-arm + arch: arm64 + platform: linux + binary_name: apm-linux-arm64 - os: macos-13 arch: x86_64 platform: darwin @@ -250,6 +258,10 @@ jobs: arch: x86_64 platform: linux binary_name: apm-linux-x86_64 + - os: ubuntu-24.04-arm + arch: arm64 + platform: linux + binary_name: apm-linux-arm64 - os: macos-13 arch: x86_64 platform: darwin @@ -309,7 +321,7 @@ jobs: - name: Run release validation tests env: - APM_E2E_TESTS: "1" # Avoids interactive prompts for MCP env values with apm install + APM_E2E_TESTS: "1" # Avoids interactive prompts for MCP env values with apm install GITHUB_TOKEN: ${{ secrets.GH_MODELS_PAT }} GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} # Primary: APM module access run: | @@ -345,7 +357,7 @@ jobs: # Create tar.gz archives from directory structure for release and Homebrew cd dist - for binary in apm-linux-x86_64 apm-darwin-x86_64 apm-darwin-arm64; do + for binary in apm-linux-x86_64 apm-linux-arm64 apm-darwin-x86_64 apm-darwin-arm64; do # With artifacts containing both scripts and dist/, the binary is in artifact/dist/binary/ artifact_dir="${binary}" binary_dir="${artifact_dir}/dist/${binary}" @@ -402,6 +414,8 @@ jobs: files: | ./dist/apm-linux-x86_64.tar.gz ./dist/apm-linux-x86_64.tar.gz.sha256 + ./dist/apm-linux-arm64.tar.gz + ./dist/apm-linux-arm64.tar.gz.sha256 ./dist/apm-darwin-x86_64.tar.gz ./dist/apm-darwin-x86_64.tar.gz.sha256 ./dist/apm-darwin-arm64.tar.gz @@ -467,19 +481,24 @@ jobs: "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-darwin-x86_64.tar.gz.sha256" curl -L -o apm-linux-x86_64.tar.gz.sha256 \ "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-linux-x86_64.tar.gz.sha256" + curl -L -o apm-linux-arm64.tar.gz.sha256 \ + "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-linux-arm64.tar.gz.sha256" # Extract SHA256 checksums DARWIN_ARM64_SHA=$(cat apm-darwin-arm64.tar.gz.sha256 | cut -d' ' -f1) DARWIN_X86_64_SHA=$(cat apm-darwin-x86_64.tar.gz.sha256 | cut -d' ' -f1) LINUX_X86_64_SHA=$(cat apm-linux-x86_64.tar.gz.sha256 | cut -d' ' -f1) + LINUX_ARM64_SHA=$(cat apm-linux-arm64.tar.gz.sha256 | cut -d' ' -f1) echo "darwin-arm64-sha=$DARWIN_ARM64_SHA" >> $GITHUB_OUTPUT echo "darwin-x86_64-sha=$DARWIN_X86_64_SHA" >> $GITHUB_OUTPUT echo "linux-x86_64-sha=$LINUX_X86_64_SHA" >> $GITHUB_OUTPUT + echo "linux-arm64-sha=$LINUX_ARM64_SHA" >> $GITHUB_OUTPUT echo "Darwin ARM64 SHA: $DARWIN_ARM64_SHA" echo "Darwin x86_64 SHA: $DARWIN_X86_64_SHA" echo "Linux x86_64 SHA: $LINUX_X86_64_SHA" + echo "Linux ARM64 SHA: $LINUX_ARM64_SHA" - name: Trigger Homebrew tap repository update uses: peter-evans/repository-dispatch@v3 @@ -497,6 +516,7 @@ jobs: "checksums": { "darwin_arm64": "${{ steps.checksums.outputs.darwin-arm64-sha }}", "darwin_x86_64": "${{ steps.checksums.outputs.darwin-x86_64-sha }}", - "linux_x86_64": "${{ steps.checksums.outputs.linux-x86_64-sha }}" + "linux_x86_64": "${{ steps.checksums.outputs.linux-x86_64-sha }}", + "linux_arm64": "${{ steps.checksums.outputs.linux-arm64-sha }}" } } From 3717e8d3c77a953d95861ec572fa12e046c02564 Mon Sep 17 00:00:00 2001 From: Paul O'Fallon Date: Fri, 17 Oct 2025 07:52:40 -0400 Subject: [PATCH 02/15] Add ARM64 Ubuntu 24.04 to the workflow test matrix --- .github/workflows/build-release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index ea191b15..c2277630 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -39,6 +39,9 @@ jobs: - os: ubuntu-24.04 arch: x86_64 platform: linux + - os: ubuntu-24.04-arm + arch: arm64 + platform: linux - os: macos-13 arch: x86_64 platform: darwin From 8becd65a6fe028ca435edf716d6e2e6335b109bc Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 15:32:41 +0100 Subject: [PATCH 03/15] fix: Add ARM64 Linux support to Codex runtime setup - Add aarch64|arm64 architecture detection in setup-common.sh - Add linux-aarch64 -> aarch64-unknown-linux-gnu mapping in setup-codex.sh - Fixes smoke test failures on ARM64 Linux runners - Enables Codex runtime installation on ARM64 Linux systems Fixes smoke test error: 'Unsupported Linux architecture: aarch64' --- scripts/runtime/setup-codex.sh | 3 +++ scripts/runtime/setup-common.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/scripts/runtime/setup-codex.sh b/scripts/runtime/setup-codex.sh index d934e357..dcf84e17 100755 --- a/scripts/runtime/setup-codex.sh +++ b/scripts/runtime/setup-codex.sh @@ -61,6 +61,9 @@ setup_codex() { linux-x86_64) codex_platform="x86_64-unknown-linux-gnu" ;; + linux-aarch64) + codex_platform="aarch64-unknown-linux-gnu" + ;; *) log_error "Unsupported platform: $DETECTED_PLATFORM" exit 1 diff --git a/scripts/runtime/setup-common.sh b/scripts/runtime/setup-common.sh index 7b25ff1d..3dfe4af2 100755 --- a/scripts/runtime/setup-common.sh +++ b/scripts/runtime/setup-common.sh @@ -40,6 +40,9 @@ detect_platform() { x86_64|amd64) DETECTED_PLATFORM="linux-x86_64" ;; + aarch64|arm64) + DETECTED_PLATFORM="linux-aarch64" + ;; *) log_error "Unsupported Linux architecture: $arch" exit 1 From 42d2c850ba6d2490aa45b0b90e832c3fc9cb4c28 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 15:42:46 +0100 Subject: [PATCH 04/15] fix: Add ARM64 Linux support to integration test platform detection - Add aarch64|arm64 -> apm-linux-aarch64 mapping in test-integration.sh - Fixes integration test failures on ARM64 Linux runners - Complements runtime setup ARM64 support This was the missing piece causing integration tests to fail with: 'Unsupported Linux architecture: aarch64' --- scripts/test-integration.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index e4eaa061..69d521c3 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -74,6 +74,9 @@ detect_platform() { x86_64|amd64) BINARY_NAME="apm-linux-x86_64" ;; + aarch64|arm64) + BINARY_NAME="apm-linux-aarch64" + ;; *) log_error "Unsupported Linux architecture: $arch" exit 1 From 0c10a6a3290c96bf2d78912de82de7c322cc04eb Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 16:06:23 +0100 Subject: [PATCH 05/15] fix: Add missing 'cross' key to STATUS_SYMBOLS dictionary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Runtime list command was failing with KeyError: 'cross' - cli.py line 2040 references STATUS_SYMBOLS['cross'] but it wasn't defined - Added 'cross': '❌' to STATUS_SYMBOLS in console.py Fixes integration test failures: - test_runtime_list_command - test_dual_runtime_installation Error was: 'Error listing runtimes: 'cross'' --- src/apm_cli/utils/console.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apm_cli/utils/console.py b/src/apm_cli/utils/console.py index 8210de9d..b2be9de2 100644 --- a/src/apm_cli/utils/console.py +++ b/src/apm_cli/utils/console.py @@ -39,6 +39,7 @@ 'warning': '⚠️', 'error': '❌', 'check': '✅', + 'cross': '❌', 'list': '📋', 'preview': '👀', 'robot': '🤖', From 04206662f36e7dd0dde352433d6e1282ed4dc880 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 16:14:56 +0100 Subject: [PATCH 06/15] fix: Improve GitHub token fallback for Codex runtime setup - Add GITHUB_APM_PAT as fallback for models token purpose - Ensure both GITHUB_TOKEN and GITHUB_APM_PAT are available to Codex script - Fixes 'Using unauthenticated GitHub API request' in CI smoke tests The smoke test environment only provides GITHUB_APM_PAT but not GITHUB_TOKEN. The token manager now properly falls back to GITHUB_APM_PAT for GitHub Models API access when GITHUB_TOKEN is not available, and ensures the Codex setup script has access to both tokens as expected. --- src/apm_cli/core/token_manager.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/apm_cli/core/token_manager.py b/src/apm_cli/core/token_manager.py index d9aabd19..bfeda7ae 100644 --- a/src/apm_cli/core/token_manager.py +++ b/src/apm_cli/core/token_manager.py @@ -23,7 +23,7 @@ class GitHubTokenManager: # Define token precedence for different use cases TOKEN_PRECEDENCE = { 'copilot': ['GITHUB_COPILOT_PAT', 'GITHUB_TOKEN', 'GITHUB_APM_PAT'], - 'models': ['GITHUB_TOKEN'], # GitHub Models requires user-scoped PAT + 'models': ['GITHUB_TOKEN', 'GITHUB_APM_PAT'], # GitHub Models prefers user-scoped PAT, falls back to APM PAT 'modules': ['GITHUB_APM_PAT', 'GITHUB_TOKEN'], # APM module access } @@ -144,14 +144,19 @@ def _setup_copilot_tokens(self, env: Dict[str, str], available_tokens: Dict[str, env[env_var] = copilot_token def _setup_codex_tokens(self, env: Dict[str, str], available_tokens: Dict[str, str]): - """Set up tokens for Codex CLI (preserve existing GITHUB_TOKEN).""" - # Codex uses GITHUB_TOKEN directly - only set if missing - if self.preserve_existing and 'GITHUB_TOKEN' in env: - return - - models_token = self.get_token_for_purpose('models', available_tokens) - if models_token and 'GITHUB_TOKEN' not in env: - env['GITHUB_TOKEN'] = models_token + """Set up tokens for Codex CLI (preserve existing tokens).""" + # Codex script checks for both GITHUB_TOKEN and GITHUB_APM_PAT + # Set up GITHUB_TOKEN if not present + if not (self.preserve_existing and 'GITHUB_TOKEN' in env): + models_token = self.get_token_for_purpose('models', available_tokens) + if models_token and 'GITHUB_TOKEN' not in env: + env['GITHUB_TOKEN'] = models_token + + # Ensure GITHUB_APM_PAT is available if we have it + if not (self.preserve_existing and 'GITHUB_APM_PAT' in env): + apm_token = available_tokens.get('GITHUB_APM_PAT') + if apm_token and 'GITHUB_APM_PAT' not in env: + env['GITHUB_APM_PAT'] = apm_token def _setup_llm_tokens(self, env: Dict[str, str], available_tokens: Dict[str, str]): """Set up tokens for LLM CLI.""" From 5e252227d71466e1c87a8808ea78166b240a5096 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 16:28:08 +0100 Subject: [PATCH 07/15] fix: Align ARM64 Linux binary naming in integration tests - Change apm-linux-aarch64 to apm-linux-arm64 in test-integration.sh - Matches build script normalization: aarch64 -> arm64 - Fixes 'Binary not found: ./dist/apm-linux-aarch64/apm' error The build script normalizes aarch64 architecture to arm64, creating apm-linux-arm64 binary, but integration test was looking for apm-linux-aarch64. Now both use consistent arm64 naming. --- scripts/test-integration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index 69d521c3..d6971d81 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -75,7 +75,7 @@ detect_platform() { BINARY_NAME="apm-linux-x86_64" ;; aarch64|arm64) - BINARY_NAME="apm-linux-aarch64" + BINARY_NAME="apm-linux-arm64" ;; *) log_error "Unsupported Linux architecture: $arch" From 46330f0e2c656cf136d64d93d8e1c98a1a45009a Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 16:36:17 +0100 Subject: [PATCH 08/15] debug: Add debug logging to token manager for troubleshooting - Add debug prints to _setup_codex_tokens to see what tokens are available - This will help diagnose why Codex setup is still using unauthenticated requests - Temporary debugging commit to understand token flow in CI Will remove debug prints once issue is identified and fixed. --- src/apm_cli/core/token_manager.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/apm_cli/core/token_manager.py b/src/apm_cli/core/token_manager.py index bfeda7ae..0960260c 100644 --- a/src/apm_cli/core/token_manager.py +++ b/src/apm_cli/core/token_manager.py @@ -145,18 +145,27 @@ def _setup_copilot_tokens(self, env: Dict[str, str], available_tokens: Dict[str, def _setup_codex_tokens(self, env: Dict[str, str], available_tokens: Dict[str, str]): """Set up tokens for Codex CLI (preserve existing tokens).""" + # DEBUG: Print what tokens we have available + print(f"DEBUG: Available tokens: {list(available_tokens.keys())}") + print(f"DEBUG: GITHUB_TOKEN in env: {'GITHUB_TOKEN' in env}") + print(f"DEBUG: GITHUB_APM_PAT in env: {'GITHUB_APM_PAT' in env}") + # Codex script checks for both GITHUB_TOKEN and GITHUB_APM_PAT # Set up GITHUB_TOKEN if not present if not (self.preserve_existing and 'GITHUB_TOKEN' in env): models_token = self.get_token_for_purpose('models', available_tokens) + print(f"DEBUG: Models token found: {models_token is not None}") if models_token and 'GITHUB_TOKEN' not in env: env['GITHUB_TOKEN'] = models_token + print(f"DEBUG: Set GITHUB_TOKEN") # Ensure GITHUB_APM_PAT is available if we have it if not (self.preserve_existing and 'GITHUB_APM_PAT' in env): apm_token = available_tokens.get('GITHUB_APM_PAT') + print(f"DEBUG: APM token found: {apm_token is not None}") if apm_token and 'GITHUB_APM_PAT' not in env: env['GITHUB_APM_PAT'] = apm_token + print(f"DEBUG: Set GITHUB_APM_PAT") def _setup_llm_tokens(self, env: Dict[str, str], available_tokens: Dict[str, str]): """Set up tokens for LLM CLI.""" From 0f342720fc9d44eb428fdae6f1093ad00dec817c Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 16:46:17 +0100 Subject: [PATCH 09/15] fix: Explicitly pass environment to subprocess in smoke tests - Add env=os.environ.copy() to subprocess.run() in run_command() - Ensures GITHUB_APM_PAT and other environment variables are properly passed to the shell scripts in smoke tests - Fixes authentication issue where runtime setup scripts couldn't access GitHub tokens set in CI workflow Root cause: subprocess.run() with shell=True may not always inherit all environment variables properly, especially in test environments. --- tests/integration/test_runtime_smoke.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_runtime_smoke.py b/tests/integration/test_runtime_smoke.py index d10edefe..6aa3cb6d 100644 --- a/tests/integration/test_runtime_smoke.py +++ b/tests/integration/test_runtime_smoke.py @@ -40,6 +40,9 @@ def run_command(cmd, check=True, capture_output=True, timeout=60, cwd=None): if cwd is None: cwd = Path(__file__).parent.parent.parent + # Ensure environment variables are properly passed to subprocess + env = os.environ.copy() + result = subprocess.run( cmd, shell=True, @@ -47,7 +50,8 @@ def run_command(cmd, check=True, capture_output=True, timeout=60, cwd=None): capture_output=capture_output, text=True, timeout=timeout, - cwd=str(cwd) + cwd=str(cwd), + env=env # Explicitly pass environment ) return result except subprocess.TimeoutExpired: From c3a9eb2de1e50b92c8b1fccc9f46c64824fc5f79 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 16:48:26 +0100 Subject: [PATCH 10/15] clean: Remove debug prints from token manager - Revert debug logging added for troubleshooting - Keep only the core fix for subprocess environment passing --- src/apm_cli/core/token_manager.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/apm_cli/core/token_manager.py b/src/apm_cli/core/token_manager.py index 0960260c..99666476 100644 --- a/src/apm_cli/core/token_manager.py +++ b/src/apm_cli/core/token_manager.py @@ -145,27 +145,22 @@ def _setup_copilot_tokens(self, env: Dict[str, str], available_tokens: Dict[str, def _setup_codex_tokens(self, env: Dict[str, str], available_tokens: Dict[str, str]): """Set up tokens for Codex CLI (preserve existing tokens).""" - # DEBUG: Print what tokens we have available - print(f"DEBUG: Available tokens: {list(available_tokens.keys())}") - print(f"DEBUG: GITHUB_TOKEN in env: {'GITHUB_TOKEN' in env}") - print(f"DEBUG: GITHUB_APM_PAT in env: {'GITHUB_APM_PAT' in env}") - # Codex script checks for both GITHUB_TOKEN and GITHUB_APM_PAT # Set up GITHUB_TOKEN if not present if not (self.preserve_existing and 'GITHUB_TOKEN' in env): models_token = self.get_token_for_purpose('models', available_tokens) - print(f"DEBUG: Models token found: {models_token is not None}") if models_token and 'GITHUB_TOKEN' not in env: env['GITHUB_TOKEN'] = models_token - print(f"DEBUG: Set GITHUB_TOKEN") + if models_token and 'GITHUB_TOKEN' not in env: + env['GITHUB_TOKEN'] = models_token # Ensure GITHUB_APM_PAT is available if we have it if not (self.preserve_existing and 'GITHUB_APM_PAT' in env): apm_token = available_tokens.get('GITHUB_APM_PAT') - print(f"DEBUG: APM token found: {apm_token is not None}") if apm_token and 'GITHUB_APM_PAT' not in env: env['GITHUB_APM_PAT'] = apm_token - print(f"DEBUG: Set GITHUB_APM_PAT") + if apm_token and 'GITHUB_APM_PAT' not in env: + env['GITHUB_APM_PAT'] = apm_token def _setup_llm_tokens(self, env: Dict[str, str], available_tokens: Dict[str, str]): """Set up tokens for LLM CLI.""" From d49fbf6e27d60747e9e75f06323b3be74fa2457c Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 16:58:39 +0100 Subject: [PATCH 11/15] fix: call setup_github_tokens before GitHub API calls in setup-codex.sh - Ensures tokens are available for GitHub API requests to fetch latest release - Fixes 'Using unauthenticated GitHub API request' in CI environments - API call at line ~97 needs tokens set up early, not at line 171 - Addresses timing issue where tokens were configured after API usage --- scripts/runtime/setup-codex.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/runtime/setup-codex.sh b/scripts/runtime/setup-codex.sh index dcf84e17..03c32f25 100755 --- a/scripts/runtime/setup-codex.sh +++ b/scripts/runtime/setup-codex.sh @@ -46,6 +46,9 @@ done setup_codex() { log_info "Setting up Codex runtime..." + # Setup GitHub tokens early for API calls (before downloading latest release) + setup_github_tokens + # Detect platform using detect_platform from common utilities detect_platform From cea245a1191b85a07102f5ef75dfc8bd8372ee4f Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 17:06:42 +0100 Subject: [PATCH 12/15] fix: add GITHUB_TOKEN to smoke test environment in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Smoke tests now have both GITHUB_TOKEN and GITHUB_APM_PAT like other test jobs - Maps GH_MODELS_PAT → GITHUB_TOKEN for GitHub API authentication - Maps GH_CLI_PAT → GITHUB_APM_PAT for APM module access - Fixes 'Using unauthenticated GitHub API request' in smoke test step - Makes smoke test environment consistent with integration-tests and release-validation --- .github/workflows/build-release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index c2277630..4ae611e6 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -93,7 +93,8 @@ jobs: - name: Run smoke tests env: - GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} # Primary: APM module access (FG PAT) + GITHUB_TOKEN: ${{ secrets.GH_MODELS_PAT }} # Models access + GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} # APM module access run: uv run pytest tests/integration/test_runtime_smoke.py -v # Build binaries From d6d641f567cd0ff92a5a3d593732d2fef56ef1c5 Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 17:11:58 +0100 Subject: [PATCH 13/15] debug: add comprehensive logging to diagnose GitHub token authentication - Add detailed environment variable debugging to github-token-helper.sh - Show initial and final token state with character counts - Add debug logging to setup-codx.sh before GitHub API calls - Add environment debugging to test_runtime_smoke.py subprocess calls - Debug output will show exactly which tokens are available and being used - Helps diagnose why CI shows 'unauthenticated' despite token setup success This will reveal the exact root cause of authentication failure in CI. --- scripts/github-token-helper.sh | 20 +++++++++++++++++++- scripts/runtime/setup-codex.sh | 13 ++++++++----- tests/integration/test_runtime_smoke.py | 10 ++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/scripts/github-token-helper.sh b/scripts/github-token-helper.sh index e4911a95..ff6eb0af 100755 --- a/scripts/github-token-helper.sh +++ b/scripts/github-token-helper.sh @@ -25,13 +25,25 @@ setup_github_tokens() { echo -e "${BLUE}Setting up GitHub tokens...${NC}" fi + # DEBUG: Show all GitHub-related environment variables + echo -e "${YELLOW}🔍 DEBUG: GitHub token environment analysis:${NC}" + echo " GITHUB_TOKEN: ${GITHUB_TOKEN:+SET(${#GITHUB_TOKEN} chars)}${GITHUB_TOKEN:-UNSET}" + echo " GITHUB_APM_PAT: ${GITHUB_APM_PAT:+SET(${#GITHUB_APM_PAT} chars)}${GITHUB_APM_PAT:-UNSET}" + echo " GH_MODELS_PAT: ${GH_MODELS_PAT:+SET(${#GH_MODELS_PAT} chars)}${GH_MODELS_PAT:-UNSET}" + echo " GH_CLI_PAT: ${GH_CLI_PAT:+SET(${#GH_CLI_PAT} chars)}${GH_CLI_PAT:-UNSET}" + echo " GH_PKG_PAT: ${GH_PKG_PAT:+SET(${#GH_PKG_PAT} chars)}${GH_PKG_PAT:-UNSET}" + echo " CI environment: ${CI:-UNSET}" + echo " GITHUB_ACTIONS: ${GITHUB_ACTIONS:-UNSET}" + # CRITICAL: Preserve existing GITHUB_TOKEN if set (for Models access) local preserve_github_token="" if [[ -n "${GITHUB_TOKEN:-}" ]]; then preserve_github_token="$GITHUB_TOKEN" if [[ "$quiet_mode" != "true" ]]; then - echo -e "${GREEN}✓ Preserving existing GITHUB_TOKEN for Models access${NC}" + echo -e "${GREEN}✓ Preserving existing GITHUB_TOKEN for Models access (${#GITHUB_TOKEN} chars)${NC}" fi + else + echo -e "${YELLOW}⚠️ No GITHUB_TOKEN found initially${NC}" fi # 2. Setup APM module access @@ -61,6 +73,12 @@ setup_github_tokens() { export GITHUB_MODELS_KEY="${GITHUB_TOKEN}" fi + # DEBUG: Show final token state + echo -e "${YELLOW}🔍 DEBUG: Final token configuration:${NC}" + echo " GITHUB_TOKEN: ${GITHUB_TOKEN:+SET(${#GITHUB_TOKEN} chars)}${GITHUB_TOKEN:-UNSET}" + echo " GITHUB_APM_PAT: ${GITHUB_APM_PAT:+SET(${#GITHUB_APM_PAT} chars)}${GITHUB_APM_PAT:-UNSET}" + echo " GITHUB_MODELS_KEY: ${GITHUB_MODELS_KEY:+SET(${#GITHUB_MODELS_KEY} chars)}${GITHUB_MODELS_KEY:-UNSET}" + if [[ "$quiet_mode" != "true" ]]; then echo -e "${GREEN}✅ GitHub token environment configured${NC}" fi diff --git a/scripts/runtime/setup-codex.sh b/scripts/runtime/setup-codex.sh index 03c32f25..043cb481 100755 --- a/scripts/runtime/setup-codex.sh +++ b/scripts/runtime/setup-codex.sh @@ -46,9 +46,6 @@ done setup_codex() { log_info "Setting up Codex runtime..." - # Setup GitHub tokens early for API calls (before downloading latest release) - setup_github_tokens - # Detect platform using detect_platform from common utilities detect_platform @@ -94,18 +91,24 @@ setup_codex() { local latest_release_url="https://api.github.com/repos/$CODEX_REPO/releases/latest" local latest_tag + # DEBUG: Show token state right before API call + log_info "🔍 DEBUG: Token state before GitHub API call:" + log_info " GITHUB_TOKEN: ${GITHUB_TOKEN:+SET(${#GITHUB_TOKEN} chars)}${GITHUB_TOKEN:-UNSET}" + log_info " GITHUB_APM_PAT: ${GITHUB_APM_PAT:+SET(${#GITHUB_APM_PAT} chars)}${GITHUB_APM_PAT:-UNSET}" + # Try to get the latest release tag using curl if command -v curl >/dev/null 2>&1; then # Use authenticated request if GITHUB_TOKEN or GITHUB_APM_PAT is available if [[ -n "${GITHUB_TOKEN:-}" ]]; then - log_info "Using authenticated GitHub API request (GITHUB_TOKEN)" + log_info "Using authenticated GitHub API request (GITHUB_TOKEN - ${#GITHUB_TOKEN} chars)" local auth_header="Authorization: Bearer ${GITHUB_TOKEN}" latest_tag=$(curl -s -H "$auth_header" "$latest_release_url" | grep '"tag_name":' | sed -E 's/.*"tag_name":[[:space:]]*"([^"]+)".*/\1/') elif [[ -n "${GITHUB_APM_PAT:-}" ]]; then - log_info "Using authenticated GitHub API request (GITHUB_APM_PAT)" + log_info "Using authenticated GitHub API request (GITHUB_APM_PAT - ${#GITHUB_APM_PAT} chars)" local auth_header="Authorization: Bearer ${GITHUB_APM_PAT}" latest_tag=$(curl -s -H "$auth_header" "$latest_release_url" | grep '"tag_name":' | sed -E 's/.*"tag_name":[[:space:]]*"([^"]+)".*/\1/') else + log_info "🚨 DEBUG: No tokens available - GITHUB_TOKEN and GITHUB_APM_PAT both unset!" log_info "Using unauthenticated GitHub API request (60 requests/hour limit)" latest_tag=$(curl -s "$latest_release_url" | grep '"tag_name":' | sed -E 's/.*"tag_name":[[:space:]]*"([^"]+)".*/\1/') fi diff --git a/tests/integration/test_runtime_smoke.py b/tests/integration/test_runtime_smoke.py index 6aa3cb6d..281ab52f 100644 --- a/tests/integration/test_runtime_smoke.py +++ b/tests/integration/test_runtime_smoke.py @@ -43,6 +43,16 @@ def run_command(cmd, check=True, capture_output=True, timeout=60, cwd=None): # Ensure environment variables are properly passed to subprocess env = os.environ.copy() + # DEBUG: Show GitHub-related environment variables being passed + print(f"🔍 DEBUG: Environment variables being passed to subprocess:") + for key in ['GITHUB_TOKEN', 'GITHUB_APM_PAT', 'GH_MODELS_PAT', 'GH_CLI_PAT', 'GH_PKG_PAT']: + value = env.get(key) + if value: + print(f" {key}: SET ({len(value)} chars)") + else: + print(f" {key}: UNSET") + print(f" Command: {cmd}") + result = subprocess.run( cmd, shell=True, From 1e4e28a4ba5c965121f27d14f8eff60c2795a4fc Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 17:28:46 +0100 Subject: [PATCH 14/15] fix: use pull_request_target for fork PR secrets access - Change from pull_request to pull_request_target - Enables secrets access for fork PRs while maintaining security - Revert to proper secrets (GH_MODELS_PAT, GH_CLI_PAT, GH_PKG_PAT) - Add security documentation for pull_request_target usage Fixes GitHub Actions fork PR limitation where custom secrets are not available, while preserving full functionality for regular PRs and main branch builds. --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 4ae611e6..a7d8d629 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -11,7 +11,7 @@ on: - 'docs/**' - '.gitignore' - 'LICENSE' - pull_request: + pull_request_target: # Use pull_request_target for secrets access from forks branches: [ main ] paths-ignore: - 'docs/**' From 369abd11a5ff5e4159b7e9d2abba853f63c7726a Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Tue, 28 Oct 2025 17:42:13 +0100 Subject: [PATCH 15/15] security: revert to pull_request for secure fork handling - Revert from pull_request_target to pull_request for proper security - This prevents automatic secrets exposure to untrusted fork code - Fork PRs will now require manual approval workflow as intended - Maintains GitHub's security model for open source projects This addresses the security concern where pull_request_target would automatically grant secrets access without approval, bypassing GitHub's built-in fork protection mechanisms. --- .github/workflows/build-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index a7d8d629..234bbe0c 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -11,7 +11,7 @@ on: - 'docs/**' - '.gitignore' - 'LICENSE' - pull_request_target: # Use pull_request_target for secrets access from forks + pull_request: branches: [ main ] paths-ignore: - 'docs/**'