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
8 changes: 7 additions & 1 deletion .github/workflows/pr-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ jobs:
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version-file: .python-version
Expand All @@ -116,6 +118,10 @@ jobs:
with:
cmakeVersion: '4.3.3'
ninjaVersion: '1.13.1'
- name: Verify reviewed dependency closure and publication refusal fixtures
run: |
python eng/dependency_policy.py
python -m unittest discover -s eng -p test_dependency_policy.py -v
- name: Reject incomplete declarations and invalid reference graphs
run: python -m unittest discover -s eng -p test_licence_boundary.py -v
- name: Verify actual managed build declarations
Expand Down Expand Up @@ -215,7 +221,7 @@ jobs:
- name: Verify actual source inventory and active native registrations
shell: pwsh
run: |
python eng/check_provenance.py --owner DesktopPlatform
python eng/check_provenance.py --owner DesktopPlatform --base "${{ startsWith(github.ref, 'refs/tags/') && github.sha || '' }}"
if ($LASTEXITCODE) { throw 'Source provenance check failed.' }
python eng/native_provenance.py
if ($LASTEXITCODE) { throw 'Native provenance registration failed.' }
Expand Down
30 changes: 18 additions & 12 deletions .github/workflows/publish-nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ name: Publish NuGet
on:
push:
branches: [main]
tags: ["v*"]
permissions:
contents: read
# Each main push owns a distinct version. Keep runs independent so a later merge
# cannot replace a pending release in a shared concurrency group.
# Serialize main and deliberate tags without cancelling queued publications.
concurrency:
group: desktopplatform-nuget-publication
queue: max
cancel-in-progress: false
jobs:
preflight:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.release.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version-file: .python-version
Expand All @@ -23,24 +30,18 @@ jobs:
NUGET_USER: ${{ vars.NUGET_USER }}
shell: pwsh
run: |
if ($env:GITHUB_EVENT_NAME -ne 'push' -or $env:GITHUB_REF -ne 'refs/heads/main' -or $env:GITHUB_REPOSITORY -ne 'ArcForges/DesktopPlatform') {
throw 'Public NuGet publication is restricted to pushes to ArcForges/DesktopPlatform main.'
}
if ([string]::IsNullOrWhiteSpace($env:NUGET_USER) -or $env:NUGET_USER -eq 'YOUR_NUGET_USERNAME') {
throw 'Set repository variable NUGET_USER and the documented nuget.org trusted publisher.'
}
$version = "1.0.0-ci.$env:GITHUB_RUN_NUMBER.$env:GITHUB_RUN_ATTEMPT"
python eng/packaging/packages.py version --version $version
if ($LASTEXITCODE) { throw 'Invalid package version.' }
"version=$version" >> $env:GITHUB_OUTPUT
"Package version: $version" >> $env:GITHUB_STEP_SUMMARY
python eng/packaging/release_channels.py
if ($LASTEXITCODE) { throw 'Invalid publisher identity or dependency closure.' }
candidate:
needs: preflight
uses: ./.github/workflows/pr-gate.yml
with:
version: ${{ needs.preflight.outputs.version }}
publish:
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'ArcForges/DesktopPlatform'
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.repository == 'ArcForges/DesktopPlatform'
needs: candidate
runs-on: ubuntu-latest
environment: nuget
Expand All @@ -49,6 +50,9 @@ jobs:
id-token: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version-file: .python-version
Expand All @@ -62,7 +66,9 @@ jobs:
- name: Recheck source identity, allowlist, contents and hashes before authentication
env:
PACKAGE_VERSION: ${{ needs.candidate.outputs.version }}
run: python eng/packaging/packages.py verify --version "$PACKAGE_VERSION" --commit "$GITHUB_SHA"
run: |
python eng/packaging/release_channels.py --expected-version "$PACKAGE_VERSION"
python eng/packaging/packages.py verify --version "$PACKAGE_VERSION" --commit "$GITHUB_SHA"
- name: Exchange GitHub OIDC identity for a short-lived NuGet API key
id: login
uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1
Expand Down
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ Follow the [current CI/local authority](https://github.com/ArcForges/ArcForges-D
- Preserve locks, required signatures, licence/provenance and one identity/integrity check at each real trust handoff. Do not routinely download public artifacts or repeat archive/hash/consumer verification after publication. Narrow FFmpeg licence/configuration and Windows signature inspection remain legal admission checks.
- Do not reinstall vcpkg, SDKs or toolchains to expand validation. Do not create tags or republish solely for verification. Stop on a network failure and report the exact operation; no proxy configuration, port 7890, wsl.exe or WSL wrappers.
- Record removed coverage honestly. Review the complete latest PR and merge only after applicable checks succeed. Post-merge work stops after commit/job/publication status and a clean primary fast-forward; retain branches/worktrees.

## Dependency admission (WP02.05)

- Keep `eng/policy/dependency-policy.json` bound to the complete actual dependency inputs. A dependency or framework change requires a reviewed replacement receipt, closure/licence and maintenance review and every upgrade checklist item. Hash refresh alone is insufficient.
- Preserve existing source/native provenance and public/internal import gates. Stable closures cannot import prerelease dependencies; only recorded exact foundation candidates are permitted in development.
- Framework major upgrades require explicit runtime/AOT/trim and affected Android Kotlin/JVM/ART/R8 assessment under VG-08. Record conditional local coverage honestly without adding forbidden CI or provisioning tools.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ placeholders remain excluded. These runtime packages expose the existing ABI, no
Every push to `main`, including a merged PR, automatically allocates a prerelease version. Native
compilation and source checks must finish before packing; targeted offline checks and the
aggregate gate must pass before the same package bytes are published to nuget.org through OIDC.
No manual workflow run, version entry or publish checkbox is required.
No manual workflow run, version entry or publish checkbox is required for main candidates.
Deliberate canonical stable tags use the same gated pipeline; see [dependency admission](docs/dependency-policy.md).

Contracts is a separate repository with handwritten proto as the business RPC authority. It also owns
schema validation, compatibility checks, generators and generated SDK packaging:
Expand Down
39 changes: 39 additions & 0 deletions docs/dependency-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Dependency admission and deliberate releases

`eng/policy/dependency-policy.json` admits the exact current NuGet lock closure and
admits the exact hash-required Python hook-tool closure and binds normalized source hashes of manifests, locks, projects and native/source
provenance records. The cached NuGet nuspec expressions and their hashes record
the reviewed metadata; no restore or public artifact download is part of this
offline policy check. Existing provenance, native licence/configuration, package
allowlist, Authenticode and source/recipe checks remain required independently.

Run `python eng/dependency_policy.py` and
`python -m unittest discover -s eng -p test_dependency_policy.py -v` for policy
changes. Dependency additions or upgrades must replace the reviewed input receipt,
review the complete affected closure and preserve required notices. Record the
owner, maintenance assessment and outcomes or explicit inapplicability for every
upgrade checklist item. Merely refreshing hashes is not an admission review.
Framework major upgrades additionally assess runtime posture, Native AOT/trim,
native ABI and affected Android Kotlin/JVM/ART/R8 implications under VG-08.
Relevant runtime diagnostics remain local and conditional on existing tools;
missing coverage is recorded honestly. No toolchain installation is implied.

Main publishes exact `1.0.0-ci.RUN.ATTEMPT` candidates to nuget.org through the
existing trusted publisher. Deliberate canonical `vX.Y.Z` tags may publish `X.Y.Z`
only when the tagged commit belongs to main history. The `nuget` environment
must permit main and `v*` tags; the portable guard rejects noncanonical tags,
other repositories/events and stable closures containing prerelease packages.
The same native, managed, packaging and source gates produce the candidate and
the publisher validates its identity before obtaining OIDC credentials. It never
rebuilds, skips colliding versions or overwrites published bytes. The stable path
is configured and tested with offline fixtures, not exercised by creating tags.

Generated business contracts belong to Contracts; this repository does not admit
public/internal schema implementations. The closed runtime ownership and licence
inventories remain the import boundary. Package access does not imply stability.

Review receipts under `eng/policy/dependency-reviews/` are append-only. The checker
compares the accepted Git tree and preserves every historical coordinate/integrity
binding: even a newly reviewed snapshot cannot change bytes under an existing
NuGet/npm version or Maven artifact coordinate. Add a successor receipt for an
actual reviewed upgrade; never edit or delete an earlier receipt.
Loading
Loading