engineering-process 1.2.5__tar.gz → 1.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {engineering_process-1.2.5 → engineering_process-1.2.6}/MANIFEST.in +1 -1
- {engineering_process-1.2.5/engineering_process.egg-info → engineering_process-1.2.6}/PKG-INFO +34 -1
- {engineering_process-1.2.5 → engineering_process-1.2.6}/README.md +33 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/__init__.py +1 -1
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/contracts.py +8 -3
- {engineering_process-1.2.5 → engineering_process-1.2.6/engineering_process.egg-info}/PKG-INFO +34 -1
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process.egg-info/SOURCES.txt +1 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/pyproject.toml +2 -1
- engineering_process-1.2.6/templates/renovate.json +6 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_automation.py +45 -1
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_contracts.py +18 -1
- {engineering_process-1.2.5 → engineering_process-1.2.6}/LICENSE +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/__main__.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/_supervisor_contract.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/_supervisor_posix.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/_supervisor_windows.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/_windows_job.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/adoption.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/cli.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/commands.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/distribution.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/helper_launch.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/lifecycle.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/production_engineering.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/project.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/publication_compat.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/release.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/repository.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/requirements-dev.txt +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/requirements-runtime.txt +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/skills.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/supervision.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process.egg-info/dependency_links.txt +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process.egg-info/entry_points.txt +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process.egg-info/requires.txt +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process.egg-info/top_level.txt +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process-graph.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/finish-change/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/implement-change/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/improve-process/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/plan-change/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/production-engineering/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/production-engineering/invariants.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/review-change/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/run-change/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/start-change/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/verify-change/SKILL.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/change.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/plan.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/process-graph.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/process-lock.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/production-engineering.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/project-legacy.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/project.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/receipt.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/release-change.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/release.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/review.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/run.schema.json +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/setup.cfg +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/templates/AGENTS.process.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/templates/PULL_REQUEST_TEMPLATE.md +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/templates/adopt-process-windows-job.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/templates/adopt-process.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_adoption.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_architecture.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_cli.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_commands.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_distribution.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_lifecycle.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_production_engineering.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_publication_compat.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_pypi_cache_horizon.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_release.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_repository.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_skills.py +0 -0
- {engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_supervisor_posix.py +0 -0
{engineering_process-1.2.5/engineering_process.egg-info → engineering_process-1.2.6}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: engineering-process
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Summary: A small agent-neutral engineering lifecycle with managed adoption
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/phuongnse/engineering-process
|
|
@@ -471,6 +471,39 @@ authorizes that merge.
|
|
|
471
471
|
This repository opts in through .github/renovate.json, so it receives the same
|
|
472
472
|
adoption PR as every other consumer. See SELF_HOSTING.md and RELEASING.md.
|
|
473
473
|
|
|
474
|
+
The optional [Renovate preset](templates/renovate.json) is generated from the
|
|
475
|
+
canonical public template. It supplies only `prHeader` and `prBodyTemplate`;
|
|
476
|
+
dependency selection, supported platforms, schedules, major-update approval,
|
|
477
|
+
commands, draft policy, and merge authority remain consumer-owned. Regenerate it
|
|
478
|
+
with `python verification/generate_renovate_preset.py`; `--check` rejects drift.
|
|
479
|
+
|
|
480
|
+
Consumers add `github>phuongnse/engineering-process//templates/renovate#COMMIT_SHA`
|
|
481
|
+
to their existing `extends` array, replacing `COMMIT_SHA` with the full source
|
|
482
|
+
commit of a verified release that contains the preset. Remove obsolete inline
|
|
483
|
+
`prHeader` and `prBodyTemplate` overrides, including matching package-rule overrides.
|
|
484
|
+
The preset targets the canonical draft grammar used by 1.2.4 and this distribution;
|
|
485
|
+
it does not claim compatibility with earlier publication contracts. A future
|
|
486
|
+
grammar change must preserve this adapter or ship an explicit consumer migration.
|
|
487
|
+
|
|
488
|
+
Renovate resolves presets from the protected base configuration before dependency
|
|
489
|
+
updates and post-upgrade tasks. Bootstrap the compatible preset in that base before
|
|
490
|
+
relying on its generated drafts; changing the candidate configuration alone cannot
|
|
491
|
+
repair the same run's body. Verify the native rendered body against both the base
|
|
492
|
+
and candidate process authority during adoption. Pending fields and unchecked
|
|
493
|
+
Completion gate items are proposals, never evidence or approval.
|
|
494
|
+
|
|
495
|
+
Before collecting lifecycle evidence for a bot PR, apply its configured
|
|
496
|
+
`stopUpdatingLabel` (Renovate's default is `stop-updating`) and confirm the head is
|
|
497
|
+
unchanged after any in-flight bot run finishes. Keep the label through verification,
|
|
498
|
+
independent review, receipt and the consumer-owned merge. Do not request a native
|
|
499
|
+
rebase or dashboard retry while reviewing: an explicit retry can resume updates.
|
|
500
|
+
If the candidate changes, open a new implementation cycle and collect fresh
|
|
501
|
+
evidence. Remove the pause label only when returning the PR to automation.
|
|
502
|
+
|
|
503
|
+
These are native [shared preset](https://docs.renovatebot.com/config-presets/) and
|
|
504
|
+
[review pause](https://docs.renovatebot.com/configuration-options/#stopupdatinglabel)
|
|
505
|
+
boundaries; the control plane does not become a second PR publisher.
|
|
506
|
+
|
|
474
507
|
## Compatibility
|
|
475
508
|
|
|
476
509
|
Version 1.x retains a few small pre-1.0 command shapes so existing consumers can
|
|
@@ -447,6 +447,39 @@ authorizes that merge.
|
|
|
447
447
|
This repository opts in through .github/renovate.json, so it receives the same
|
|
448
448
|
adoption PR as every other consumer. See SELF_HOSTING.md and RELEASING.md.
|
|
449
449
|
|
|
450
|
+
The optional [Renovate preset](templates/renovate.json) is generated from the
|
|
451
|
+
canonical public template. It supplies only `prHeader` and `prBodyTemplate`;
|
|
452
|
+
dependency selection, supported platforms, schedules, major-update approval,
|
|
453
|
+
commands, draft policy, and merge authority remain consumer-owned. Regenerate it
|
|
454
|
+
with `python verification/generate_renovate_preset.py`; `--check` rejects drift.
|
|
455
|
+
|
|
456
|
+
Consumers add `github>phuongnse/engineering-process//templates/renovate#COMMIT_SHA`
|
|
457
|
+
to their existing `extends` array, replacing `COMMIT_SHA` with the full source
|
|
458
|
+
commit of a verified release that contains the preset. Remove obsolete inline
|
|
459
|
+
`prHeader` and `prBodyTemplate` overrides, including matching package-rule overrides.
|
|
460
|
+
The preset targets the canonical draft grammar used by 1.2.4 and this distribution;
|
|
461
|
+
it does not claim compatibility with earlier publication contracts. A future
|
|
462
|
+
grammar change must preserve this adapter or ship an explicit consumer migration.
|
|
463
|
+
|
|
464
|
+
Renovate resolves presets from the protected base configuration before dependency
|
|
465
|
+
updates and post-upgrade tasks. Bootstrap the compatible preset in that base before
|
|
466
|
+
relying on its generated drafts; changing the candidate configuration alone cannot
|
|
467
|
+
repair the same run's body. Verify the native rendered body against both the base
|
|
468
|
+
and candidate process authority during adoption. Pending fields and unchecked
|
|
469
|
+
Completion gate items are proposals, never evidence or approval.
|
|
470
|
+
|
|
471
|
+
Before collecting lifecycle evidence for a bot PR, apply its configured
|
|
472
|
+
`stopUpdatingLabel` (Renovate's default is `stop-updating`) and confirm the head is
|
|
473
|
+
unchanged after any in-flight bot run finishes. Keep the label through verification,
|
|
474
|
+
independent review, receipt and the consumer-owned merge. Do not request a native
|
|
475
|
+
rebase or dashboard retry while reviewing: an explicit retry can resume updates.
|
|
476
|
+
If the candidate changes, open a new implementation cycle and collect fresh
|
|
477
|
+
evidence. Remove the pause label only when returning the PR to automation.
|
|
478
|
+
|
|
479
|
+
These are native [shared preset](https://docs.renovatebot.com/config-presets/) and
|
|
480
|
+
[review pause](https://docs.renovatebot.com/configuration-options/#stopupdatinglabel)
|
|
481
|
+
boundaries; the control plane does not become a second PR publisher.
|
|
482
|
+
|
|
450
483
|
## Compatibility
|
|
451
484
|
|
|
452
485
|
Version 1.x retains a few small pre-1.0 command shapes so existing consumers can
|
|
@@ -67,9 +67,9 @@ def digest_json(value: Any) -> str:
|
|
|
67
67
|
return "sha256:" + hashlib.sha256(canonical_bytes(value)).hexdigest()
|
|
68
68
|
|
|
69
69
|
|
|
70
|
-
def
|
|
71
|
-
"""
|
|
72
|
-
|
|
70
|
+
def formatted_json_bytes(value: Any) -> bytes:
|
|
71
|
+
"""Serialize human-readable JSON as UTF-8 without BOM, using LF."""
|
|
72
|
+
return (
|
|
73
73
|
json.dumps(
|
|
74
74
|
value,
|
|
75
75
|
ensure_ascii=False,
|
|
@@ -79,6 +79,11 @@ def write_json_atomic(path: Path, value: Any) -> None:
|
|
|
79
79
|
)
|
|
80
80
|
+ "\n"
|
|
81
81
|
).encode("utf-8")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def write_json_atomic(path: Path, value: Any) -> None:
|
|
85
|
+
"""Write canonical human-readable JSON without exposing a partial file."""
|
|
86
|
+
data = formatted_json_bytes(value)
|
|
82
87
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
83
88
|
temporary = path.with_name(f".{path.name}.tmp")
|
|
84
89
|
try:
|
{engineering_process-1.2.5 → engineering_process-1.2.6/engineering_process.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: engineering-process
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
4
4
|
Summary: A small agent-neutral engineering lifecycle with managed adoption
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/phuongnse/engineering-process
|
|
@@ -471,6 +471,39 @@ authorizes that merge.
|
|
|
471
471
|
This repository opts in through .github/renovate.json, so it receives the same
|
|
472
472
|
adoption PR as every other consumer. See SELF_HOSTING.md and RELEASING.md.
|
|
473
473
|
|
|
474
|
+
The optional [Renovate preset](templates/renovate.json) is generated from the
|
|
475
|
+
canonical public template. It supplies only `prHeader` and `prBodyTemplate`;
|
|
476
|
+
dependency selection, supported platforms, schedules, major-update approval,
|
|
477
|
+
commands, draft policy, and merge authority remain consumer-owned. Regenerate it
|
|
478
|
+
with `python verification/generate_renovate_preset.py`; `--check` rejects drift.
|
|
479
|
+
|
|
480
|
+
Consumers add `github>phuongnse/engineering-process//templates/renovate#COMMIT_SHA`
|
|
481
|
+
to their existing `extends` array, replacing `COMMIT_SHA` with the full source
|
|
482
|
+
commit of a verified release that contains the preset. Remove obsolete inline
|
|
483
|
+
`prHeader` and `prBodyTemplate` overrides, including matching package-rule overrides.
|
|
484
|
+
The preset targets the canonical draft grammar used by 1.2.4 and this distribution;
|
|
485
|
+
it does not claim compatibility with earlier publication contracts. A future
|
|
486
|
+
grammar change must preserve this adapter or ship an explicit consumer migration.
|
|
487
|
+
|
|
488
|
+
Renovate resolves presets from the protected base configuration before dependency
|
|
489
|
+
updates and post-upgrade tasks. Bootstrap the compatible preset in that base before
|
|
490
|
+
relying on its generated drafts; changing the candidate configuration alone cannot
|
|
491
|
+
repair the same run's body. Verify the native rendered body against both the base
|
|
492
|
+
and candidate process authority during adoption. Pending fields and unchecked
|
|
493
|
+
Completion gate items are proposals, never evidence or approval.
|
|
494
|
+
|
|
495
|
+
Before collecting lifecycle evidence for a bot PR, apply its configured
|
|
496
|
+
`stopUpdatingLabel` (Renovate's default is `stop-updating`) and confirm the head is
|
|
497
|
+
unchanged after any in-flight bot run finishes. Keep the label through verification,
|
|
498
|
+
independent review, receipt and the consumer-owned merge. Do not request a native
|
|
499
|
+
rebase or dashboard retry while reviewing: an explicit retry can resume updates.
|
|
500
|
+
If the candidate changes, open a new implementation cycle and collect fresh
|
|
501
|
+
evidence. Remove the pause label only when returning the PR to automation.
|
|
502
|
+
|
|
503
|
+
These are native [shared preset](https://docs.renovatebot.com/config-presets/) and
|
|
504
|
+
[review pause](https://docs.renovatebot.com/configuration-options/#stopupdatinglabel)
|
|
505
|
+
boundaries; the control plane does not become a second PR publisher.
|
|
506
|
+
|
|
474
507
|
## Compatibility
|
|
475
508
|
|
|
476
509
|
Version 1.x retains a few small pre-1.0 command shapes so existing consumers can
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "engineering-process"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.6"
|
|
8
8
|
description = "A small agent-neutral engineering lifecycle with managed adoption"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -42,6 +42,7 @@ dev = {file = ["engineering_process/requirements-dev.txt"]}
|
|
|
42
42
|
"share/engineering-process/templates" = [
|
|
43
43
|
"templates/AGENTS.process.md",
|
|
44
44
|
"templates/PULL_REQUEST_TEMPLATE.md",
|
|
45
|
+
"templates/renovate.json",
|
|
45
46
|
"templates/adopt-process.py",
|
|
46
47
|
"templates/adopt-process-windows-job.py",
|
|
47
48
|
]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
+
"description": "Pending process draft; generated from templates/PULL_REQUEST_TEMPLATE.md.",
|
|
4
|
+
"prBodyTemplate": "{{{header}}}",
|
|
5
|
+
"prHeader": "## Summary\n\n- Outcome: Update {{#each upgrades}}{{depName}} from {{currentValue}}{{#if currentDigest}} ({{currentDigest}}){{/if}} to {{newValue}}{{#if newDigest}} ({{newDigest}}){{/if}}{{#unless @last}}; {{/unless}}{{/each}}.\n- Scope: {{#each upgrades}}{{packageFile}}{{#unless @last}}; {{/unless}}{{/each}}.\n\n## Contract and risk\n\n- Source: pending\n- Risk: pending\n- Compatibility: pending\n- Stack: pending\n\n## Verification\n\n- Profiles: pending\n- Snapshot: pending\n- Completion receipt: pending\n\n## Independent review\n\n- Verdict: pending\n- Cycles: pending\n- Blocking findings: pending\n- Non-blocking dispositions: pending\n\n## Completion gate\n\n- [ ] Accepted scope is implemented without silent expansion.\n- [ ] Required profiles pass on the reviewed snapshot.\n- [ ] Independent review approved with no blocking finding.\n- [ ] Every non-blocking finding has a recorded disposition.\n"
|
|
6
|
+
}
|
|
@@ -3,9 +3,14 @@ from __future__ import annotations
|
|
|
3
3
|
import json
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import re
|
|
6
|
+
import tempfile
|
|
6
7
|
import unittest
|
|
8
|
+
from unittest.mock import patch
|
|
7
9
|
|
|
8
|
-
from engineering_process.
|
|
10
|
+
from engineering_process.contracts import ProcessError
|
|
11
|
+
from engineering_process.publication_compat import _pull_request_body_issues, validate_pull_request
|
|
12
|
+
from verification.generate_renovate_preset import generate_preset
|
|
13
|
+
from verification import generate_renovate_preset
|
|
9
14
|
|
|
10
15
|
|
|
11
16
|
ROOT = Path(__file__).resolve().parent.parent
|
|
@@ -15,6 +20,45 @@ ACTIVE_PROCESS_PIN = re.compile(
|
|
|
15
20
|
|
|
16
21
|
|
|
17
22
|
class AutomationTests(unittest.TestCase):
|
|
23
|
+
def test_renovate_preset_matches_the_canonical_pending_template(self) -> None:
|
|
24
|
+
template = (ROOT / "templates" / "PULL_REQUEST_TEMPLATE.md").read_text(encoding="utf-8")
|
|
25
|
+
preset = json.loads((ROOT / "templates" / "renovate.json").read_text(encoding="utf-8"))
|
|
26
|
+
self.assertEqual(generate_preset(template), preset)
|
|
27
|
+
self.assertEqual([], _pull_request_body_issues(preset["prHeader"], "draft"))
|
|
28
|
+
self.assertTrue(_pull_request_body_issues(preset["prHeader"], "ready"))
|
|
29
|
+
|
|
30
|
+
def test_renovate_preset_rejects_an_incomplete_public_contract(self) -> None:
|
|
31
|
+
template = (ROOT / "templates" / "PULL_REQUEST_TEMPLATE.md").read_text(encoding="utf-8")
|
|
32
|
+
with self.assertRaises(ProcessError):
|
|
33
|
+
generate_preset(template.replace("## Completion gate", "## Other"))
|
|
34
|
+
|
|
35
|
+
def test_renovate_generator_rejects_changed_bytes_and_recovers(self) -> None:
|
|
36
|
+
template = (ROOT / "templates" / "PULL_REQUEST_TEMPLATE.md").read_bytes()
|
|
37
|
+
with tempfile.TemporaryDirectory() as directory:
|
|
38
|
+
root = Path(directory)
|
|
39
|
+
(root / "templates").mkdir()
|
|
40
|
+
(root / "templates" / "PULL_REQUEST_TEMPLATE.md").write_bytes(template)
|
|
41
|
+
target = root / "templates" / "renovate.json"
|
|
42
|
+
with patch.object(generate_renovate_preset, "PROJECT_ROOT", root), patch("sys.argv", ["generate"]):
|
|
43
|
+
self.assertEqual(0, generate_renovate_preset.main())
|
|
44
|
+
expected = target.read_bytes()
|
|
45
|
+
self.assertNotIn(b"\r", expected)
|
|
46
|
+
self.assertFalse(expected.startswith(b"\xef\xbb\xbf"))
|
|
47
|
+
for changed in (
|
|
48
|
+
expected.replace(b"\n", b"\r\n"),
|
|
49
|
+
expected.replace(b"\n", b"\r\n", 1),
|
|
50
|
+
b"\xef\xbb\xbf" + expected,
|
|
51
|
+
):
|
|
52
|
+
with self.subTest(changed=changed[:20]):
|
|
53
|
+
target.write_bytes(changed)
|
|
54
|
+
with patch("sys.argv", ["generate", "--check"]):
|
|
55
|
+
with self.assertRaisesRegex(ProcessError, "is stale"):
|
|
56
|
+
generate_renovate_preset.main()
|
|
57
|
+
self.assertEqual(0, generate_renovate_preset.main())
|
|
58
|
+
self.assertEqual(expected, target.read_bytes())
|
|
59
|
+
with patch("sys.argv", ["generate", "--check"]):
|
|
60
|
+
self.assertEqual(0, generate_renovate_preset.main())
|
|
61
|
+
|
|
18
62
|
def test_pull_request_template_defines_public_evidence_hierarchy(self) -> None:
|
|
19
63
|
template = (ROOT / "templates" / "PULL_REQUEST_TEMPLATE.md").read_text(
|
|
20
64
|
encoding="utf-8"
|
|
@@ -2,11 +2,18 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from copy import deepcopy
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
import tempfile
|
|
5
6
|
import unittest
|
|
6
7
|
|
|
7
8
|
from jsonschema import Draft202012Validator
|
|
8
9
|
|
|
9
|
-
from engineering_process.contracts import
|
|
10
|
+
from engineering_process.contracts import (
|
|
11
|
+
ProcessError,
|
|
12
|
+
formatted_json_bytes,
|
|
13
|
+
read_json,
|
|
14
|
+
validate_document,
|
|
15
|
+
write_json_atomic,
|
|
16
|
+
)
|
|
10
17
|
from engineering_process.distribution import schemas_root
|
|
11
18
|
from engineering_process.project import (
|
|
12
19
|
load_project,
|
|
@@ -21,6 +28,16 @@ SCHEMAS = schemas_root(ROOT)
|
|
|
21
28
|
|
|
22
29
|
|
|
23
30
|
class ContractTests(unittest.TestCase):
|
|
31
|
+
def test_json_documents_have_one_utf8_lf_representation(self) -> None:
|
|
32
|
+
document = {"z": "\u0111", "a": 1}
|
|
33
|
+
expected = b'{\n "a": 1,\n "z": "\xc4\x91"\n}\n'
|
|
34
|
+
self.assertEqual(expected, formatted_json_bytes(document))
|
|
35
|
+
with tempfile.TemporaryDirectory() as directory:
|
|
36
|
+
target = Path(directory) / "document.json"
|
|
37
|
+
write_json_atomic(target, document)
|
|
38
|
+
self.assertEqual(expected, target.read_bytes())
|
|
39
|
+
self.assertEqual(document, read_json(target))
|
|
40
|
+
|
|
24
41
|
def test_every_schema_is_valid_and_is_used(self) -> None:
|
|
25
42
|
expected = {
|
|
26
43
|
"change",
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/_supervisor_contract.py
RENAMED
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/_supervisor_posix.py
RENAMED
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/_supervisor_windows.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/helper_launch.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/publication_compat.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/requirements-dev.txt
RENAMED
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process/requirements-runtime.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process.egg-info/requires.txt
RENAMED
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/engineering_process.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/finish-change/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/plan-change/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/review-change/SKILL.md
RENAMED
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/run-change/SKILL.md
RENAMED
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/start-change/SKILL.md
RENAMED
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/process_assets/skills/verify-change/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/schemas/production-engineering.schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/templates/adopt-process-windows-job.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{engineering_process-1.2.5 → engineering_process-1.2.6}/tests/test_production_engineering.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|