From 4705c21055997236c5c23e3b52fd489b41da09ad Mon Sep 17 00:00:00 2001 From: enyst Date: Sun, 24 May 2026 00:12:49 +0000 Subject: [PATCH 1/8] Harden workflow GitHub context handling Pass attacker-controllable GitHub context and workflow values through environment variables before shell use. Co-authored-by: openhands --- .github/workflows/api-compliance-runner.yml | 13 +++-- .github/workflows/condenser-runner.yml | 7 ++- .github/workflows/create-release.yml | 3 +- .github/workflows/integration-runner.yml | 17 ++++-- .github/workflows/pr-artifacts.yml | 5 +- .github/workflows/prepare-release.yml | 40 ++++++++----- .github/workflows/pypi-release.yml | 7 ++- .github/workflows/release-binaries.yml | 16 ++++-- .github/workflows/run-examples.yml | 5 +- .github/workflows/server.yml | 63 ++++++++++++++------- .github/workflows/todo-management.yml | 14 +++-- .github/workflows/version-bump-prs.yml | 4 +- 12 files changed, 129 insertions(+), 65 deletions(-) diff --git a/.github/workflows/api-compliance-runner.yml b/.github/workflows/api-compliance-runner.yml index 784912f1da..d51e7b2d75 100644 --- a/.github/workflows/api-compliance-runner.yml +++ b/.github/workflows/api-compliance-runner.yml @@ -49,11 +49,15 @@ jobs: - name: Determine test parameters id: params + env: + EVENT_NAME: ${{ github.event_name }} + PATTERNS_INPUT: ${{ github.event.inputs.patterns }} + MODELS_INPUT: ${{ github.event.inputs.models }} run: | # Use input values or defaults - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - PATTERNS="${{ github.event.inputs.patterns }}" - MODELS="${{ github.event.inputs.models }}" + if [ "$EVENT_NAME" = "workflow_dispatch" ]; then + PATTERNS="$PATTERNS_INPUT" + MODELS="$MODELS_INPUT" else PATTERNS="" MODELS="" @@ -78,9 +82,10 @@ jobs: LLM_API_KEY: ${{ secrets.LLM_API_KEY_EVAL }} LLM_BASE_URL: https://llm-proxy.eval.all-hands.dev GITHUB_RUN_ID: ${{ github.run_id }} + PARAM_ARGS: ${{ steps.params.outputs.args }} run: | uv run python tests/integration/api_compliance/run_compliance.py \ - ${{ steps.params.outputs.args }} \ + $PARAM_ARGS \ --output-dir compliance-results/ continue-on-error: true # Tests may "fail" but that's expected diff --git a/.github/workflows/condenser-runner.yml b/.github/workflows/condenser-runner.yml index 962da506e1..d708d90726 100644 --- a/.github/workflows/condenser-runner.yml +++ b/.github/workflows/condenser-runner.yml @@ -228,6 +228,9 @@ jobs: - name: Create consolidated PR comment if: github.event_name == 'pull_request_target' + env: + GH_TOKEN: ${{ github.token }} + GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} run: | # Add header to clarify these are non-blocking tests echo "## Condenser Test Results (Non-Blocking)" > final_report.md @@ -239,6 +242,4 @@ jobs: # Sanitize @OpenHands mentions to prevent self-mention loops COMMENT_BODY=$(uv run python -c "from openhands.sdk.utils.github import sanitize_openhands_mentions; import sys; print(sanitize_openhands_mentions(sys.stdin.read()), end='')" < final_report.md) # Use GitHub CLI to create comment with explicit PR number - echo "$COMMENT_BODY" | gh pr comment ${{ github.event.pull_request.number }} --body-file - - env: - GH_TOKEN: ${{ github.token }} + echo "$COMMENT_BODY" | gh pr comment "$GITHUB_EVENT_PULL_REQUEST_NUMBER" --body-file - diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index efed7dd209..f2c6a8d8c9 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -146,6 +146,7 @@ jobs: PREAMBLE_PATH: release-note-preamble.md VERSION: ${{ steps.version.outputs.version }} PREV_TAG: ${{ steps.prev_tag.outputs.prev_tag }} + GITHUB_EVENT_PULL_REQUEST_MERGE_COMMIT_SHA: ${{ github.event.pull_request.merge_commit_sha }} run: | NOTES_START_FLAG=() if [ -n "$PREV_TAG" ]; then @@ -159,7 +160,7 @@ jobs: gh release create "v${VERSION}" \ --repo "${{ github.repository }}" \ - --target "${{ github.event.pull_request.merge_commit_sha }}" \ + --target "$GITHUB_EVENT_PULL_REQUEST_MERGE_COMMIT_SHA" \ --title "v${VERSION}" \ --generate-notes \ "${PREAMBLE_FLAG[@]}" \ diff --git a/.github/workflows/integration-runner.yml b/.github/workflows/integration-runner.yml index 009c1006d9..3341b804b4 100644 --- a/.github/workflows/integration-runner.yml +++ b/.github/workflows/integration-runner.yml @@ -260,16 +260,20 @@ jobs: # Run integration test evaluation - name: Determine test selection + env: + EVENT_NAME: ${{ github.event_name }} + LABEL_NAME: ${{ github.event.label.name }} + TEST_TYPE_INPUT: ${{ github.event.inputs.test_type }} run: | TEST_TYPE_ARGS="" - if [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "behavior-test" ]; then + if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$LABEL_NAME" = "behavior-test" ]; then TEST_TYPE_ARGS="--test-type behavior" echo "behavior-test label detected; running behavior tests only." - elif [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "integration-test" ]; then + elif [ "$EVENT_NAME" = "pull_request_target" ] && [ "$LABEL_NAME" = "integration-test" ]; then TEST_TYPE_ARGS="--test-type integration" echo "integration-test label detected; running integration tests only." - elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - test_type="${{ github.event.inputs.test_type }}" + elif [ "$EVENT_NAME" = "workflow_dispatch" ]; then + test_type="$TEST_TYPE_INPUT" case "$test_type" in behavior) TEST_TYPE_ARGS="--test-type behavior" @@ -286,7 +290,7 @@ jobs: echo "workflow_dispatch provided unknown test_type '$test_type'; defaulting to full suite." ;; esac - elif [ "${{ github.event_name }}" = "schedule" ]; then + elif [ "$EVENT_NAME" = "schedule" ]; then TEST_TYPE_ARGS="--test-type integration" echo "Scheduled run; running integration tests only." else @@ -447,9 +451,10 @@ jobs: # Sanitize @OpenHands mentions to prevent self-mention loops COMMENT_BODY=$(uv run python -c "from openhands.sdk.utils.github import sanitize_openhands_mentions; import sys; print(sanitize_openhands_mentions(sys.stdin.read()), end='')" < consolidated_report.md) # Use GitHub CLI to create comment with explicit PR number - echo "$COMMENT_BODY" | gh pr comment ${{ github.event.pull_request.number }} --body-file - + echo "$COMMENT_BODY" | gh pr comment "$PR_NUMBER" --body-file - env: GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} - name: Comment on specified issue/PR (workflow_dispatch) if: github.event_name == 'workflow_dispatch' && needs.setup-matrix.outputs.issue_number != '' diff --git a/.github/workflows/pr-artifacts.yml b/.github/workflows/pr-artifacts.yml index 5d233e5e51..d5fac6a56c 100644 --- a/.github/workflows/pr-artifacts.yml +++ b/.github/workflows/pr-artifacts.yml @@ -23,8 +23,11 @@ jobs: steps: - name: Check if fork PR id: check-fork + env: + PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + PR_BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }} run: | - if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.event.pull_request.base.repo.full_name }}" ]; then + if [ "$PR_HEAD_REPO" != "$PR_BASE_REPO" ]; then echo "is_fork=true" >> $GITHUB_OUTPUT echo "::notice::Fork PR detected - skipping auto-cleanup (manual removal required)" else diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 1aa6e632ee..64b54d7505 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -14,12 +14,14 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Validate version format + env: + INPUTS_VERSION: ${{ inputs.version }} run: | - if ! [[ "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + if ! [[ "$INPUTS_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "❌ Invalid version format. Expected: X.Y.Z (e.g., 1.2.3)" exit 1 fi - echo "✅ Version format is valid: ${{ inputs.version }}" + echo "✅ Version format is valid: $INPUTS_VERSION" - name: Checkout repository uses: actions/checkout@v6 @@ -38,27 +40,35 @@ jobs: git config user.email "github-actions[bot]@users.noreply.github.com" - name: Create release branch + env: + INPUTS_VERSION: ${{ inputs.version }} run: | - BRANCH_NAME="rel-${{ inputs.version }}" + BRANCH_NAME="rel-$INPUTS_VERSION" echo "Creating branch: $BRANCH_NAME" git checkout -b "$BRANCH_NAME" echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV - name: Set package version + env: + INPUTS_VERSION: ${{ inputs.version }} run: | - echo "🔧 Setting version to ${{ inputs.version }}" - make set-package-version version=${{ inputs.version }} + echo "🔧 Setting version to $INPUTS_VERSION" + make set-package-version version=$INPUTS_VERSION - name: Update sdk_ref default in run-eval workflow - run: python3 .github/scripts/update_sdk_ref_default.py "${{ inputs.version }}" + env: + INPUTS_VERSION: ${{ inputs.version }} + run: python3 .github/scripts/update_sdk_ref_default.py "$INPUTS_VERSION" - name: Commit version changes + env: + INPUTS_VERSION: ${{ inputs.version }} run: | git add . if git diff --staged --quiet; then echo "No changes to commit" else - git commit -m "Release v${{ inputs.version }}" -m "Co-authored-by: openhands " + git commit -m "Release v$INPUTS_VERSION" -m "Co-authored-by: openhands " echo "✅ Changes committed" fi @@ -70,14 +80,15 @@ jobs: - name: Create Pull Request env: GH_TOKEN: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC }} + INPUTS_VERSION: ${{ inputs.version }} run: | cat > pr_body.txt << 'EOF' - ## Release v${{ inputs.version }} + ## Release v__VERSION__ - This PR prepares the release for version **${{ inputs.version }}**. + This PR prepares the release for version **__VERSION__**. ### Release Checklist - - [x] Version set to ${{ inputs.version }} + - [x] Version set to __VERSION__ - [ ] Fix any deprecation deadlines if they exist - [ ] Integration tests pass (tagged with `integration-test`) - [ ] Behavior tests pass (tagged with `behavior-test`) @@ -87,13 +98,14 @@ jobs: ### What happens on merge When this PR is merged, the `create-release.yml` workflow will automatically: - 1. Create a GitHub release with tag `v${{ inputs.version }}` and auto-generated notes, plus an explicit preamble for merged `release-note-required` PRs + 1. Create a GitHub release with tag `v__VERSION__` and auto-generated notes, plus an explicit preamble for merged `release-note-required` PRs 2. Trigger `pypi-release.yml` to publish all packages to PyPI 3. Trigger `version-bump-prs.yml` to create downstream version bump PRs EOF + sed -i "s/__VERSION__/$INPUTS_VERSION/g" pr_body.txt gh pr create \ - --title "Release v${{ inputs.version }}" \ + --title "Release v$INPUTS_VERSION" \ --body-file pr_body.txt \ --base main \ --head "${{ env.BRANCH_NAME }}" \ @@ -110,10 +122,12 @@ jobs: echo "PR_URL=$PR_URL" >> $GITHUB_ENV - name: Summary + env: + INPUTS_VERSION: ${{ inputs.version }} run: | echo "## ✅ Release Preparation Complete!" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "- **Version**: ${{ inputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "- **Version**: $INPUTS_VERSION" >> $GITHUB_STEP_SUMMARY echo "- **Branch**: ${{ env.BRANCH_NAME }}" >> $GITHUB_STEP_SUMMARY echo "- **PR URL**: ${{ env.PR_URL }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index 8e05fb03ec..3af4256ae8 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -28,10 +28,13 @@ jobs: - name: Extract version from release tag id: extract_version + env: + GITHUB_EVENT_NAME: ${{ github.event_name }} + GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }} run: | # Get version from release tag (e.g., v1.2.3 -> 1.2.3) - if [[ "${{ github.event_name }}" == "release" ]]; then - VERSION="${{ github.event.release.tag_name }}" + if [[ "$GITHUB_EVENT_NAME" == "release" ]]; then + VERSION="$GITHUB_EVENT_RELEASE_TAG_NAME" VERSION="${VERSION#v}" # Remove 'v' prefix if present else # For manual dispatch, extract from pyproject.toml diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index 71ef04c020..f22b520f9a 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -38,19 +38,23 @@ jobs: steps: - id: resolve shell: bash + env: + GITHUB_EVENT_NAME: ${{ github.event_name }} + GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }} + INPUTS_RELEASE_TAG: ${{ inputs.release_tag }} run: | set -euo pipefail - if [[ "${{ github.event_name }}" == "release" ]]; then - TAG="${{ github.event.release.tag_name }}" + if [[ "$GITHUB_EVENT_NAME" == "release" ]]; then + TAG="$GITHUB_EVENT_RELEASE_TAG_NAME" VERSION="${TAG#v}" - elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - TAG="${{ inputs.release_tag }}" + elif [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then + TAG="$INPUTS_RELEASE_TAG" VERSION="${TAG#v}" - elif [[ "${{ github.event_name }}" == "push" ]]; then + elif [[ "$GITHUB_EVENT_NAME" == "push" ]]; then TAG="" VERSION="${GITHUB_SHA::7}" else - echo "ERROR: unsupported event '${{ github.event_name }}'" + echo "ERROR: unsupported event '$GITHUB_EVENT_NAME'" exit 1 fi diff --git a/.github/workflows/run-examples.yml b/.github/workflows/run-examples.yml index f6c1a130e0..4b2224a231 100644 --- a/.github/workflows/run-examples.yml +++ b/.github/workflows/run-examples.yml @@ -83,6 +83,7 @@ jobs: ANTHROPIC_API_KEY: ${{ secrets.LLM_API_KEY }} OPENAI_BASE_URL: https://llm-proxy.app.all-hands.dev OPENAI_API_KEY: ${{ secrets.LLM_API_KEY }} + GITHUB_EVENT_NAME: ${{ github.event_name }} run: | RESULTS_DIR=".example-test-results" REPORT_PATH="examples_report.md" @@ -135,7 +136,7 @@ jobs: API_URL="" COMMENT_ID="" - if [ "${{ github.event_name }}" = "pull_request" ]; then + if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then API_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/issues/${PR_NUMBER}/comments" initial_comment="## 🔄 Running Examples with \`${LLM_MODEL}\`" initial_comment+=$'\n\n' @@ -163,7 +164,7 @@ jobs: COMMENT_BODY="$(cat "$REPORT_PATH")" echo "$COMMENT_BODY" - if [ "${{ github.event_name }}" = "pull_request" ]; then + if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then echo "Publishing PR comment..." update_comment "$COMMENT_BODY" fi diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index c3ab529464..0bf8f71e8f 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -351,6 +351,8 @@ jobs: - name: Prepare build context and metadata id: prep + env: + GITHUB_REF: ${{ github.ref }} run: | uv sync --frozen @@ -358,7 +360,7 @@ jobs: # build.py now handles architecture tagging internally via --arch flag # Add --versioned-tag when triggered by a git tag (e.g., v1.0.0) BUILD_CMD="uv run ./openhands-agent-server/openhands/agent_server/docker/build.py --build-ctx-only --arch ${{ matrix.arch }}" - if [[ "${{ github.ref }}" == refs/tags/* ]]; then + if [[ "$GITHUB_REF" == refs/tags/* ]]; then BUILD_CMD="$BUILD_CMD --versioned-tag" fi eval "$BUILD_CMD" @@ -403,23 +405,33 @@ jobs: - name: Cleanup build context if: always() + env: + BUILD_CONTEXT: ${{ steps.prep.outputs.build_context }} run: | - if [ -n "${{ steps.prep.outputs.build_context }}" ] && [ -d "${{ steps.prep.outputs.build_context }}" ]; then - echo "Cleaning up build context: ${{ steps.prep.outputs.build_context }}" - rm -rf "${{ steps.prep.outputs.build_context }}" + if [ -n "$BUILD_CONTEXT" ] && [ -d "$BUILD_CONTEXT" ]; then + echo "Cleaning up build context: $BUILD_CONTEXT" + rm -rf "$BUILD_CONTEXT" fi - name: Summary (${{ matrix.variant }}-${{ matrix.arch }}) - outputs + env: + SHORT_SHA: ${{ steps.prep.outputs.short_sha }} + TAGS: ${{ steps.prep.outputs.tags }} + BUILD_DIGEST: ${{ steps.build.outputs.digest }} run: | - echo "Image: ${{ env.IMAGE }}" - echo "Variant: ${{ env.VARIANT }}" - echo "Architecture: ${{ env.ARCH }}" - echo "Platform: ${{ env.PLATFORM }}" - echo "Short SHA: ${{ steps.prep.outputs.short_sha }}" - echo "Tags: ${{ steps.prep.outputs.tags }}" - echo "Build digest: ${{ steps.build.outputs.digest }}" + echo "Image: $IMAGE" + echo "Variant: $VARIANT" + echo "Architecture: $ARCH" + echo "Platform: $PLATFORM" + echo "Short SHA: $SHORT_SHA" + echo "Tags: $TAGS" + echo "Build digest: $BUILD_DIGEST" - name: Save build info for consolidation + env: + SHORT_SHA: ${{ steps.prep.outputs.short_sha }} + TAGS: ${{ steps.prep.outputs.tags }} + VERSIONED_TAGS_CSV: ${{ steps.prep.outputs.versioned_tags_csv }} run: | mkdir -p build-info cat > "build-info/${{ matrix.variant }}-${{ matrix.arch }}.json" << EOF @@ -427,11 +439,11 @@ jobs: "variant": "${{ matrix.variant }}", "arch": "${{ matrix.arch }}", "base_image": "${{ matrix.base_image }}", - "image": "${{ env.IMAGE }}", - "short_sha": "${{ steps.prep.outputs.short_sha }}", - "tags": "${{ steps.prep.outputs.tags }}", - "versioned_tags_csv": "${{ steps.prep.outputs.versioned_tags_csv }}", - "platform": "${{ env.PLATFORM }}" + "image": "$IMAGE", + "short_sha": "$SHORT_SHA", + "tags": "$TAGS", + "versioned_tags_csv": "$VERSIONED_TAGS_CSV", + "platform": "$PLATFORM" } EOF @@ -485,8 +497,10 @@ jobs: - name: Create and push multi-arch manifest for ${{ matrix.variant }} id: create_manifest + env: + SHORT_SHA: ${{ steps.get_sha.outputs.short_sha }} + GIT_REF: ${{ github.ref }} run: | - SHORT_SHA=${{ steps.get_sha.outputs.short_sha }} VARIANT=${{ matrix.variant }} AMD64_TAGS_CSV=$(jq -r '.tags' build-info/${VARIANT}-amd64.json) declare -A SEEN_MANIFEST_TAGS=() @@ -529,7 +543,7 @@ jobs: done # Preserve the latest- alias used by the workspace defaults. - if [ "${{ github.ref }}" == "refs/heads/main" ]; then + if [ "$GIT_REF" == "refs/heads/main" ]; then LATEST_TAG="latest-${VARIANT}" create_manifest "$LATEST_TAG" "main-${VARIANT}" MANIFEST_TAGS+=("$LATEST_TAG") @@ -731,13 +745,18 @@ jobs: steps: - name: Generate PR description from build summary id: generate_description + env: + EVENT_NAME: ${{ github.event_name }} + PR_NUMBER: ${{ github.event.number }} + RUN_ATTEMPT: ${{ github.run_attempt }} + BUILD_SUMMARY_JSON: ${{ needs.consolidate-build-info.outputs.build_summary }} run: | - echo "Event: ${{ github.event_name }}" - echo "PR number: ${{ github.event.number }}" - echo "Run attempt: ${{ github.run_attempt }}" + echo "Event: $EVENT_NAME" + echo "PR number: $PR_NUMBER" + echo "Run attempt: $RUN_ATTEMPT" # Parse the build summary JSON - BUILD_SUMMARY='${{ needs.consolidate-build-info.outputs.build_summary }}' + BUILD_SUMMARY="$BUILD_SUMMARY_JSON" echo "Build summary received:" echo "$BUILD_SUMMARY" | jq . diff --git a/.github/workflows/todo-management.yml b/.github/workflows/todo-management.yml index 43f006050f..4d1f9903d6 100644 --- a/.github/workflows/todo-management.yml +++ b/.github/workflows/todo-management.yml @@ -71,11 +71,14 @@ jobs: - name: Scan for TODOs id: scan + env: + TODO_IDENTIFIER_INPUT: ${{ github.event.inputs.todo_identifier || 'TODO(openhands)' }} + MAX_TODOS_INPUT: ${{ github.event.inputs.max_todos || '3' }} run: | echo "Scanning for TODO comments..." # Run the scanner and capture output - TODO_IDENTIFIER="${{ github.event.inputs.todo_identifier || 'TODO(openhands)' }}" + TODO_IDENTIFIER="$TODO_IDENTIFIER_INPUT" python /tmp/scanner.py . --identifier "$TODO_IDENTIFIER" > todos.json # Count TODOs @@ -84,7 +87,7 @@ jobs: echo "Found $TODO_COUNT $TODO_IDENTIFIER items" # Limit the number of TODOs to process - MAX_TODOS="${{ github.event.inputs.max_todos || '3' }}" + MAX_TODOS="$MAX_TODOS_INPUT" if [ "$TODO_COUNT" -gt "$MAX_TODOS" ]; then echo "Limiting to first $MAX_TODOS TODOs" python -c " @@ -175,6 +178,7 @@ jobs: TODO_FILE: ${{ matrix.todo.file }} TODO_LINE: ${{ matrix.todo.line }} TODO_DESCRIPTION: ${{ matrix.todo.description }} + BASE_REF: ${{ github.ref_name }} PYTHONPATH: '' run: | echo "Processing TODO: $TODO_DESCRIPTION" @@ -291,7 +295,7 @@ jobs: \"title\": \"$PR_TITLE\", \"body\": \"$PR_BODY\", \"head\": \"$BRANCH_NAME\", - \"base\": \"${{ github.ref_name }}\" + \"base\": \"$BASE_REF\" }" summary: @@ -300,11 +304,13 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Generate Summary + env: + TODO_COUNT_OUTPUT: ${{ needs.scan-todos.outputs.todo-count || '0' }} run: | echo "# 🤖 TODO Management Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - TODO_COUNT="${{ needs.scan-todos.outputs.todo-count || '0' }}" + TODO_COUNT="$TODO_COUNT_OUTPUT" echo "**TODOs Found:** $TODO_COUNT" >> $GITHUB_STEP_SUMMARY if [ "$TODO_COUNT" -gt 0 ]; then diff --git a/.github/workflows/version-bump-prs.yml b/.github/workflows/version-bump-prs.yml index ac42a50518..65b8bbc62d 100644 --- a/.github/workflows/version-bump-prs.yml +++ b/.github/workflows/version-bump-prs.yml @@ -23,8 +23,10 @@ jobs: - name: Get version from release or input id: get_version + env: + VERSION_INPUT: ${{ github.event.inputs.version }} run: | - VERSION="${{ github.event.inputs.version }}" + VERSION="$VERSION_INPUT" echo "version=$VERSION" >> $GITHUB_OUTPUT echo "📦 Version: $VERSION" From 7fd69bd678a921fdd4ff1123fbe92f58aa647b2c Mon Sep 17 00:00:00 2001 From: enyst Date: Sun, 24 May 2026 00:19:16 +0000 Subject: [PATCH 2/8] Address workflow hardening review feedback Co-authored-by: openhands --- .github/workflows/prepare-release.yml | 2 +- .github/workflows/server.yml | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 64b54d7505..2101779743 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -53,7 +53,7 @@ jobs: INPUTS_VERSION: ${{ inputs.version }} run: | echo "🔧 Setting version to $INPUTS_VERSION" - make set-package-version version=$INPUTS_VERSION + make set-package-version version="$INPUTS_VERSION" - name: Update sdk_ref default in run-eval workflow env: diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index 0bf8f71e8f..3cba962c37 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -353,13 +353,14 @@ jobs: id: prep env: GITHUB_REF: ${{ github.ref }} + ARCH: ${{ matrix.arch }} run: | uv sync --frozen # Generate build context and tags with arch suffix # build.py now handles architecture tagging internally via --arch flag # Add --versioned-tag when triggered by a git tag (e.g., v1.0.0) - BUILD_CMD="uv run ./openhands-agent-server/openhands/agent_server/docker/build.py --build-ctx-only --arch ${{ matrix.arch }}" + BUILD_CMD="uv run ./openhands-agent-server/openhands/agent_server/docker/build.py --build-ctx-only --arch "$ARCH"" if [[ "$GITHUB_REF" == refs/tags/* ]]; then BUILD_CMD="$BUILD_CMD --versioned-tag" fi @@ -432,13 +433,16 @@ jobs: SHORT_SHA: ${{ steps.prep.outputs.short_sha }} TAGS: ${{ steps.prep.outputs.tags }} VERSIONED_TAGS_CSV: ${{ steps.prep.outputs.versioned_tags_csv }} + VARIANT: ${{ matrix.variant }} + ARCH: ${{ matrix.arch }} + BASE_IMAGE: ${{ matrix.base_image }} run: | mkdir -p build-info - cat > "build-info/${{ matrix.variant }}-${{ matrix.arch }}.json" << EOF + cat > "build-info/${VARIANT}-${ARCH}.json" << EOF { - "variant": "${{ matrix.variant }}", - "arch": "${{ matrix.arch }}", - "base_image": "${{ matrix.base_image }}", + "variant": "$VARIANT", + "arch": "$ARCH", + "base_image": "$BASE_IMAGE", "image": "$IMAGE", "short_sha": "$SHORT_SHA", "tags": "$TAGS", @@ -500,8 +504,8 @@ jobs: env: SHORT_SHA: ${{ steps.get_sha.outputs.short_sha }} GIT_REF: ${{ github.ref }} + VARIANT: ${{ matrix.variant }} run: | - VARIANT=${{ matrix.variant }} AMD64_TAGS_CSV=$(jq -r '.tags' build-info/${VARIANT}-amd64.json) declare -A SEEN_MANIFEST_TAGS=() MANIFEST_TAGS=() From 5cb5062e614c816f766d3b5e86a0934bfa086c9a Mon Sep 17 00:00:00 2001 From: enyst Date: Sun, 24 May 2026 00:24:12 +0000 Subject: [PATCH 3/8] Harden example workflow shell inputs Co-authored-by: openhands --- .../03_todo_management/workflow.yml | 14 +++++++---- .../04_datadog_debugging/workflow.yml | 23 ++++++++++++++----- .../05_posthog_debugging/workflow.yml | 23 ++++++++++++++----- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/examples/03_github_workflows/03_todo_management/workflow.yml b/examples/03_github_workflows/03_todo_management/workflow.yml index b42f090b41..8b9e185307 100644 --- a/examples/03_github_workflows/03_todo_management/workflow.yml +++ b/examples/03_github_workflows/03_todo_management/workflow.yml @@ -73,11 +73,14 @@ jobs: - name: Scan for TODOs id: scan + env: + GITHUB_EVENT_INPUTS_TODO_IDENTIFIER: ${{ github.event.inputs.todo_identifier || 'TODO(openhands)' }} + GITHUB_EVENT_INPUTS_MAX_TODOS: ${{ github.event.inputs.max_todos || '3' }} run: | echo "Scanning for TODO comments..." # Run the scanner and capture output - TODO_IDENTIFIER="${{ github.event.inputs.todo_identifier || 'TODO(openhands)' }}" + TODO_IDENTIFIER="$GITHUB_EVENT_INPUTS_TODO_IDENTIFIER" python /tmp/scanner.py . --identifier "$TODO_IDENTIFIER" > todos.json # Count TODOs @@ -86,7 +89,7 @@ jobs: echo "Found $TODO_COUNT $TODO_IDENTIFIER items" # Limit the number of TODOs to process - MAX_TODOS="${{ github.event.inputs.max_todos || '3' }}" + MAX_TODOS="$GITHUB_EVENT_INPUTS_MAX_TODOS" if [ "$TODO_COUNT" -gt "$MAX_TODOS" ]; then echo "Limiting to first $MAX_TODOS TODOs" python -c " @@ -178,6 +181,7 @@ jobs: TODO_LINE: ${{ matrix.todo.line }} TODO_DESCRIPTION: ${{ matrix.todo.description }} PYTHONPATH: '' + GITHUB_REF_NAME: ${{ github.ref_name }} run: | echo "Processing TODO: $TODO_DESCRIPTION" echo "File: $TODO_FILE:$TODO_LINE" @@ -293,7 +297,7 @@ jobs: \"title\": \"$PR_TITLE\", \"body\": \"$PR_BODY\", \"head\": \"$BRANCH_NAME\", - \"base\": \"${{ github.ref_name }}\" + \"base\": \"$GITHUB_REF_NAME\" }" summary: @@ -302,11 +306,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Generate Summary + env: + NEEDS_SCAN_TODOS_OUTPUTS_TODO_COUNT: ${{ needs.scan-todos.outputs.todo-count || '0' }} run: | echo "# 🤖 TODO Management Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - TODO_COUNT="${{ needs.scan-todos.outputs.todo-count || '0' }}" + TODO_COUNT="$NEEDS_SCAN_TODOS_OUTPUTS_TODO_COUNT" echo "**TODOs Found:** $TODO_COUNT" >> $GITHUB_STEP_SUMMARY if [ "$TODO_COUNT" -gt 0 ]; then diff --git a/examples/03_github_workflows/04_datadog_debugging/workflow.yml b/examples/03_github_workflows/04_datadog_debugging/workflow.yml index 80e2d1b31f..6779784758 100644 --- a/examples/03_github_workflows/04_datadog_debugging/workflow.yml +++ b/examples/03_github_workflows/04_datadog_debugging/workflow.yml @@ -89,17 +89,28 @@ jobs: LLM_MODEL: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PYTHONPATH: '' + INPUTS_QUERY_TYPE: ${{ inputs.query_type }} + INPUTS_DATADOG_QUERY: ${{ inputs.datadog_query }} + INPUTS_REPO_LIST: ${{ inputs.repo_list }} + INPUTS_ISSUE_REPO: ${{ inputs.issue_repo }} + INPUTS_ISSUE_PARENT: ${{ inputs.issue_parent }} + INPUTS_ISSUE_PREFIX: ${{ inputs.issue_prefix }} run: | mkdir -p /tmp/datadog-debug cd /tmp/datadog-debug-script + ISSUE_PARENT_ARG=() + if [ -n "$INPUTS_ISSUE_PARENT" ]; then + ISSUE_PARENT_ARG=(--issue-parent "$INPUTS_ISSUE_PARENT") + fi + python datadog_debugging.py \ - --query-type "${{ inputs.query_type }}" \ - --query "${{ inputs.datadog_query }}" \ - --repos "${{ inputs.repo_list }}" \ + --query-type "$INPUTS_QUERY_TYPE" \ + --query "$INPUTS_DATADOG_QUERY" \ + --repos "$INPUTS_REPO_LIST" \ --working-dir "/tmp/datadog-debug" \ - --issue-repo "${{ inputs.issue_repo }}" \ - --issue-parent "${{ inputs.issue_parent }}" \ - --issue-prefix "${{ inputs.issue_prefix }}" + --issue-repo "$INPUTS_ISSUE_REPO" \ + "${ISSUE_PARENT_ARG[@]}" \ + --issue-prefix "$INPUTS_ISSUE_PREFIX" - name: Upload debugging artifacts if: always() diff --git a/examples/03_github_workflows/05_posthog_debugging/workflow.yml b/examples/03_github_workflows/05_posthog_debugging/workflow.yml index 0464fa603d..b99c0a0c4c 100644 --- a/examples/03_github_workflows/05_posthog_debugging/workflow.yml +++ b/examples/03_github_workflows/05_posthog_debugging/workflow.yml @@ -83,15 +83,26 @@ jobs: LLM_API_KEY: ${{ secrets.LLM_API_KEY }} LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} LLM_MODEL: ${{ inputs.llm_model }} + INPUTS_QUERY_TYPE: ${{ inputs.query_type }} + INPUTS_POSTHOG_QUERY: ${{ inputs.posthog_query }} + INPUTS_REPO_LIST: ${{ inputs.repo_list }} + INPUTS_ISSUE_REPO: ${{ inputs.issue_repo }} + INPUTS_ISSUE_PARENT: ${{ inputs.issue_parent }} + INPUTS_ISSUE_PREFIX: ${{ inputs.issue_prefix }} run: | cd posthog_debug_tools + ISSUE_PARENT_ARG=() + if [ -n "$INPUTS_ISSUE_PARENT" ]; then + ISSUE_PARENT_ARG=(--issue-parent "$INPUTS_ISSUE_PARENT") + fi + python posthog_debugging.py \ - --query-type "${{ inputs.query_type }}" \ - --query "${{ inputs.posthog_query }}" \ - --repos "${{ inputs.repo_list }}" \ - --issue-repo "${{ inputs.issue_repo }}" \ - ${{ inputs.issue_parent && format('--issue-parent "{0}"', inputs.issue_parent) || '' }} \ - --issue-prefix "${{ inputs.issue_prefix }}" \ + --query-type "$INPUTS_QUERY_TYPE" \ + --query "$INPUTS_POSTHOG_QUERY" \ + --repos "$INPUTS_REPO_LIST" \ + --issue-repo "$INPUTS_ISSUE_REPO" \ + "${ISSUE_PARENT_ARG[@]}" \ + --issue-prefix "$INPUTS_ISSUE_PREFIX" \ --working-dir ./workspace - name: Upload debugging artifacts From 39748dea742c06caee12d83b7abda73285adf624 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 24 May 2026 06:45:05 +0000 Subject: [PATCH 4/8] Simplify workflow hardening scope Co-authored-by: openhands --- .github/workflows/api-compliance-runner.yml | 3 +- .github/workflows/condenser-runner.yml | 3 +- .github/workflows/create-release.yml | 3 +- .github/workflows/integration-runner.yml | 16 ++--- .github/workflows/pypi-release.yml | 1 - .github/workflows/release-binaries.yml | 1 - .github/workflows/run-examples.yml | 1 - .github/workflows/server.yml | 59 +++++++------------ .github/workflows/todo-management.yml | 4 +- .../03_todo_management/workflow.yml | 4 +- 10 files changed, 32 insertions(+), 63 deletions(-) diff --git a/.github/workflows/api-compliance-runner.yml b/.github/workflows/api-compliance-runner.yml index d51e7b2d75..9b8bbcdb49 100644 --- a/.github/workflows/api-compliance-runner.yml +++ b/.github/workflows/api-compliance-runner.yml @@ -50,12 +50,11 @@ jobs: - name: Determine test parameters id: params env: - EVENT_NAME: ${{ github.event_name }} PATTERNS_INPUT: ${{ github.event.inputs.patterns }} MODELS_INPUT: ${{ github.event.inputs.models }} run: | # Use input values or defaults - if [ "$EVENT_NAME" = "workflow_dispatch" ]; then + if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then PATTERNS="$PATTERNS_INPUT" MODELS="$MODELS_INPUT" else diff --git a/.github/workflows/condenser-runner.yml b/.github/workflows/condenser-runner.yml index d708d90726..ceeab809e4 100644 --- a/.github/workflows/condenser-runner.yml +++ b/.github/workflows/condenser-runner.yml @@ -230,7 +230,6 @@ jobs: if: github.event_name == 'pull_request_target' env: GH_TOKEN: ${{ github.token }} - GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} run: | # Add header to clarify these are non-blocking tests echo "## Condenser Test Results (Non-Blocking)" > final_report.md @@ -242,4 +241,4 @@ jobs: # Sanitize @OpenHands mentions to prevent self-mention loops COMMENT_BODY=$(uv run python -c "from openhands.sdk.utils.github import sanitize_openhands_mentions; import sys; print(sanitize_openhands_mentions(sys.stdin.read()), end='')" < final_report.md) # Use GitHub CLI to create comment with explicit PR number - echo "$COMMENT_BODY" | gh pr comment "$GITHUB_EVENT_PULL_REQUEST_NUMBER" --body-file - + echo "$COMMENT_BODY" | gh pr comment ${{ github.event.pull_request.number }} --body-file - diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index f2c6a8d8c9..efed7dd209 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -146,7 +146,6 @@ jobs: PREAMBLE_PATH: release-note-preamble.md VERSION: ${{ steps.version.outputs.version }} PREV_TAG: ${{ steps.prev_tag.outputs.prev_tag }} - GITHUB_EVENT_PULL_REQUEST_MERGE_COMMIT_SHA: ${{ github.event.pull_request.merge_commit_sha }} run: | NOTES_START_FLAG=() if [ -n "$PREV_TAG" ]; then @@ -160,7 +159,7 @@ jobs: gh release create "v${VERSION}" \ --repo "${{ github.repository }}" \ - --target "$GITHUB_EVENT_PULL_REQUEST_MERGE_COMMIT_SHA" \ + --target "${{ github.event.pull_request.merge_commit_sha }}" \ --title "v${VERSION}" \ --generate-notes \ "${PREAMBLE_FLAG[@]}" \ diff --git a/.github/workflows/integration-runner.yml b/.github/workflows/integration-runner.yml index 3341b804b4..52639aada0 100644 --- a/.github/workflows/integration-runner.yml +++ b/.github/workflows/integration-runner.yml @@ -129,7 +129,6 @@ jobs: id: resolve-issue env: ISSUE_NUMBER_INPUT: ${{ github.event.inputs.issue_number || '' }} - PR_NUMBER: ${{ github.event.pull_request.number }} run: | # Priority: explicit input > PR number from label trigger if [ -n "$ISSUE_NUMBER_INPUT" ]; then @@ -261,18 +260,16 @@ jobs: # Run integration test evaluation - name: Determine test selection env: - EVENT_NAME: ${{ github.event_name }} - LABEL_NAME: ${{ github.event.label.name }} TEST_TYPE_INPUT: ${{ github.event.inputs.test_type }} run: | TEST_TYPE_ARGS="" - if [ "$EVENT_NAME" = "pull_request_target" ] && [ "$LABEL_NAME" = "behavior-test" ]; then + if [ "$GITHUB_EVENT_NAME" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "behavior-test" ]; then TEST_TYPE_ARGS="--test-type behavior" echo "behavior-test label detected; running behavior tests only." - elif [ "$EVENT_NAME" = "pull_request_target" ] && [ "$LABEL_NAME" = "integration-test" ]; then + elif [ "$GITHUB_EVENT_NAME" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "integration-test" ]; then TEST_TYPE_ARGS="--test-type integration" echo "integration-test label detected; running integration tests only." - elif [ "$EVENT_NAME" = "workflow_dispatch" ]; then + elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then test_type="$TEST_TYPE_INPUT" case "$test_type" in behavior) @@ -290,7 +287,7 @@ jobs: echo "workflow_dispatch provided unknown test_type '$test_type'; defaulting to full suite." ;; esac - elif [ "$EVENT_NAME" = "schedule" ]; then + elif [ "$GITHUB_EVENT_NAME" = "schedule" ]; then TEST_TYPE_ARGS="--test-type integration" echo "Scheduled run; running integration tests only." else @@ -419,8 +416,6 @@ jobs: - name: Consolidate test results env: - EVENT_NAME: ${{ github.event_name }} - PR_NUMBER: ${{ github.event.pull_request.number }} MANUAL_REASON: ${{ github.event.inputs.reason }} COMMIT_SHA: ${{ github.sha }} PYTHONPATH: ${{ github.workspace }} @@ -451,10 +446,9 @@ jobs: # Sanitize @OpenHands mentions to prevent self-mention loops COMMENT_BODY=$(uv run python -c "from openhands.sdk.utils.github import sanitize_openhands_mentions; import sys; print(sanitize_openhands_mentions(sys.stdin.read()), end='')" < consolidated_report.md) # Use GitHub CLI to create comment with explicit PR number - echo "$COMMENT_BODY" | gh pr comment "$PR_NUMBER" --body-file - + echo "$COMMENT_BODY" | gh pr comment ${{ github.event.pull_request.number }} --body-file - env: GH_TOKEN: ${{ github.token }} - PR_NUMBER: ${{ github.event.pull_request.number }} - name: Comment on specified issue/PR (workflow_dispatch) if: github.event_name == 'workflow_dispatch' && needs.setup-matrix.outputs.issue_number != '' diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index 3af4256ae8..2acf687f88 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -29,7 +29,6 @@ jobs: - name: Extract version from release tag id: extract_version env: - GITHUB_EVENT_NAME: ${{ github.event_name }} GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }} run: | # Get version from release tag (e.g., v1.2.3 -> 1.2.3) diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index f22b520f9a..b56d92a4a7 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -39,7 +39,6 @@ jobs: - id: resolve shell: bash env: - GITHUB_EVENT_NAME: ${{ github.event_name }} GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }} INPUTS_RELEASE_TAG: ${{ inputs.release_tag }} run: | diff --git a/.github/workflows/run-examples.yml b/.github/workflows/run-examples.yml index 4b2224a231..46cc519483 100644 --- a/.github/workflows/run-examples.yml +++ b/.github/workflows/run-examples.yml @@ -83,7 +83,6 @@ jobs: ANTHROPIC_API_KEY: ${{ secrets.LLM_API_KEY }} OPENAI_BASE_URL: https://llm-proxy.app.all-hands.dev OPENAI_API_KEY: ${{ secrets.LLM_API_KEY }} - GITHUB_EVENT_NAME: ${{ github.event_name }} run: | RESULTS_DIR=".example-test-results" REPORT_PATH="examples_report.md" diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index 3cba962c37..a4ba2219e9 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -353,14 +353,13 @@ jobs: id: prep env: GITHUB_REF: ${{ github.ref }} - ARCH: ${{ matrix.arch }} run: | uv sync --frozen # Generate build context and tags with arch suffix # build.py now handles architecture tagging internally via --arch flag # Add --versioned-tag when triggered by a git tag (e.g., v1.0.0) - BUILD_CMD="uv run ./openhands-agent-server/openhands/agent_server/docker/build.py --build-ctx-only --arch "$ARCH"" + BUILD_CMD="uv run ./openhands-agent-server/openhands/agent_server/docker/build.py --build-ctx-only --arch ${{ matrix.arch }}" if [[ "$GITHUB_REF" == refs/tags/* ]]; then BUILD_CMD="$BUILD_CMD --versioned-tag" fi @@ -415,39 +414,28 @@ jobs: fi - name: Summary (${{ matrix.variant }}-${{ matrix.arch }}) - outputs - env: - SHORT_SHA: ${{ steps.prep.outputs.short_sha }} - TAGS: ${{ steps.prep.outputs.tags }} - BUILD_DIGEST: ${{ steps.build.outputs.digest }} run: | - echo "Image: $IMAGE" - echo "Variant: $VARIANT" - echo "Architecture: $ARCH" - echo "Platform: $PLATFORM" - echo "Short SHA: $SHORT_SHA" - echo "Tags: $TAGS" - echo "Build digest: $BUILD_DIGEST" + echo "Image: ${{ env.IMAGE }}" + echo "Variant: ${{ env.VARIANT }}" + echo "Architecture: ${{ env.ARCH }}" + echo "Platform: ${{ env.PLATFORM }}" + echo "Short SHA: ${{ steps.prep.outputs.short_sha }}" + echo "Tags: ${{ steps.prep.outputs.tags }}" + echo "Build digest: ${{ steps.build.outputs.digest }}" - name: Save build info for consolidation - env: - SHORT_SHA: ${{ steps.prep.outputs.short_sha }} - TAGS: ${{ steps.prep.outputs.tags }} - VERSIONED_TAGS_CSV: ${{ steps.prep.outputs.versioned_tags_csv }} - VARIANT: ${{ matrix.variant }} - ARCH: ${{ matrix.arch }} - BASE_IMAGE: ${{ matrix.base_image }} run: | mkdir -p build-info - cat > "build-info/${VARIANT}-${ARCH}.json" << EOF + cat > "build-info/${{ matrix.variant }}-${{ matrix.arch }}.json" << EOF { - "variant": "$VARIANT", - "arch": "$ARCH", - "base_image": "$BASE_IMAGE", - "image": "$IMAGE", - "short_sha": "$SHORT_SHA", - "tags": "$TAGS", - "versioned_tags_csv": "$VERSIONED_TAGS_CSV", - "platform": "$PLATFORM" + "variant": "${{ matrix.variant }}", + "arch": "${{ matrix.arch }}", + "base_image": "${{ matrix.base_image }}", + "image": "${{ env.IMAGE }}", + "short_sha": "${{ steps.prep.outputs.short_sha }}", + "tags": "${{ steps.prep.outputs.tags }}", + "versioned_tags_csv": "${{ steps.prep.outputs.versioned_tags_csv }}", + "platform": "${{ env.PLATFORM }}" } EOF @@ -502,10 +490,10 @@ jobs: - name: Create and push multi-arch manifest for ${{ matrix.variant }} id: create_manifest env: - SHORT_SHA: ${{ steps.get_sha.outputs.short_sha }} GIT_REF: ${{ github.ref }} - VARIANT: ${{ matrix.variant }} run: | + SHORT_SHA=${{ steps.get_sha.outputs.short_sha }} + VARIANT=${{ matrix.variant }} AMD64_TAGS_CSV=$(jq -r '.tags' build-info/${VARIANT}-amd64.json) declare -A SEEN_MANIFEST_TAGS=() MANIFEST_TAGS=() @@ -750,14 +738,11 @@ jobs: - name: Generate PR description from build summary id: generate_description env: - EVENT_NAME: ${{ github.event_name }} - PR_NUMBER: ${{ github.event.number }} - RUN_ATTEMPT: ${{ github.run_attempt }} BUILD_SUMMARY_JSON: ${{ needs.consolidate-build-info.outputs.build_summary }} run: | - echo "Event: $EVENT_NAME" - echo "PR number: $PR_NUMBER" - echo "Run attempt: $RUN_ATTEMPT" + echo "Event: $GITHUB_EVENT_NAME" + echo "PR number: ${{ github.event.number }}" + echo "Run attempt: ${{ github.run_attempt }}" # Parse the build summary JSON BUILD_SUMMARY="$BUILD_SUMMARY_JSON" diff --git a/.github/workflows/todo-management.yml b/.github/workflows/todo-management.yml index 4d1f9903d6..0a5f7bee0e 100644 --- a/.github/workflows/todo-management.yml +++ b/.github/workflows/todo-management.yml @@ -304,13 +304,11 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Generate Summary - env: - TODO_COUNT_OUTPUT: ${{ needs.scan-todos.outputs.todo-count || '0' }} run: | echo "# 🤖 TODO Management Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - TODO_COUNT="$TODO_COUNT_OUTPUT" + TODO_COUNT="${{ needs.scan-todos.outputs.todo-count || '0' }}" echo "**TODOs Found:** $TODO_COUNT" >> $GITHUB_STEP_SUMMARY if [ "$TODO_COUNT" -gt 0 ]; then diff --git a/examples/03_github_workflows/03_todo_management/workflow.yml b/examples/03_github_workflows/03_todo_management/workflow.yml index 8b9e185307..44548c85dd 100644 --- a/examples/03_github_workflows/03_todo_management/workflow.yml +++ b/examples/03_github_workflows/03_todo_management/workflow.yml @@ -306,13 +306,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Generate Summary - env: - NEEDS_SCAN_TODOS_OUTPUTS_TODO_COUNT: ${{ needs.scan-todos.outputs.todo-count || '0' }} run: | echo "# 🤖 TODO Management Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - TODO_COUNT="$NEEDS_SCAN_TODOS_OUTPUTS_TODO_COUNT" + TODO_COUNT="${{ needs.scan-todos.outputs.todo-count || '0' }}" echo "**TODOs Found:** $TODO_COUNT" >> $GITHUB_STEP_SUMMARY if [ "$TODO_COUNT" -gt 0 ]; then From 3dd818bbba07529ca47eec86b828bb085f557670 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 24 May 2026 13:47:32 +0000 Subject: [PATCH 5/8] Keep GitHub-controlled event names direct Co-authored-by: openhands --- .github/workflows/api-compliance-runner.yml | 2 +- .github/workflows/integration-runner.yml | 8 ++++---- .github/workflows/pypi-release.yml | 2 +- .github/workflows/release-binaries.yml | 8 ++++---- .github/workflows/run-examples.yml | 4 ++-- .github/workflows/server.yml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/api-compliance-runner.yml b/.github/workflows/api-compliance-runner.yml index 9b8bbcdb49..8c2586da47 100644 --- a/.github/workflows/api-compliance-runner.yml +++ b/.github/workflows/api-compliance-runner.yml @@ -54,7 +54,7 @@ jobs: MODELS_INPUT: ${{ github.event.inputs.models }} run: | # Use input values or defaults - if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then PATTERNS="$PATTERNS_INPUT" MODELS="$MODELS_INPUT" else diff --git a/.github/workflows/integration-runner.yml b/.github/workflows/integration-runner.yml index 52639aada0..bc6066edd3 100644 --- a/.github/workflows/integration-runner.yml +++ b/.github/workflows/integration-runner.yml @@ -263,13 +263,13 @@ jobs: TEST_TYPE_INPUT: ${{ github.event.inputs.test_type }} run: | TEST_TYPE_ARGS="" - if [ "$GITHUB_EVENT_NAME" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "behavior-test" ]; then + if [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "behavior-test" ]; then TEST_TYPE_ARGS="--test-type behavior" echo "behavior-test label detected; running behavior tests only." - elif [ "$GITHUB_EVENT_NAME" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "integration-test" ]; then + elif [ "${{ github.event_name }}" = "pull_request_target" ] && [ "${{ github.event.label.name }}" = "integration-test" ]; then TEST_TYPE_ARGS="--test-type integration" echo "integration-test label detected; running integration tests only." - elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then + elif [ "${{ github.event_name }}" = "workflow_dispatch" ]; then test_type="$TEST_TYPE_INPUT" case "$test_type" in behavior) @@ -287,7 +287,7 @@ jobs: echo "workflow_dispatch provided unknown test_type '$test_type'; defaulting to full suite." ;; esac - elif [ "$GITHUB_EVENT_NAME" = "schedule" ]; then + elif [ "${{ github.event_name }}" = "schedule" ]; then TEST_TYPE_ARGS="--test-type integration" echo "Scheduled run; running integration tests only." else diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index 2acf687f88..319b71af4b 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -32,7 +32,7 @@ jobs: GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }} run: | # Get version from release tag (e.g., v1.2.3 -> 1.2.3) - if [[ "$GITHUB_EVENT_NAME" == "release" ]]; then + if [[ "${{ github.event_name }}" == "release" ]]; then VERSION="$GITHUB_EVENT_RELEASE_TAG_NAME" VERSION="${VERSION#v}" # Remove 'v' prefix if present else diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index b56d92a4a7..71617a0999 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -43,17 +43,17 @@ jobs: INPUTS_RELEASE_TAG: ${{ inputs.release_tag }} run: | set -euo pipefail - if [[ "$GITHUB_EVENT_NAME" == "release" ]]; then + if [[ "${{ github.event_name }}" == "release" ]]; then TAG="$GITHUB_EVENT_RELEASE_TAG_NAME" VERSION="${TAG#v}" - elif [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then + elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then TAG="$INPUTS_RELEASE_TAG" VERSION="${TAG#v}" - elif [[ "$GITHUB_EVENT_NAME" == "push" ]]; then + elif [[ "${{ github.event_name }}" == "push" ]]; then TAG="" VERSION="${GITHUB_SHA::7}" else - echo "ERROR: unsupported event '$GITHUB_EVENT_NAME'" + echo "ERROR: unsupported event '${{ github.event_name }}'" exit 1 fi diff --git a/.github/workflows/run-examples.yml b/.github/workflows/run-examples.yml index 46cc519483..f6c1a130e0 100644 --- a/.github/workflows/run-examples.yml +++ b/.github/workflows/run-examples.yml @@ -135,7 +135,7 @@ jobs: API_URL="" COMMENT_ID="" - if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then + if [ "${{ github.event_name }}" = "pull_request" ]; then API_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/issues/${PR_NUMBER}/comments" initial_comment="## 🔄 Running Examples with \`${LLM_MODEL}\`" initial_comment+=$'\n\n' @@ -163,7 +163,7 @@ jobs: COMMENT_BODY="$(cat "$REPORT_PATH")" echo "$COMMENT_BODY" - if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then + if [ "${{ github.event_name }}" = "pull_request" ]; then echo "Publishing PR comment..." update_comment "$COMMENT_BODY" fi diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index a4ba2219e9..c125567d86 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -740,7 +740,7 @@ jobs: env: BUILD_SUMMARY_JSON: ${{ needs.consolidate-build-info.outputs.build_summary }} run: | - echo "Event: $GITHUB_EVENT_NAME" + echo "Event: ${{ github.event_name }}" echo "PR number: ${{ github.event.number }}" echo "Run attempt: ${{ github.run_attempt }}" From 24441136f7ad7ec9229650d1c94087b32b5f9919 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 24 May 2026 20:13:53 +0000 Subject: [PATCH 6/8] Harden workflow input output handling Co-authored-by: openhands --- .github/workflows/integration-runner.yml | 5 +++-- .github/workflows/version-bump-prs.yml | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration-runner.yml b/.github/workflows/integration-runner.yml index bc6066edd3..cc1d54c378 100644 --- a/.github/workflows/integration-runner.yml +++ b/.github/workflows/integration-runner.yml @@ -88,13 +88,14 @@ jobs: # Resolve model configs using resolve_model_config.py # Transform output to matrix format for integration tests - MATRIX=$(python3 << EOF + MATRIX=$(python3 << 'EOF' import json + import os import sys sys.path.insert(0, '.github/run-eval') from resolve_model_config import MODELS - model_ids = "$MODEL_IDS".split(",") + model_ids = os.environ["MODEL_IDS"].split(",") model_ids = [m.strip() for m in model_ids if m.strip()] matrix = [] diff --git a/.github/workflows/version-bump-prs.yml b/.github/workflows/version-bump-prs.yml index 65b8bbc62d..50ce3549a3 100644 --- a/.github/workflows/version-bump-prs.yml +++ b/.github/workflows/version-bump-prs.yml @@ -27,7 +27,11 @@ jobs: VERSION_INPUT: ${{ github.event.inputs.version }} run: | VERSION="$VERSION_INPUT" - echo "version=$VERSION" >> $GITHUB_OUTPUT + if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "❌ Invalid version format. Expected: X.Y.Z (e.g., 1.2.3)" + exit 1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "📦 Version: $VERSION" - name: Validate version From d8c12692ff871bf302d41c908a6df5ce6d754dd3 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 24 May 2026 20:36:36 +0000 Subject: [PATCH 7/8] Address workflow review hardening gaps Co-authored-by: openhands --- .github/workflows/api-compliance-runner.yml | 7 ++- .github/workflows/integration-runner.yml | 2 + .github/workflows/server.yml | 53 ++++++++++++------- .github/workflows/todo-management.yml | 14 ++--- .../03_todo_management/workflow.yml | 14 ++--- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/.github/workflows/api-compliance-runner.yml b/.github/workflows/api-compliance-runner.yml index 8c2586da47..ea728d566d 100644 --- a/.github/workflows/api-compliance-runner.yml +++ b/.github/workflows/api-compliance-runner.yml @@ -73,7 +73,12 @@ jobs: ARGS="$ARGS --models $DEFAULT_MODELS" fi - echo "args=$ARGS" >> $GITHUB_OUTPUT + DELIMITER="args_$(openssl rand -hex 16)" + { + echo "args<<$DELIMITER" + printf '%s\n' "$ARGS" + echo "$DELIMITER" + } >> "$GITHUB_OUTPUT" - name: Run API compliance tests id: compliance diff --git a/.github/workflows/integration-runner.yml b/.github/workflows/integration-runner.yml index cc1d54c378..9da76653bb 100644 --- a/.github/workflows/integration-runner.yml +++ b/.github/workflows/integration-runner.yml @@ -86,6 +86,8 @@ jobs: echo "Using specified model_ids: $MODEL_IDS" fi + export MODEL_IDS + # Resolve model configs using resolve_model_config.py # Transform output to matrix format for integration tests MATRIX=$(python3 << 'EOF' diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index c125567d86..ffcbcb1f09 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -414,30 +414,45 @@ jobs: fi - name: Summary (${{ matrix.variant }}-${{ matrix.arch }}) - outputs + env: + SHORT_SHA: ${{ steps.prep.outputs.short_sha }} + TAGS: ${{ steps.prep.outputs.tags }} + BUILD_DIGEST: ${{ steps.build.outputs.digest }} run: | - echo "Image: ${{ env.IMAGE }}" - echo "Variant: ${{ env.VARIANT }}" - echo "Architecture: ${{ env.ARCH }}" - echo "Platform: ${{ env.PLATFORM }}" - echo "Short SHA: ${{ steps.prep.outputs.short_sha }}" - echo "Tags: ${{ steps.prep.outputs.tags }}" - echo "Build digest: ${{ steps.build.outputs.digest }}" + echo "Image: $IMAGE" + echo "Variant: $VARIANT" + echo "Architecture: $ARCH" + echo "Platform: $PLATFORM" + echo "Short SHA: $SHORT_SHA" + echo "Tags: $TAGS" + echo "Build digest: $BUILD_DIGEST" - name: Save build info for consolidation + env: + SHORT_SHA: ${{ steps.prep.outputs.short_sha }} + TAGS: ${{ steps.prep.outputs.tags }} + VERSIONED_TAGS_CSV: ${{ steps.prep.outputs.versioned_tags_csv }} run: | mkdir -p build-info - cat > "build-info/${{ matrix.variant }}-${{ matrix.arch }}.json" << EOF - { - "variant": "${{ matrix.variant }}", - "arch": "${{ matrix.arch }}", - "base_image": "${{ matrix.base_image }}", - "image": "${{ env.IMAGE }}", - "short_sha": "${{ steps.prep.outputs.short_sha }}", - "tags": "${{ steps.prep.outputs.tags }}", - "versioned_tags_csv": "${{ steps.prep.outputs.versioned_tags_csv }}", - "platform": "${{ env.PLATFORM }}" - } - EOF + jq -n \ + --arg variant "$VARIANT" \ + --arg arch "$ARCH" \ + --arg base_image "$BASE_IMAGE" \ + --arg image "$IMAGE" \ + --arg short_sha "$SHORT_SHA" \ + --arg tags "$TAGS" \ + --arg versioned_tags_csv "$VERSIONED_TAGS_CSV" \ + --arg platform "$PLATFORM" \ + '{ + variant: $variant, + arch: $arch, + base_image: $base_image, + image: $image, + short_sha: $short_sha, + tags: $tags, + versioned_tags_csv: $versioned_tags_csv, + platform: $platform + }' > "build-info/${{ matrix.variant }}-${{ matrix.arch }}.json" - name: Upload build info artifact uses: actions/upload-artifact@v7 diff --git a/.github/workflows/todo-management.yml b/.github/workflows/todo-management.yml index 0a5f7bee0e..3ea147e524 100644 --- a/.github/workflows/todo-management.yml +++ b/.github/workflows/todo-management.yml @@ -286,17 +286,19 @@ jobs: --- *This PR was created automatically by the TODO Management workflow.*" + PR_PAYLOAD=$(jq -n \ + --arg title "$PR_TITLE" \ + --arg body "$PR_BODY" \ + --arg head "$BRANCH_NAME" \ + --arg base "$BASE_REF" \ + '{title: $title, body: $body, head: $head, base: $base}') + # Create PR using GitHub CLI or API curl -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/${{ github.repository }}/pulls" \ - -d "{ - \"title\": \"$PR_TITLE\", - \"body\": \"$PR_BODY\", - \"head\": \"$BRANCH_NAME\", - \"base\": \"$BASE_REF\" - }" + -d "$PR_PAYLOAD" summary: needs: [scan-todos, process-todos] diff --git a/examples/03_github_workflows/03_todo_management/workflow.yml b/examples/03_github_workflows/03_todo_management/workflow.yml index 44548c85dd..320bab37d3 100644 --- a/examples/03_github_workflows/03_todo_management/workflow.yml +++ b/examples/03_github_workflows/03_todo_management/workflow.yml @@ -288,17 +288,19 @@ jobs: --- *This PR was created automatically by the TODO Management workflow.*" + PR_PAYLOAD=$(jq -n \ + --arg title "$PR_TITLE" \ + --arg body "$PR_BODY" \ + --arg head "$BRANCH_NAME" \ + --arg base "$GITHUB_REF_NAME" \ + '{title: $title, body: $body, head: $head, base: $base}') + # Create PR using GitHub CLI or API curl -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/${{ github.repository }}/pulls" \ - -d "{ - \"title\": \"$PR_TITLE\", - \"body\": \"$PR_BODY\", - \"head\": \"$BRANCH_NAME\", - \"base\": \"$GITHUB_REF_NAME\" - }" + -d "$PR_PAYLOAD" summary: needs: [scan-todos, process-todos] From 511f918a068a5435b3ca99c4c4ca9f514b382154 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 24 May 2026 21:03:23 +0000 Subject: [PATCH 8/8] Tighten workflow argument and JSON handling Co-authored-by: openhands --- .github/workflows/api-compliance-runner.yml | 40 +++++++++++-------- .github/workflows/server.yml | 23 ++++++----- .github/workflows/todo-management.yml | 2 +- .../03_todo_management/workflow.yml | 4 +- 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/.github/workflows/api-compliance-runner.yml b/.github/workflows/api-compliance-runner.yml index ea728d566d..d77cd5696f 100644 --- a/.github/workflows/api-compliance-runner.yml +++ b/.github/workflows/api-compliance-runner.yml @@ -62,23 +62,23 @@ jobs: MODELS="" fi - # Build command args - ARGS="" - if [ -n "$PATTERNS" ]; then - ARGS="$ARGS --patterns $PATTERNS" - fi - if [ -n "$MODELS" ]; then - ARGS="$ARGS --models $MODELS" - else - ARGS="$ARGS --models $DEFAULT_MODELS" + if [ -z "$MODELS" ]; then + MODELS="$DEFAULT_MODELS" fi - DELIMITER="args_$(openssl rand -hex 16)" - { - echo "args<<$DELIMITER" - printf '%s\n' "$ARGS" - echo "$DELIMITER" - } >> "$GITHUB_OUTPUT" + write_output() { + local name=$1 + local value=$2 + local delimiter="${name}_$(openssl rand -hex 16)" + { + echo "$name<<$delimiter" + printf '%s\n' "$value" + echo "$delimiter" + } >> "$GITHUB_OUTPUT" + } + + write_output patterns "$PATTERNS" + write_output models "$MODELS" - name: Run API compliance tests id: compliance @@ -86,10 +86,16 @@ jobs: LLM_API_KEY: ${{ secrets.LLM_API_KEY_EVAL }} LLM_BASE_URL: https://llm-proxy.eval.all-hands.dev GITHUB_RUN_ID: ${{ github.run_id }} - PARAM_ARGS: ${{ steps.params.outputs.args }} + PATTERNS: ${{ steps.params.outputs.patterns }} + MODELS: ${{ steps.params.outputs.models }} run: | + args=(--models "$MODELS") + if [ -n "$PATTERNS" ]; then + args=(--patterns "$PATTERNS" "${args[@]}") + fi + uv run python tests/integration/api_compliance/run_compliance.py \ - $PARAM_ARGS \ + "${args[@]}" \ --output-dir compliance-results/ continue-on-error: true # Tests may "fail" but that's expected diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index ffcbcb1f09..f7bceb4583 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -506,9 +506,9 @@ jobs: id: create_manifest env: GIT_REF: ${{ github.ref }} + SHORT_SHA: ${{ steps.get_sha.outputs.short_sha }} + VARIANT: ${{ matrix.variant }} run: | - SHORT_SHA=${{ steps.get_sha.outputs.short_sha }} - VARIANT=${{ matrix.variant }} AMD64_TAGS_CSV=$(jq -r '.tags' build-info/${VARIANT}-amd64.json) declare -A SEEN_MANIFEST_TAGS=() MANIFEST_TAGS=() @@ -560,14 +560,17 @@ jobs: # Save manifest info for consolidation mkdir -p manifest-info - cat > "manifest-info/${VARIANT}.json" << EOF - { - "variant": "${VARIANT}", - "image": "${IMAGE}", - "short_sha": "${SHORT_SHA}", - "manifest_tag": "${MANIFEST_TAG_CSV}" - } - EOF + jq -n \ + --arg variant "$VARIANT" \ + --arg image "$IMAGE" \ + --arg short_sha "$SHORT_SHA" \ + --arg manifest_tag "$MANIFEST_TAG_CSV" \ + '{ + variant: $variant, + image: $image, + short_sha: $short_sha, + manifest_tag: $manifest_tag + }' > "manifest-info/${VARIANT}.json" - name: Upload manifest info artifact uses: actions/upload-artifact@v7 diff --git a/.github/workflows/todo-management.yml b/.github/workflows/todo-management.yml index 3ea147e524..6b5ea55247 100644 --- a/.github/workflows/todo-management.yml +++ b/.github/workflows/todo-management.yml @@ -178,7 +178,7 @@ jobs: TODO_FILE: ${{ matrix.todo.file }} TODO_LINE: ${{ matrix.todo.line }} TODO_DESCRIPTION: ${{ matrix.todo.description }} - BASE_REF: ${{ github.ref_name }} + BASE_REF: ${{ github.event.pull_request.base.ref || github.ref_name }} PYTHONPATH: '' run: | echo "Processing TODO: $TODO_DESCRIPTION" diff --git a/examples/03_github_workflows/03_todo_management/workflow.yml b/examples/03_github_workflows/03_todo_management/workflow.yml index 320bab37d3..0cf72f500a 100644 --- a/examples/03_github_workflows/03_todo_management/workflow.yml +++ b/examples/03_github_workflows/03_todo_management/workflow.yml @@ -181,7 +181,7 @@ jobs: TODO_LINE: ${{ matrix.todo.line }} TODO_DESCRIPTION: ${{ matrix.todo.description }} PYTHONPATH: '' - GITHUB_REF_NAME: ${{ github.ref_name }} + BASE_REF: ${{ github.event.pull_request.base.ref || github.ref_name }} run: | echo "Processing TODO: $TODO_DESCRIPTION" echo "File: $TODO_FILE:$TODO_LINE" @@ -292,7 +292,7 @@ jobs: --arg title "$PR_TITLE" \ --arg body "$PR_BODY" \ --arg head "$BRANCH_NAME" \ - --arg base "$GITHUB_REF_NAME" \ + --arg base "$BASE_REF" \ '{title: $title, body: $body, head: $head, base: $base}') # Create PR using GitHub CLI or API