diff --git a/.github/workflows/codeboarding.yml b/.github/workflows/codeboarding.yml index 5b868b7..3495800 100644 --- a/.github/workflows/codeboarding.yml +++ b/.github/workflows/codeboarding.yml @@ -2,11 +2,10 @@ name: CodeBoarding review on: pull_request: - # Generate once, when the PR becomes reviewable. Reusing this PR's previous - # analysis makes per-push runs affordable, so `synchronize` is a reasonable - # addition now; /codeboarding still refreshes on demand. 'closed' only - # cancels an in-flight review (see concurrency), it doesn't start one. - types: [opened, reopened, ready_for_review, closed] + # Analyze when the PR opens or receives a commit, whether it is ready or draft. + # Changing only the draft state does not rerun analysis. 'closed' only cancels + # an in-flight review (see concurrency), it doesn't start one. + types: [opened, reopened, closed, synchronize] issue_comment: types: [created] @@ -37,7 +36,7 @@ jobs: # changes generated files, so a diff comment would be noise. Scope this to # this repository so a fork using the same branch name is still reviewed. if: > - (github.event_name == 'pull_request' && github.event.action != 'closed' && github.event.pull_request.draft == false && + (github.event_name == 'pull_request' && github.event.action != 'closed' && github.event.pull_request.head.repo.full_name == github.repository && !(github.head_ref == 'codeboarding/sync' && github.event.pull_request.head.repo.full_name == github.repository)) || (github.event_name == 'issue_comment' && github.event.issue.pull_request != null && diff --git a/README.md b/README.md index 1d01f82..fb5a194 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ name: CodeBoarding review on: pull_request: - types: [opened, reopened, ready_for_review, synchronize] + types: [opened, reopened, synchronize] issue_comment: types: [created] @@ -42,7 +42,7 @@ concurrency: jobs: review: if: > - (github.event_name == 'pull_request' && github.event.pull_request.draft == false && + (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || (github.event_name == 'issue_comment' && github.event.issue.pull_request != null && startsWith(github.event.comment.body, '/codeboarding') && @@ -55,7 +55,7 @@ jobs: llm: hosted # or license, or a provider name -- see Authentication ``` -Automatic runs update one sticky **CodeBoarding review** comment. A trusted repository owner, member, or collaborator can comment `/codeboarding` to analyze the current PR head again, including on fork PRs; every command creates a new result comment. +Automatic runs review both draft and non-draft pull requests and update one sticky **CodeBoarding review** comment. Opening, reopening, or pushing a commit runs analysis; changing only the draft state does not. A trusted repository owner, member, or collaborator can comment `/codeboarding` to analyze the current PR head again, including on fork PRs; every command creates a new result comment. `synchronize` re-runs the review on every push to the branch. Each of those runs covers only the commits pushed since the previous one, so a push costs a fraction of a first analysis — and a pushed commit is the only thing that builds the reusable analysis, since GitHub gives comment-triggered runs a read-only cache. Drop `synchronize` from the list if you would rather spend one analysis per pull request than one per push. diff --git a/tests/test_action_inputs.py b/tests/test_action_inputs.py index eb7f21d..4757bc7 100644 --- a/tests/test_action_inputs.py +++ b/tests/test_action_inputs.py @@ -16,6 +16,7 @@ ROOT = Path(__file__).resolve().parent.parent ACTION = (ROOT / "action.yml").read_text(encoding="utf-8") TABLE = json.loads((ROOT / "scripts" / "action" / "supported-providers.json").read_text(encoding="utf-8")) +DOGFOOD = (ROOT / ".github" / "workflows" / "codeboarding.yml").read_text(encoding="utf-8") def declared_inputs() -> dict[str, str]: @@ -70,6 +71,15 @@ def test_depth_is_wired_to_state_identity_and_both_analysis_modes(self) -> None: block = ACTION[start : ACTION.index("\n run:", start)] self.assertIn("DEPTH_CAP: ${{ inputs.depth_cap }}", block) + def test_default_workflow_reviews_drafts_on_open_and_new_commits(self) -> None: + self.assertNotIn("github.event.pull_request.draft", DOGFOOD) + start = DOGFOOD.index("types:") + types = DOGFOOD[start : DOGFOOD.index("\n", start)] + for event in ("opened", "reopened", "synchronize"): + self.assertIn(event, types) + for state_change in ("ready_for_review", "converted_to_draft"): + self.assertNotIn(state_change, types) + def test_the_inferred_credential_inputs_are_gone(self) -> None: """`llm_api_key`/`llm_provider` are what made a fallback expressible at all.""" for stale in ("llm_api_key", "llm_provider"):