Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions repo_policy_sync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ Policy options can be kept in the optional `score-repo-policy-sync.toml` file.
Explicit CLI values override the file; see the
[configuration reference](docs/reference/configuration.md).

The CLI always prints a compact table to standard output. Pass
The CLI always prints a compact table to standard output. Its status column
shows the discovered policy pull-request state (`open`, `merged`, or `closed`)
and number instead of the plain compliance status whenever that PR state is
actionable — an open PR while changes are still required, or a merged/closed
PR alongside current compliance; other combinations, including no matching
PR, keep the plain compliance status. Pass
`--json-output PATH` and/or `--markdown-output PATH` to write additional
versioned JSON and Markdown reports during the same policy run. Markdown is
suited for pull requests, issues, and wikis. Its cells use `✅` for compliant,
Expand Down Expand Up @@ -140,8 +145,10 @@ quadrants:
The supported executable is `score-repo-policy-sync`. Policy IDs are the
directory names containing each `policy.yml`, and policy-owned branches use
the `repo-policy-sync/<policy-id>` naming scheme. The first version does not
provide command aliases or historical policy-ID compatibility; update callers
to the supported command and current policy IDs before rollout.
provide command aliases; update callers to the supported command before
rollout. Renaming a policy is supported by listing its former directory name
in `legacy_names` (see Compatibility notes below) so the existing branch or
pull request is located and updated instead of duplicated.

## First-version change summary

Expand All @@ -153,11 +160,11 @@ policy concurrency, and recovery from stale or conflicting policy branches.

Compatibility notes:

- Callers must use `score-repo-policy-sync`, `--policy-dir`, the current policy
IDs, and `repo-policy-sync/<policy-id>` branches. Legacy command aliases,
`--policy-directory`, and historical policy IDs are not supported.
- Renaming a policy changes its branch and pull-request identity. Existing
policy branches or pull requests must be handled before adopting the new ID.
- Callers must use `score-repo-policy-sync` and `--policy-dir`; legacy command
aliases and `--policy-directory` are not supported.
- Policy migrations can list historical policy IDs in `legacy_names`. Matching
labelled historical pull requests are reported and can only be modified when
their body contains a verifiable branch-head marker.
Comment thread
AlexanderLanin marked this conversation as resolved.
- The first version intentionally does not provide dynamic operation plugins,
persistent result storage, generalized retries/rate-limit handling, or
non-GitHub providers.
4 changes: 2 additions & 2 deletions repo_policy_sync/docs/explanation/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ pre-authenticated `gh` CLI and Git.
applicability and compliance.
- Policy operations use repository-relative paths and are idempotent.
- Each policy maps to one deterministic branch per repository.
- A branch is treated as tool-owned only when its open pull request contains
the policy marker.
- A labelled pull request is associated with a policy only when its body
contains the policy marker.
- An apply run updates the owned pull request’s title and body from the current
policy before pushing any required commit.

Expand Down
22 changes: 13 additions & 9 deletions repo_policy_sync/docs/explanation/pull-request-safety.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,22 @@ The policy directory name is the policy ID and maps to the deterministic branch
`repo-policy-sync/<normalized-policy-id>`, so subsequent runs update the same pull
request instead of creating duplicates.

The first version recognizes only the current policy ID and the
`repo-policy-sync/<normalized-policy-id>` branch and marker. Renaming a policy
is a breaking change: update any existing policy branch or pull request before
using the new ID.
PR discovery uses the `repo-policy-sync` label and then matches the policy
marker in the body. A policy can list former IDs in `legacy_names`, allowing
historical branch names and the former `repo-sync` marker format to remain
visible during a policy migration. New pull requests always use the current
policy ID and branch scheme.

## Ownership and safety

The PR body contains invisible markers for the policy ID and the branch head
created by Repository Policy Sync. Before reusing a branch, the tool verifies
that its remote head still matches the stored value. A missing marker or a
mismatch fails the run without updating, closing, or otherwise taking over the
pull request. This protects a policy branch that someone has changed manually.
The label identifies the tool and the PR body contains an invisible marker for
the policy. The body may also contain a marker for the branch head created by
Repository Policy Sync. Before reusing or closing a PR in apply mode, the tool
verifies that its remote head still matches the stored value. A missing head
marker or a mismatch fails the run without updating, closing, or otherwise
taking over the pull request. This protects a policy branch that someone has
changed manually. Plan mode can report a matching historical PR even when its
old body has no head marker.

