Skip to content

ci: post Validate Integration comments on fork PRs via workflow_run#313

Merged
TheRealAgentK merged 2 commits into
masterfrom
ci/312/fork-pr-comments
May 1, 2026
Merged

ci: post Validate Integration comments on fork PRs via workflow_run#313
TheRealAgentK merged 2 commits into
masterfrom
ci/312/fork-pr-comments

Conversation

@TheRealAgentK
Copy link
Copy Markdown
Collaborator

Closes #312.

What

Switches the Validate Integration (Tooling) workflow to the two-workflow pattern for fork PR comments:

  • .github/workflows/validate-integration.yml (modified)
    • Sets post_comment: 'false' on the tooling action so the inline post step is skipped.
    • Captures the rendered comment via the new comment_path output (tooling 2.1.0).
    • Uploads { pr-number.txt, comment.md } (or delete.marker when no integration directories changed) as a validation-comment artifact, 1-day retention.
    • Drops pull-requests: write from permissions: — no longer needed in this job.
  • .github/workflows/validate-integration-comment.yml (new)
    • Triggers on workflow_run completion of Validate Integration (Tooling).
    • Runs in base-repo context with pull-requests: write (which actually works there because the token isn't downgraded — workflow_run is the documented escape hatch).
    • Downloads the artifact, reads the PR number, then either deletes a stale sticky comment (delete.marker) or posts the rendered comment via marocchino/sticky-pull-request-comment@v2.

Why

pull_request workflows triggered from forks always run with a read-only GITHUB_TOKEN regardless of the workflow's permissions: block (docs). The existing inline comment step always 403s on fork PRs and the job goes red purely because of the failed comment-posting step, even when validation passed. Concrete example: #293 (HubSpot tasks, opened from lohitya/autohive-integrations).

workflow_run-triggered jobs run in the base-repository context with normal token permissions, regardless of whether the original event was a fork PR. Untrusted fork code never executes with elevated tokens — the validation job stays read-only, and the companion job only ever processes a small artifact (PR number + Markdown text), never executes fork code. Same trade-off (and same reason) that ruled out pull_request_target for this workflow.

Properties

  • ✅ Same-repo PRs: comment posting still happens, via the new flow. Slight delay (~few seconds for the second workflow to start) but otherwise identical.
  • ✅ Fork PRs: comment now appears (didn't before). CI ✅/❌ reflects validation, not comment-posting.
  • ✅ Untrusted fork code never runs with elevated tokens.
  • marocchino's sticky behaviour still works — matches by header: validation-results and updates in place across runs.

One-time blind spot during this PR's review

workflow_run triggers fire based on the workflow file on the repository's default branch, not on the PR branch. So while this PR is open, the new validate-integration-comment.yml is on the PR branch but not yet on master — meaning this PR's own CI runs won't have a companion workflow to post their comment. CI ✅/❌ will still be correct (reflects validation only). After merge, every subsequent PR — fork or same-repo — gets the full pipeline working.

Verification

  • python3 -c "import yaml; yaml.safe_load(...)" on both workflow files — both parse cleanly.
  • Renderer (in tooling) and the file-handoff design were smoke-tested locally during the tooling-repo PR.

Prerequisites (already done)

pull_request workflows triggered from forks always run with a
read-only GITHUB_TOKEN, regardless of the workflow's permissions:
block — that's a documented GitHub Actions security boundary, not a
config oversight. As a result the existing 'Post PR comment' step
in autohive-ai/autohive-integrations-tooling@v2 always 403s on fork
PRs (e.g. #293), and the job conclusion goes red purely because of
the failed comment-posting step even when all five validation
checks passed.

This commit switches to the standard two-workflow pattern for fork
PR comments:

* validate-integration.yml now sets post_comment: 'false' on the
  tooling action (so the inline post step is skipped), captures the
  rendered comment via the action's new comment_path output, and
  uploads it together with the PR number as a 'validation-comment'
  artifact. Job conclusion now reflects validation only.

* validate-integration-comment.yml (new) is triggered on
  workflow_run completion of the validation workflow, runs in the
  base-repository context with full token permissions, downloads
  the artifact, and posts the sticky comment via
  marocchino/sticky-pull-request-comment@v2.

Untrusted fork code never executes with elevated tokens — the
validation job stays read-only, and the companion job only ever
processes a small artifact (PR number + Markdown text), never
executes fork code. Same trade-off (and same reason) that ruled out
pull_request_target for this workflow.

Requires autohive-integrations-tooling 2.1.0 (already released and
v2 retagged).

Closes #312
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a20ebed3db

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .github/workflows/validate-integration-comment.yml Outdated
Addresses review feedback: the validation job runs fork-controlled
code (pytest, imported integration modules) on the runner, so
anything it writes to the workspace — including the artifact — must
be treated as untrusted by the privileged workflow_run companion.
A malicious fork could overwrite pr-number.txt during pytest /
conftest hooks to redirect the companion's write-scoped
sticky-comment posting (or delete) at an arbitrary victim PR.

The companion now resolves the target PR from the trusted
workflow_run event payload:

  1. Try github.event.workflow_run.pull_requests[0].number first
     (populated for same-repo PRs).
  2. Fall back to a GitHub API lookup using the trusted
     workflow_run.head_sha (the pull_requests array is empty for
     fork PRs because the head SHA lives in a different repo).

Both inputs come from GitHub's event payload, not from the
artifact, so on-runner fork code cannot influence the resolution.

The validate workflow no longer writes pr-number.txt — only
comment.md (or delete.marker). The artifact is still required for
the rendered comment body, but its contents now only ever land on
the PR that GitHub itself associates with the head SHA, so the
worst-case effect of fork manipulation is bounded to the fork
author's own PR.

Refs #312, codex review on #313.
@TheRealAgentK TheRealAgentK merged commit 3bb54c5 into master May 1, 2026
3 checks passed
@TheRealAgentK TheRealAgentK deleted the ci/312/fork-pr-comments branch May 1, 2026 03:04
TheRealAgentK added a commit to lohitya/autohive-integrations that referenced this pull request May 1, 2026
Empty commit to retrigger CI on PR Autohive-AI#293 so we can verify the new
fork-PR comment pipeline (Autohive-AI#313)
works end-to-end:

  1. Validate Integration (Tooling) should now go ✅ even on a fork
     PR (uploads artifact instead of attempting an inline 403-bound
     comment post).
  2. Validate Integration Comment companion should run, resolve the
     PR number from the workflow_run event payload, and post the
     sticky validation-results comment.

No code changes. Safe to drop / squash on merge.
Shubhank-Jonnada pushed a commit that referenced this pull request May 12, 2026
…h unit tests (#293)

* feat: add tasks management to HubSpot integration with unit tests

* fix: refine hubspot task association logic

* fix(hubspot): refine task action handling and tests

Restrict HubSpot task updates to the intended task action paths and align task unit tests with the latest task behavior to keep task-scoped changes isolated.

Made-with: Cursor

* fix(hubspot): correct integration version

* fix(hubspot): remove duplicate fetch in get_thread_id_from_ticket

The function was making two consecutive identical context.fetch() calls
for the ticket URL — a merge artifact from resolving conflicts when
master was merged into ls/hubspot-tasks. The extra call shifted
mock_context.fetch.call_args_list indices by one in the existing
ticket-conversation tests, causing 15 failures in
test_hubspot_tickets_unit.py.

Removing the duplicate restores the single-fetch behaviour from master.

* style(hubspot): apply ruff format to match project line-length

Reflow lines in the new task handlers and tests to match the
project's 120-char ruff configuration. No behavioural changes.

* ci: retrigger Validate Integration after fork-PR comment fix

Empty commit to retrigger CI on PR #293 so we can verify the new
fork-PR comment pipeline (#313)
works end-to-end:

  1. Validate Integration (Tooling) should now go ✅ even on a fork
     PR (uploads artifact instead of attempting an inline 403-bound
     comment post).
  2. Validate Integration Comment companion should run, resolve the
     PR number from the workflow_run event payload, and post the
     sticky validation-results comment.

No code changes. Safe to drop / squash on merge.

* ci: retrigger after fork PR resolution fix

Empty commit to retrigger CI on PR #293 so we can verify the
fork-PR resolution fix from #315 works end-to-end:

  Validate Integration Comment should now successfully resolve
  PR 293 via /pulls?head=lohitya:ls/hubspot-tasks (the previous
  /commits/{sha}/pulls endpoint was returning empty for fork SHAs)
  and post the sticky validation-results comment.

No code changes.

* fix(hubspot): align task actions with schema and version bump

* test(hubspot): align task unit tests with hs_task_* inputs and adds context.py

This commit adds context.py for structure validation and aligns canonical HubSpot task property names.

* docs(hubspot): align README task sections with config schema

This commit aligns README file with updated config schema

* refactor(hubspot): remove dead context.py shim and simplify test imports

- Delete unused tests/context.py (was scaffolding, never imported)
- Simplify tests/conftest.py to only put integration root on sys.path
- Replace per-file importlib.spec_from_file_location boilerplate with
  plain 'from hubspot.hubspot import ...' imports across all test files
- Apply ruff format using the tooling ruff.toml config

---------

Co-authored-by: Kai Koenig <kai@ventego-creative.co.nz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Post Validate Integration results on fork PRs via workflow_run companion

3 participants