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
32 changes: 32 additions & 0 deletions actions/setup/js/create_pull_request_helpers.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,38 @@ describe("buildPatchPreviewBlocks", () => {
// buildFallbackIssueBlocks
// ---------------------------------------------------------------------------
describe("buildFallbackIssueBlocks", () => {
it.each([
["manifest_protection_create_pr_fallback.md", "create-pull-request", "fallback-to-issue"],
["manifest_protection_push_failed_fallback.md", "create-pull-request", "fallback-to-issue"],
["manifest_protection_push_to_pr_fallback.md", "push-to-pull-request-branch", "fallback-to-issue"],
["manifest_protection_request_review.md", "create-pull-request", "request-review"],
["manifest_protection_request_changes_review.md", "create-pull-request", "request-review"],
])("includes scoped exclusion guidance in %s", (template, safeOutput, policy) => {
const children = buildFallbackIssueBlocks(require.resolve(`../md/${template}`), {
files: { type: "inline_slot", children: [{ type: "code", value: ".changeset/release.md", agentTainted: true }] },
main_body: [],
footer: [],
create_pr_url: "https://github.com/my-org/my-repo/compare/main...feature?expand=1",
pull_number: "42",
pr_url: "https://github.com/my-org/my-repo/pull/42",
run_url: "https://github.com/my-org/my-repo/actions/runs/123",
apply_instructions: "git am changes.patch",
branch_name: "feature",
title: "Protected file changes",
base_branch: "main",
repo: "my-org/my-repo",
});
const yaml = `safe-outputs:\n ${safeOutput}:\n protected-files:\n policy: ${policy}\n exclude:\n - .changeset/`;
const guidance = children.flatMap(block => (block.type === "details" ? block.children : [block]));
expect(guidance).toContainEqual({ type: "code_block", language: "yaml", value: yaml, agentTainted: false });
const { body } = renderReport({ type: "report", title: "Protected files", children });
expect(body).toContain("`.changeset/*`");
expect(body).toContain("not glob patterns");
expect(body).toContain("`allowed-files`");
expect(body).toContain("`gh aw compile`");
expect(body).not.toContain("protected-files: allowed");
});

it("composes protected-files fallback content as typed blocks with a compare link", () => {
const mainBody = { type: "paragraph", children: [{ type: "text", value: "Original PR description", agentTainted: true }], agentTainted: true };
const footer = { type: "paragraph", children: [{ type: "text", value: "Workflow footer", agentTainted: false }], agentTainted: false };
Expand Down
28 changes: 28 additions & 0 deletions actions/setup/js/handle_agent_failure.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,11 +1110,39 @@ function buildCodePushFailureContext(codePushFailureErrors, pullRequest = null,
};
const blockedTypes = [...new Set(manifestErrors.map(e => e.type))];
let yamlSnippet = "safe-outputs:\n";
let excludeSnippet = "safe-outputs:\n";
for (const type of blockedTypes) {
const yamlKey = typeToYamlKey[type] || type.replace(/_/g, "-");
yamlSnippet += ` ${yamlKey}:\n protected-files: fallback-to-issue\n`;
excludeSnippet += ` ${yamlKey}:\n protected-files:\n policy: blocked\n exclude:\n - .changeset/\n`;
}
context.push(nodes.details([nodes.text("⚙️ Configure "), nodes.code("protected-files: fallback-to-issue")], [nodes.codeBlock(yamlSnippet.trimEnd(), "yaml")]));
context.push(
nodes.details(
[nodes.text("Allow intentional protected-file changes")],
[
nodes.paragraph([
nodes.text("If this workflow is intended to modify these files, add specific filenames or folder prefixes to "),
nodes.code("protected-files.exclude"),
nodes.text(" under the affected safe output in the workflow Markdown frontmatter. For example, to allow "),
nodes.code(".changeset/*"),
nodes.text(", exclude the folder using "),
nodes.code(".changeset/"),
nodes.text(":"),
]),
nodes.codeBlock(excludeSnippet.trimEnd(), "yaml"),
nodes.paragraph([
nodes.text(
"Keep your existing policy and exclusions. Folder exclusions use path prefixes, not glob patterns, and allow all files beneath that folder, including subfolders. Other protected files still follow the configured policy. If "
),
nodes.code("allowed-files"),
nodes.text(" is configured, these paths must also match it. Run "),
nodes.code("gh aw compile"),
nodes.text(" after updating the workflow."),
]),
]
)
);
}

// Patch size exceeded section
Expand Down
8 changes: 8 additions & 0 deletions actions/setup/js/handle_agent_failure.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3440,6 +3440,13 @@ describe("handle_agent_failure", () => {
expect(result).toContain("🛡️ Protected Files");
expect(result).toContain("package.json");
expect(result).toContain("protected-files: fallback-to-issue");
expect(result).toContain("Allow intentional protected-file changes");
expect(result).toContain("`.changeset/*`");
expect(result).toContain("policy: blocked");
expect(result).toContain("exclude:\n - .changeset/");
expect(result).toContain("not glob patterns");
expect(result).toContain("`allowed-files`");
expect(result).toContain("`gh aw compile`");
// Should NOT contain generic "Code Push Failed" for pure manifest errors
expect(result).not.toContain("Code Push Failed");
});
Expand Down Expand Up @@ -3554,6 +3561,7 @@ describe("handle_agent_failure", () => {
const result = buildCodePushFailureContext(errors);
expect(result).toContain("push-to-pull-request-branch:");
expect(result).toContain("protected-files: fallback-to-issue");
expect(result).toContain("push-to-pull-request-branch:\n protected-files:\n policy: blocked\n exclude:\n - .changeset/");
expect(result).not.toContain("create-pull-request:");
});

Expand Down
85 changes: 85 additions & 0 deletions actions/setup/js/testdata/messages_preview.md
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,24 @@ This is a synthetic body for a test. No GitHub item is created.

To route changes like this to a review issue instead of blocking, configure `protected-files: fallback-to-issue` in your workflow configuration.

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add specific filenames or folder prefixes to `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the folder using `.changeset/`:

```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: fallback-to-issue
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Folder exclusions use path prefixes, not glob patterns, and allow all files beneath that folder, including subfolders. Other protected files still follow the configured policy. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>

> Generated by [Synthetic preview workflow](https://example.test/synthetic/repository/actions/runs/1000)

---
Expand Down Expand Up @@ -1238,6 +1256,24 @@ gh pr create --title 'Synthetic pull request' --base main --head synthetic-branc

</details>

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add a supported exclusion to `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the top-level dot-folder using `.changeset/`:

```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: fallback-to-issue
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Top-level dot-folder exclusions use folder names, not glob patterns; `.changeset/` allows all files beneath the top-level `.changeset` folder, including subfolders. Other protected files still follow the configured policy. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>

> Generated by [Synthetic preview workflow](https://example.test/synthetic/repository/actions/runs/1000)

---
Expand Down Expand Up @@ -1277,6 +1313,24 @@ synthetic_apply_instructions

To route changes like this to a review issue instead of blocking, configure `protected-files: fallback-to-issue` in your workflow configuration.

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add specific filenames or folder prefixes to `safe-outputs.push-to-pull-request-branch.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the folder using `.changeset/`:

```yaml
safe-outputs:
push-to-pull-request-branch:
protected-files:
policy: fallback-to-issue
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Folder exclusions use path prefixes, not glob patterns, and allow all files beneath that folder, including subfolders. Other protected files still follow the configured policy. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>

---

## Template: manifest_protection_request_changes_review.md
Expand All @@ -1287,6 +1341,19 @@ Please verify that each protected-file change is intentional, policy-compliant,

- Protected files: `synthetic/file.txt`

To allow intentional changes to specific files or folders in future runs, configure `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, this allows `.changeset/*` by excluding the folder:

```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: request-review
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Use folder prefixes, not glob patterns; `.changeset/` also allows subfolders. Other protected files still require review, and `allowed-files`, if configured, must also permit these paths. Run `gh aw compile` after updating the workflow. This configuration change applies to future runs; review this pull request separately.

---

## Template: manifest_protection_request_review.md
Expand All @@ -1297,6 +1364,24 @@ Please verify that each protected-file change is intentional, policy-compliant,
>
> Protected files: `synthetic/file.txt`

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add specific filenames or folder prefixes to `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the folder using `.changeset/`:

```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: request-review
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Folder exclusions use path prefixes, not glob patterns, and allow all files beneath that folder, including subfolders. Other protected files still require review. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>

---

## Template: max_cache_misses_exceeded.md
Expand Down
18 changes: 18 additions & 0 deletions actions/setup/md/manifest_protection_create_pr_fallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,22 @@

To route changes like this to a review issue instead of blocking, configure `protected-files: fallback-to-issue` in your workflow configuration.

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add specific filenames or folder prefixes to `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the folder using `.changeset/`:
Comment thread
pelikhan marked this conversation as resolved.
Resolved

Comment thread
pelikhan marked this conversation as resolved.
Resolved
```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: fallback-to-issue
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Folder exclusions use path prefixes, not glob patterns, and allow all files beneath that folder, including subfolders. Other protected files still follow the configured policy. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>

{footer}
18 changes: 18 additions & 0 deletions actions/setup/md/manifest_protection_push_failed_fallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,22 @@ gh pr create --title '{title}' --base {base_branch} --head {branch_name} --repo

</details>

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add a supported exclusion to `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the top-level dot-folder using `.changeset/`:

```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: fallback-to-issue
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Top-level dot-folder exclusions use folder names, not glob patterns; `.changeset/` allows all files beneath the top-level `.changeset` folder, including subfolders. Other protected files still follow the configured policy. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>

{footer}
18 changes: 18 additions & 0 deletions actions/setup/md/manifest_protection_push_to_pr_fallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,21 @@ The changes are available in the workflow run artifacts:
</details>

To route changes like this to a review issue instead of blocking, configure `protected-files: fallback-to-issue` in your workflow configuration.

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add specific filenames or folder prefixes to `safe-outputs.push-to-pull-request-branch.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the folder using `.changeset/`:

```yaml
safe-outputs:
push-to-pull-request-branch:
protected-files:
policy: fallback-to-issue
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Folder exclusions use path prefixes, not glob patterns, and allow all files beneath that folder, including subfolders. Other protected files still follow the configured policy. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>
13 changes: 13 additions & 0 deletions actions/setup/md/manifest_protection_request_changes_review.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,16 @@ Protected files were modified in this pull request and require manual scrutiny b
Please verify that each protected-file change is intentional, policy-compliant, and safe:

- Protected files: {files}

To allow intentional changes to specific files or folders in future runs, configure `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, this allows `.changeset/*` by excluding the folder:

```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: request-review
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Use folder prefixes, not glob patterns; `.changeset/` also allows subfolders. Other protected files still require review, and `allowed-files`, if configured, must also permit these paths. Run `gh aw compile` after updating the workflow. This configuration change applies to future runs; review this pull request separately.
18 changes: 18 additions & 0 deletions actions/setup/md/manifest_protection_request_review.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,21 @@
> This pull request is in `request-review` mode and requires explicit human scrutiny before merge.
>
> Protected files: {files}

<details>
<summary>Allow intentional protected-file changes</summary>

If this workflow is intended to modify these files, add specific filenames or folder prefixes to `safe-outputs.create-pull-request.protected-files.exclude` in the workflow Markdown frontmatter. For example, to allow `.changeset/*`, exclude the folder using `.changeset/`:

```yaml
safe-outputs:
create-pull-request:
protected-files:
policy: request-review
exclude:
- .changeset/
```

Keep your existing policy and exclusions. Folder exclusions use path prefixes, not glob patterns, and allow all files beneath that folder, including subfolders. Other protected files still require review. If `allowed-files` is configured, these paths must also match it. Run `gh aw compile` after updating the workflow.

</details>
Loading