If the refreshed default branch is compliant while an owned PR remains open,
apply mode closes that PR after verifying the same branch-head marker used for
Expand Down
6 changes: 4 additions & 2 deletions repo_policy_sync/docs/how-to/run-a-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

# How to run a policy

Use plan mode first. It refreshes disposable local checkouts and reports drift,
but never changes remote repositories:
Use plan mode first. It refreshes disposable local checkouts, reports drift,
and surfaces an actionable matching policy pull request (for example an open
PR while changes are still required, or a merged/closed PR alongside current
compliance), but never changes remote repositories:

```bash
uv run score-repo-policy-sync plan --org eclipse-score
Expand Down
4 changes: 2 additions & 2 deletions repo_policy_sync/docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ are CLI-only.

| Command | Description |
| --- | --- |
| `plan` | Evaluate policies without changing repositories. Exit status `1` indicates drift. |
| `plan` | Evaluate policies and report matching policy pull requests without changing repositories. Exit status `1` indicates drift. |
| `apply` | Apply policies and create or update policy-owned pull requests. |

## Typical
Expand All @@ -37,7 +37,7 @@ are CLI-only.
| `--org NAME` | GitHub organization to scan. May be set in TOML. |
| `--policy NAME` | Select a policy by directory name from local or bundled policies. Repeat to select more than one; when present, only the selected policies run. Defaults to all local and bundled policies. |
| `--repo NAME` | Restrict the run to an exact repository name. Repeat to select more than one. |
| *(stdout)* | Always prints the terminal policy-evaluation table. |
| *(stdout)* | Always prints the terminal policy-evaluation table; its status column shows policy pull-request state and number instead of the plain compliance status when that state is actionable. |

## Rare

Expand Down
7 changes: 5 additions & 2 deletions repo_policy_sync/docs/reference/policy-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ ensure:

`title` and a non-empty `ensure` list are required. `description`,
`legacy_names`, and `when` are optional. `legacy_names` is a list of former
policy IDs whose branches and pull-request markers are still recognized for
this policy. New pull requests use the current directory name and marker.
policy IDs whose pull-request markers are still recognized for this policy.
Pull requests are located through the `repo-policy-sync` label and then matched
by marker, so this also supports historical branch names and the former
`repo-sync` marker format. New pull requests use the current directory name
and marker.
Paths must be non-empty and
repository-relative; absolute paths and paths containing `..` are rejected.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
title: "chore(docs): update score_docs_as_code gitignore configuration"
legacy_names: [docs-as-code-legacy-configuration-removal]
legacy_names:
- docs-as-code-legacy-configuration-removal
- score-docs-as-code.gitignore-and-cleanup
- score-docs-as-code.legacy-documentation-cleanup
description: >
Update the `.gitignore` configuration for `score_docs_as_code`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
title: "chore(bazel): use a minimal module declaration"
legacy_names:
- bazel.minimal-module-declaration
- bazel.module-one-line
description: Keep the Bazel module declaration limited to its repository-owned name.

when:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
title: "chore(bazel): keep the declared version at 8.6.0 or newer"
legacy_names: [bazel.minimum-version]
description: |
Bazel versions older than `8.6.0` are no longer supported, due to a breaking
change in how they handle `compatibility_level`.
Expand Down
10 changes: 9 additions & 1 deletion repo_policy_sync/src/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,16 @@ def main(argv: Sequence[str] | None = None) -> int:
allow_dirty_pr=allow_dirty_pr,
sync_workers=sync_workers,
policy_workers=policy_workers,
# apply already looks up an open PR itself whenever it might act on
# one, so this only buys the merged/closed history used for
# display, at the cost of extra `gh pr list` calls (a closed-state
# scan and, for a branch outside the label lookup, a per-branch
# collision check). Skip that in a bare apply run; still fetch it
# for plan (its only output) and for report files.
include_pull_request_status=(
args.json_output is not None or args.markdown_output is not None
args.command == "plan"
or args.json_output is not None
or args.markdown_output is not None
),
progress=_discard_progress if quiet else _write_progress,
)
Expand Down
Loading