Files
PowerToys/.github/scripts/issue-triage/tests/test_workflow_contract.py
Niels Laute e5a19c4ac5 fix(ci): correct issue and PR triage automation (#50052)
## Summary

- skip AI issue triage when the latest issue state is closed and recheck
state before publishing
- restrict duplicate searches and digest canonical candidates to live
open issues
- add deterministic, additive `Product-*` labels from changed paths for
draft and non-draft PRs
- map Window Hopper, Cursor Wrap, and all Mouse Jump project paths to
their specific product labels before generic fallbacks
- preserve manually applied product labels while managing only intake
lifecycle labels and trusted comments
- collect the PowerToys version and release channel in one required
bug/localization field
- add Window Hopper to the bug report area dropdown and preserve parsing
of both old and combined version headings

This consolidates and supersedes #49961 and #49804.

## Validation

- `node --test .github\scripts\pr-intake\tests\pr-intake.test.mjs` - 39
passing
- `python -m unittest discover .github\scripts\issue-triage\tests -v` -
55 passing
- parsed all modified issue-form and workflow YAML files with PyYAML
- verified every current `src/modules/*` root maps to a product label
- verified the Window Hopper path maps to `Product-Window Hopper`
- `git diff --check`

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b313a270-e6e8-4c4a-89b2-880c1d79027c
Copilot-Session: 498721d4-1098-4298-ac8a-147066fbfea3
2026-08-26 12:13:16 -07:00

74 lines
2.4 KiB
Python

import unittest
from pathlib import Path
GITHUB_DIR = Path(__file__).resolve().parents[3]
WORKFLOW_SOURCE = GITHUB_DIR / "workflows" / "issue-triage.md"
WORKFLOW_LOCK = GITHUB_DIR / "workflows" / "issue-triage.lock.yml"
class WorkflowContractTests(unittest.TestCase):
def test_agent_evidence_uses_shared_runtime_directory(self):
source = WORKFLOW_SOURCE.read_text(encoding="utf-8")
generated = WORKFLOW_LOCK.read_text(encoding="utf-8")
for filename in (
"issue-context.md",
"triage-event.json",
"bug-report-context.md",
):
expected_path = f"/tmp/gh-aw/{filename}"
self.assertIn(expected_path, source)
self.assertIn(expected_path, generated)
def test_copilot_can_publish_without_general_write_or_shell_access(self):
generated = WORKFLOW_LOCK.read_text(encoding="utf-8")
self.assertIn("shell(safeoutputs:*)", generated)
self.assertIn("--deny-tool write", generated)
for command in (
"cat",
"date",
"echo",
"grep",
"head",
"ls",
"printf",
"pwd",
"sort",
"tail",
"uniq",
"wc",
"yq",
):
self.assertIn(f"--deny-tool '\\''shell({command})'\\''", generated)
def test_workflow_never_manages_version_labels(self):
source = WORKFLOW_SOURCE.read_text(encoding="utf-8")
generated = WORKFLOW_LOCK.read_text(encoding="utf-8")
for workflow in (source, generated):
self.assertNotIn("versionLabels", workflow)
self.assertNotIn("desiredVersionLabel", workflow)
self.assertRegex(source, r"never adds or removes\s+version labels")
def test_closed_issues_are_gated_before_publication(self):
source = WORKFLOW_SOURCE.read_text(encoding="utf-8")
generated = WORKFLOW_LOCK.read_text(encoding="utf-8")
self.assertIn("id: refresh", source)
self.assertEqual(
source.count("if: steps.refresh.outputs.should_process == 'true'"),
3,
)
for workflow in (source, generated):
self.assertIn("Issue is closed; ${action} was skipped.", workflow)
self.assertIn(
"currentIssue.closed_by?.login === 'github-actions[bot]'",
workflow,
)
if __name__ == "__main__":
unittest.main()