Skip to content

Commit 76532bf

Browse files
docs: Add implementation plan for unified CI/CD workflow
- Phase 0: Research complete (conditional execution, concurrency, authentication) - Phase 1: Design complete (data model, workflow contract, quickstart guide) - Phase 2: Task planning approach documented - Updated agent context with feature information - All constitutional requirements validated
1 parent b0c44ad commit 76532bf

File tree

6 files changed

+1598
-0
lines changed

6 files changed

+1598
-0
lines changed
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
# Workflow Contract: Unified workflow.yml
2+
3+
**Feature**: 001-unified-workflow
4+
**Date**: 2025-10-02
5+
6+
## Overview
7+
8+
This contract defines the expected structure and behavior of the unified workflow.yml file that consolidates CI.yml and workflow.yml functionality.
9+
10+
## Workflow Definition Contract
11+
12+
### Required Top-Level Properties
13+
14+
```yaml
15+
name: Process-PSModule
16+
17+
on:
18+
workflow_call:
19+
secrets: {...}
20+
inputs: {...}
21+
22+
permissions: {...}
23+
24+
concurrency:
25+
group: {...}
26+
cancel-in-progress: {...}
27+
28+
jobs: {...}
29+
```
30+
31+
### Trigger Configuration (on)
32+
33+
**Type**: `workflow_call`
34+
35+
**Required Secrets**:
36+
| Secret | Type | Required | Description |
37+
|--------|------|----------|-------------|
38+
| APIKey | string | true | PowerShell Gallery API key |
39+
| TEST_APP_ENT_CLIENT_ID | string | false | Enterprise App client ID |
40+
| TEST_APP_ENT_PRIVATE_KEY | string | false | Enterprise App private key |
41+
| TEST_APP_ORG_CLIENT_ID | string | false | Organization App client ID |
42+
| TEST_APP_ORG_PRIVATE_KEY | string | false | Organization App private key |
43+
| TEST_USER_ORG_FG_PAT | string | false | Fine-grained PAT (org scope) |
44+
| TEST_USER_USER_FG_PAT | string | false | Fine-grained PAT (user scope) |
45+
| TEST_USER_PAT | string | false | Classic PAT |
46+
47+
**Required Inputs**:
48+
| Input | Type | Required | Default | Description |
49+
|-------|------|----------|---------|-------------|
50+
| Name | string | false | (repo name) | Module name |
51+
| SettingsPath | string | false | .github/PSModule.yml | Settings file path |
52+
| Debug | boolean | false | false | Enable debug output |
53+
| Verbose | boolean | false | false | Enable verbose output |
54+
| Version | string | false | '' | GitHub module version |
55+
| Prerelease | boolean | false | false | Use prerelease GitHub module |
56+
| WorkingDirectory | string | false | '.' | Repository root path |
57+
58+
### Permissions
59+
60+
**Required Permissions**:
61+
```yaml
62+
permissions:
63+
contents: write # Repository operations, releases
64+
pull-requests: write # PR comments
65+
statuses: write # Workflow status updates
66+
pages: write # GitHub Pages deployment
67+
id-token: write # Deployment verification
68+
```
69+
70+
### Concurrency Configuration
71+
72+
**Required Structure**:
73+
```yaml
74+
concurrency:
75+
group: ${{ github.workflow }}-${{ github.ref }}
76+
cancel-in-progress: ${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }}
77+
```
78+
79+
**Behavior**:
80+
- PR builds: `cancel-in-progress` = `true` (new commits cancel old runs)
81+
- Main branch builds: `cancel-in-progress` = `false` (runs complete)
82+
83+
### Job Execution Order
84+
85+
**Required Jobs** (in dependency order):
86+
87+
1. **Get-Settings** (always runs)
88+
- Uses: `./.github/workflows/Get-Settings.yml`
89+
- No dependencies
90+
- Outputs: Settings JSON, test matrices
91+
92+
2. **Build-Module** (conditional)
93+
- Uses: `./.github/workflows/Build-Module.yml`
94+
- Depends on: Get-Settings
95+
- Condition: `Settings.Build.Module.Skip != true`
96+
97+
3. **Build-Docs** (conditional)
98+
- Uses: `./.github/workflows/Build-Docs.yml`
99+
- Depends on: Get-Settings, Build-Module
100+
- Condition: `Settings.Build.Docs.Skip != true`
101+
102+
4. **Build-Site** (conditional)
103+
- Uses: `./.github/workflows/Build-Site.yml`
104+
- Depends on: Get-Settings, Build-Docs
105+
- Condition: `Settings.Build.Site.Skip != true`
106+
107+
5. **Test-SourceCode** (matrix, conditional)
108+
- Uses: `./.github/workflows/Test-SourceCode.yml`
109+
- Depends on: Get-Settings
110+
- Condition: `SourceCodeTestSuites != '[]'`
111+
- Strategy: Matrix based on test suite configuration
112+
113+
6. **Lint-SourceCode** (matrix, conditional)
114+
- Uses: `./.github/workflows/Lint-SourceCode.yml`
115+
- Depends on: Get-Settings
116+
- Condition: `SourceCodeTestSuites != '[]'`
117+
- Strategy: Matrix based on test suite configuration
118+
119+
7. **Test-Module** (conditional)
120+
- Uses: `./.github/workflows/Test-Module.yml`
121+
- Depends on: Get-Settings, Build-Module
122+
- Condition: `Settings.Test.Module.Skip != true`
123+
124+
8. **BeforeAll-ModuleLocal** (conditional)
125+
- Uses: `./.github/workflows/BeforeAll-ModuleLocal.yml` (if exists)
126+
- Depends on: Get-Settings, Build-Module
127+
- Condition: `Settings.Test.ModuleLocal.Skip != true AND tests/BeforeAll.ps1 exists`
128+
129+
9. **Test-ModuleLocal** (matrix, conditional)
130+
- Uses: `./.github/workflows/Test-ModuleLocal.yml`
131+
- Depends on: Get-Settings, Build-Module, BeforeAll-ModuleLocal
132+
- Condition: `Settings.Test.ModuleLocal.Skip != true`
133+
- Strategy: Matrix across platforms (ubuntu, windows, macos)
134+
135+
10. **AfterAll-ModuleLocal** (conditional, always runs)
136+
- Uses: `./.github/workflows/AfterAll-ModuleLocal.yml` (if exists)
137+
- Depends on: Test-ModuleLocal
138+
- Condition: `always() AND Settings.Test.ModuleLocal.Skip != true AND tests/AfterAll.ps1 exists`
139+
140+
11. **Get-TestResults** (always after tests)
141+
- Uses: `./.github/workflows/Get-TestResults.yml`
142+
- Depends on: Test-SourceCode, Lint-SourceCode, Test-Module, Test-ModuleLocal
143+
- Condition: `always()` (runs even if tests fail)
144+
145+
12. **Get-CodeCoverage** (always after results)
146+
- Uses: `./.github/workflows/Get-CodeCoverage.yml`
147+
- Depends on: Get-TestResults
148+
- Condition: `always()` (runs even if tests fail)
149+
150+
13. **Publish-Module** (conditional, main branch only)
151+
- Uses: `./.github/workflows/Publish-Module.yml` (if exists)
152+
- Depends on: Build-Module, Get-TestResults
153+
- Condition: `github.event_name == 'pull_request' AND github.event.pull_request.merged == true AND Settings.Publish.Module.Skip != true AND tests passed`
154+
155+
14. **Publish-Site** (conditional, main branch only)
156+
- Uses: `./.github/workflows/Publish-Site.yml` (if exists)
157+
- Depends on: Build-Site, Get-TestResults
158+
- Condition: `github.event_name == 'pull_request' AND github.event.pull_request.merged == true AND Settings.Publish.Site.Skip != true AND tests passed`
159+
160+
### Conditional Execution Matrix
161+
162+
| Context | Event | Get-Settings | Build | Test | Publish-Module | Publish-Site |
163+
|---------|-------|--------------|-------|------|----------------|--------------|
164+
| PR opened | pull_request | ✅ | ✅ | ✅ | ❌ | ❌ |
165+
| PR sync | pull_request | ✅ | ✅ | ✅ | ❌ | ❌ |
166+
| PR merged | pull_request (merged=true) | ✅ | ✅ | ✅ | ✅ (if tests pass) | ✅ (if tests pass) |
167+
| PR closed (not merged) | pull_request (merged=false) | ❌ | ❌ | ❌ | ❌ | ❌ |
168+
169+
## Breaking Changes from CI.yml
170+
171+
### Removed
172+
- **CI.yml file**: Deleted entirely
173+
- **Separate CI workflow**: Functionality consolidated into workflow.yml
174+
175+
### Maintained (No Changes)
176+
- All workflow inputs
177+
- All secrets
178+
- All permissions
179+
- All job definitions
180+
- All reusable workflow references
181+
- All conditional logic (except publishing conditions)
182+
183+
### Modified
184+
- **Publishing trigger**: Changed from separate workflow to conditional execution within unified workflow
185+
- **Concurrency group**: Applied to unified workflow instead of separate workflows
186+
187+
## Consumer Repository Impact
188+
189+
### Required Changes
190+
1. Delete `.github/workflows/CI.yml`
191+
2. Update any references to `CI.yml` in:
192+
- Documentation
193+
- External CI/CD integrations
194+
- Monitoring/alerting systems
195+
- Branch protection rules (use `workflow.yml` status checks)
196+
197+
### No Changes Required
198+
- `.github/PSModule.yml` configuration
199+
- Test files
200+
- Module source code
201+
- Documentation (except workflow references)
202+
203+
## Validation Contract
204+
205+
### PR Context Validation
206+
```yaml
207+
# Test that publish jobs are skipped on PR
208+
assert:
209+
- job: Publish-Module
210+
status: skipped
211+
reason: "Condition not met (PR not merged)"
212+
- job: Publish-Site
213+
status: skipped
214+
reason: "Condition not met (PR not merged)"
215+
```
216+
217+
### Merge Context Validation
218+
```yaml
219+
# Test that publish jobs execute on merge (when tests pass)
220+
assert:
221+
- job: Publish-Module
222+
status: success
223+
condition: "github.event.pull_request.merged == true AND tests passed"
224+
- job: Publish-Site
225+
status: success
226+
condition: "github.event.pull_request.merged == true AND tests passed"
227+
```
228+
229+
### Concurrency Validation
230+
```yaml
231+
# Test that PR builds cancel in-progress runs
232+
assert:
233+
- concurrency_group: "Process-PSModule-refs/heads/feature-branch"
234+
- cancel_in_progress: true
235+
- previous_run_status: cancelled
236+
237+
# Test that main branch builds do not cancel
238+
assert:
239+
- concurrency_group: "Process-PSModule-refs/heads/main"
240+
- cancel_in_progress: false
241+
- previous_run_status: completed
242+
```
243+
244+
### Failure Handling Validation
245+
```yaml
246+
# Test that publish is skipped when tests fail
247+
assert:
248+
- job: Test-Module
249+
status: failure
250+
- job: Publish-Module
251+
status: skipped
252+
reason: "Dependency failed"
253+
```
254+
255+
## Error Handling
256+
257+
### Test Failure on PR
258+
- **Behavior**: Workflow fails, PR status check fails, merge blocked
259+
- **Publish jobs**: Skipped (conditions not met)
260+
- **Notification**: GitHub default mechanisms
261+
262+
### Test Failure on Merge
263+
- **Behavior**: Workflow fails, publish jobs skipped
264+
- **Rollback**: Not automatic; maintainer must fix and re-run or revert merge
265+
- **Notification**: GitHub default mechanisms
266+
267+
### Publish Failure
268+
- **Behavior**: Workflow fails
269+
- **Retry**: Maintainer manually re-runs entire workflow (tests + publish)
270+
- **Partial retry**: Not supported; entire workflow re-executes
271+
272+
## Backward Compatibility
273+
274+
### Compatible
275+
- All existing consuming repositories can migrate by deleting CI.yml
276+
- No changes to module structure, test frameworks, or configuration files
277+
- Publishing behavior unchanged (still uses APIKey secret)
278+
279+
### Incompatible
280+
- External systems referencing CI.yml must be updated
281+
- Branch protection rules must reference workflow.yml checks instead of CI.yml checks
282+
283+
## Migration Contract
284+
285+
### Pre-Migration Checklist
286+
- [ ] Identify all references to CI.yml in external systems
287+
- [ ] Document external integrations that must be updated
288+
- [ ] Communicate breaking change to consuming repository maintainers
289+
- [ ] Prepare migration guide
290+
291+
### Migration Steps
292+
1. Update workflow.yml with unified logic
293+
2. Test in Process-PSModule repository
294+
3. Validate all scenarios in quickstart.md
295+
4. Release as new major version
296+
5. Update consuming repositories:
297+
- Delete CI.yml
298+
- Update branch protection rules
299+
- Update external integrations
300+
- Test workflow execution
301+
302+
### Post-Migration Validation
303+
- [ ] CI.yml file deleted
304+
- [ ] Workflow.yml triggers on PR events
305+
- [ ] Tests execute on PR open/sync
306+
- [ ] Publishing executes on PR merge
307+
- [ ] Concurrency control working
308+
- [ ] External integrations updated
309+
310+
## References
311+
312+
- [GitHub Actions Workflow Syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
313+
- [Reusing Workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows)
314+
- [Feature Specification](../spec.md)
315+
- [Data Model](../data-model.md)

0 commit comments

Comments
 (0)