Repository navigation
151 lines (135 loc) · 6.6 KB
/
Copy pathplatform-manifest.yml
File metadata and controls
151 lines (135 loc) · 6.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
name: Platform manifest and source boundary
# Validates platform-manifest.json against the real published artifacts
# (PyPI, status.json) and enforces the open-core source boundary.
# See docs/platform-manifest.md and scripts/check_source_boundary.py.
on:
pull_request:
branches:
- '**'
push:
branches:
- main
schedule:
# DAILY drift check. The manifest goes stale when a component releases in
# ANOTHER repository, so no commit
# lands here and only the schedule can notice. This was weekly, which
# meant up to seven days of serving wrong sha256 digests from
# raw.githubusercontent; flow 1.24.0 published on 2026-07-27 and the
# manifest still advertised 1.23.0's digests. One small stdlib-only job
# costs seconds a day.
- cron: '17 6 * * *'
workflow_dispatch:
# Receiver for a component repository to announce its release immediately
# rather than waiting for the daily sweep.
#
# NOT YET WIRED: as of 2026-07-28 no component repository sends this. No
# component has a dispatch step in its release
# workflow, so the daily cron above is in practice the ONLY thing that
# notices a component release. That is how flow 1.25.0 and 1.25.1 published
# on 2026-07-27 after the manifest was regenerated at 15:42 that day and the
# manifest went stale again within hours, red on every PR until someone
# regenerated by hand.
#
# The sending side would be one step in each component's release workflow:
# gh api repos/OpenAdaptAI/OpenAdapt/dispatches -f event_type=component-released
# It cannot use that repository's default GITHUB_TOKEN, which is scoped to
# its own repository; cross-repository dispatch needs a token with `contents:
# write` on OpenAdaptAI/OpenAdapt stored as a secret in each component repo.
# Provisioning that secret is a credential decision, not a code change, so it
# is tracked outside this file rather than half-implemented here.
#
# Note that even a wired sender only makes DETECTION immediate. Repair stays
# manual: this workflow validates and files an issue, it does not regenerate.
# Auto-opening a fix PR is currently impossible anyway -- Actions is not
# permitted to create pull requests in this repository
# (`can_approve_pull_request_reviews: false`), so such a job would be
# permanently red rather than helpful.
repository_dispatch:
types: [component-released]
concurrency:
group: >-
platform-manifest-${{ github.event_name }}-${{
github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
validate-platform-manifest:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.12'
# Cheapest decisive check first: structure, signature honesty, and
# repo agreement need no network and cannot be flaky.
- name: Validate platform manifest structure (offline)
run: python scripts/validate_platform_manifest.py --offline
# Standard library only: no dependency install, no lockfile, no cache.
- name: Validate platform manifest against published artifacts
env:
GITHUB_TOKEN: ${{ github.token }}
run: python scripts/validate_platform_manifest.py
- name: Prove the drift guard fails when it should
# The daily/dispatched production check is intentionally stdlib-only.
# This characterization suite belongs on source changes, not every
# remote drift probe, so scheduled checks stay fast and network-light.
if: github.event_name == 'pull_request' || github.event_name == 'push'
run: |
python -m pip install --quiet 'pytest>=8.0.0'
python -m pytest \
tests/test_platform_manifest_drift.py \
tests/test_platform_version_display.py -q
report-manifest-drift:
# A red scheduled run in a repository nobody has open is not a signal.
# The 2026-07-27 drift DID turn the cron red and still shipped, because
# main was already red from the previous night's release. File an issue
# so drift has an owner and a paper trail instead of a stale red dot.
needs: validate-platform-manifest
if: >-
${{ always() && needs.validate-platform-manifest.result == 'failure' &&
(github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch' ||
github.event_name == 'repository_dispatch') }}
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: File or update the manifest drift issue
env:
GH_TOKEN: ${{ github.token }}
run: |
TITLE="platform-manifest.json has drifted from the published releases"
BODY="The scheduled platform manifest check failed: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
\`platform-manifest.json\` is served publicly from raw.githubusercontent and is OpenAdapt's only cryptographic claim about the current release. While it is stale, anyone verifying a downloaded wheel or sdist against it fails.
Fix: \`python scripts/generate_platform_manifest.py && python scripts/validate_platform_manifest.py\`, then open a PR."
EXISTING=$(gh issue list --repo "${{ github.repository }}" --state open \
--search "in:title \"$TITLE\"" --json number --jq '.[0].number // empty')
if [ -n "$EXISTING" ]; then
gh issue comment "$EXISTING" --repo "${{ github.repository }}" --body "$BODY"
else
gh issue create --repo "${{ github.repository }}" --title "$TITLE" --body "$BODY"
fi
check-source-boundary:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.12'
# The guard reads its rules from source-policy.public.json (rendered from
# the canonical private manifest) and fails closed when that file is
# missing or incomplete. Stdlib only: no dependency install.
- name: Check open-core source boundary
run: python scripts/check_source_boundary.py
# Prove the guard still blocks what it blocked before the rules moved out
# of the script, and that it fails closed without them.
- name: Prove the boundary guard fails when it should
if: github.event_name == 'pull_request' || github.event_name == 'push'
run: |
python -m pip install --quiet 'pytest>=8.0.0'
python -m pytest tests/test_source_boundary.py -q