toolframe-core 0.6.2__tar.gz → 0.6.4__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.
- toolframe_core-0.6.4/.dockerignore +15 -0
- toolframe_core-0.6.4/.github/actions/scan-container/action.yml +44 -0
- toolframe_core-0.6.4/.github/dependabot.yml +50 -0
- toolframe_core-0.6.4/.github/workflows/ci.yml +52 -0
- toolframe_core-0.6.4/.github/workflows/container-security.yml +52 -0
- toolframe_core-0.6.4/.github/workflows/container.yml +221 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/.github/workflows/launcher.yml +3 -0
- toolframe_core-0.6.4/.github/workflows/pr-policy.yml +31 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/.github/workflows/publish.yml +68 -28
- toolframe_core-0.6.4/.github/workflows/quality.yml +49 -0
- toolframe_core-0.6.4/.github/workflows/validate.yml +214 -0
- toolframe_core-0.6.4/.pre-commit-config.yaml +29 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/CHANGELOG.md +17 -0
- toolframe_core-0.6.4/CONTRIBUTING.md +47 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/Cargo.lock +1 -1
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/Cargo.toml +1 -1
- toolframe_core-0.6.4/Dockerfile +107 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/PKG-INFO +11 -1
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/README.md +10 -0
- toolframe_core-0.6.4/cchk.toml +10 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/architecture.md +3 -0
- toolframe_core-0.6.4/docs/artifacts.md +73 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/ci.md +59 -8
- toolframe_core-0.6.4/docs/container.md +247 -0
- toolframe_core-0.6.4/docs/intel-companion.md +100 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/postgresql-state.md +1 -1
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/releasing.md +33 -13
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/pyproject.toml +1 -1
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/build-launcher.py +10 -11
- toolframe_core-0.6.4/scripts/check-container-security.py +128 -0
- toolframe_core-0.6.4/scripts/check_branch_name.py +59 -0
- toolframe_core-0.6.4/scripts/ci/artifacts.py +496 -0
- toolframe_core-0.6.4/scripts/ci/intel-companion.json +29 -0
- toolframe_core-0.6.4/scripts/ci/intel_companion.py +365 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/ci/prepare-launcher.py +2 -1
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/ci/validate.py +2 -1
- toolframe_core-0.6.4/scripts/container-healthcheck.py +23 -0
- toolframe_core-0.6.4/scripts/harden-container.py +41 -0
- toolframe_core-0.6.4/scripts/prepare-container.py +88 -0
- toolframe_core-0.6.4/scripts/verify-container.py +335 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/main.rs +8 -8
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/__init__.py +1 -1
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/api.py +1 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/host.py +3 -1
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_acceptance.py +40 -0
- toolframe_core-0.6.4/tests/test_ci_artifacts.py +563 -0
- toolframe_core-0.6.4/tests/test_container_release.py +98 -0
- toolframe_core-0.6.4/tests/test_container_security.py +105 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_core_state.py +1 -0
- toolframe_core-0.6.4/tests/test_intel_companion.py +314 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_mcp_auth.py +4 -3
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/uv.lock +1 -1
- toolframe_core-0.6.2/.github/workflows/ci.yml +0 -20
- toolframe_core-0.6.2/.github/workflows/validate.yml +0 -102
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/.gitignore +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/LICENSE +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/NOTICE +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/companion-wheels.txt +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0001-explicit-dashboard-access-mode.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0002-scoped-passwords-and-public-business-entrances.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0003-public-fallback-on-auth-error-or-disablement.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0004-separate-auth-ownership-from-dashboard-presentation.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0005-password-only-login-and-secret-reuse.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0006-require-explicit-plugin-authorization-contracts.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0007-independent-mcp-bearer-authentication.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0008-shared-oidc-authentication.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0009-replaceable-core-journal.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0010-multiple-sql-providers.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0011-safe-new-application-access.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0012-optional-runtime-tracing.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/adr/0013-context-logging.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/authentication.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/dependency-graph.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/glossary.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/mcp-authentication.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/object-storage.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/offline-maintenance.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/oidc-authentication.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/runtime.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/sql-storage.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/testing.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/docs/tracing.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/packaging/launcher/NOTICE +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/packaging/launcher/README.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/packaging/launcher/pyproject.toml +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/build-release.sh +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/ci/check-launcher-wheel.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/ci/check-postgres.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/ci/check-release.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/ci/dependencies.json +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/dev-wheelhouse.sh +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-auth-upgrade.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-auth.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-dependencies.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-network.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-operation-history.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-release.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-retained-plugins.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-scaffold.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/scripts/verify-skill.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/companions.rs +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/_state_postgres.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/_state_sqlite.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/access.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/LICENSE +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/SKILL.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/agents/openai.yaml +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/LICENSE +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/pyproject.toml +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/__init__.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/docs/usage.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/migrations/0001_init.sql +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/page.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/plugin.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/service.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/evals/cases.json +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/design.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/operations.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/plugin-api.md +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/cli.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/config.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/diagnostics.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/graph.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/maintenance.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/mcp_access.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/network.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/oidc_access.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/packages.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/process.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/redaction.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/scaffold.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/skills.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/state.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/state_admin.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/stores.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/templates.json +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/toolframe_core/templates.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/src/uv.rs +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_access_policy.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_architecture.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_auth.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_bundles.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_cli.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_diagnostics.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_foundations.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_host.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_maintenance.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_managed_tasks.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_mixed_storage.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_network.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_object_store.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_oidc.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_operation_history.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_process.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_redaction.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_retained_plugins.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_scaffold.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_skills.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_storage_bindings.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/tests/test_tracing.py +0 -0
- {toolframe_core-0.6.2 → toolframe_core-0.6.4}/uv-release-manifest.txt +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
**
|
|
2
|
+
!Dockerfile
|
|
3
|
+
!scripts/
|
|
4
|
+
!scripts/container-healthcheck.py
|
|
5
|
+
!scripts/harden-container.py
|
|
6
|
+
!build/
|
|
7
|
+
!build/container/
|
|
8
|
+
!build/container/amd64/
|
|
9
|
+
!build/container/amd64/toolframe
|
|
10
|
+
!build/container/amd64/LICENSE
|
|
11
|
+
!build/container/amd64/NOTICE
|
|
12
|
+
!build/container/arm64/
|
|
13
|
+
!build/container/arm64/toolframe
|
|
14
|
+
!build/container/arm64/LICENSE
|
|
15
|
+
!build/container/arm64/NOTICE
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Scan a Toolframe container
|
|
2
|
+
description: Retain the full vulnerability inventory and enforce publication policy
|
|
3
|
+
inputs:
|
|
4
|
+
image:
|
|
5
|
+
description: Local image tag or public registry reference
|
|
6
|
+
required: true
|
|
7
|
+
platform:
|
|
8
|
+
description: Linux platform to scan
|
|
9
|
+
required: true
|
|
10
|
+
image-source:
|
|
11
|
+
description: Trivy image source (docker or remote)
|
|
12
|
+
required: true
|
|
13
|
+
runs:
|
|
14
|
+
using: composite
|
|
15
|
+
steps:
|
|
16
|
+
- uses: aquasecurity/setup-trivy@81e514348e19b6112ce2a7e3ecbafe19c1e1f567
|
|
17
|
+
with:
|
|
18
|
+
version: v0.76.0
|
|
19
|
+
cache: false
|
|
20
|
+
- name: Scan every severity and keep the package inventory
|
|
21
|
+
shell: bash
|
|
22
|
+
env:
|
|
23
|
+
SCAN_IMAGE: ${{ inputs.image }}
|
|
24
|
+
SCAN_PLATFORM: ${{ inputs.platform }}
|
|
25
|
+
SCAN_SOURCE: ${{ inputs.image-source }}
|
|
26
|
+
run: |
|
|
27
|
+
mkdir -p build/security
|
|
28
|
+
trivy image --image-src "$SCAN_SOURCE" --platform "$SCAN_PLATFORM" \
|
|
29
|
+
--scanners vuln --ignorefile '' --disable-telemetry --list-all-pkgs \
|
|
30
|
+
--timeout 10m --format json --output build/security/scan.json "$SCAN_IMAGE"
|
|
31
|
+
trivy version --format json > build/security/scanner.json
|
|
32
|
+
trivy convert --format cyclonedx --output build/security/sbom.cdx.json build/security/scan.json
|
|
33
|
+
- name: Enforce the security policy
|
|
34
|
+
shell: bash
|
|
35
|
+
run: |
|
|
36
|
+
python3 scripts/check-container-security.py build/security/scan.json \
|
|
37
|
+
--summary build/security/summary.md
|
|
38
|
+
- name: Add findings to the run summary
|
|
39
|
+
if: always()
|
|
40
|
+
shell: bash
|
|
41
|
+
run: |
|
|
42
|
+
if [ -f build/security/summary.md ]; then
|
|
43
|
+
cat build/security/summary.md >> "$GITHUB_STEP_SUMMARY"
|
|
44
|
+
fi
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: docker
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
day: monday
|
|
8
|
+
time: '04:23'
|
|
9
|
+
timezone: Etc/UTC
|
|
10
|
+
open-pull-requests-limit: 4
|
|
11
|
+
commit-message:
|
|
12
|
+
prefix: fix(container)
|
|
13
|
+
pull-request-branch-name:
|
|
14
|
+
prefix: chore
|
|
15
|
+
template: '{prefix}/{name}'
|
|
16
|
+
groups:
|
|
17
|
+
# Catch every version and security update, including major versions.
|
|
18
|
+
# To split a dependency out, add a named group before these catch-alls;
|
|
19
|
+
# exclusions would fall back to noncompliant solo dependency/version names.
|
|
20
|
+
container-dependencies:
|
|
21
|
+
applies-to: version-updates
|
|
22
|
+
patterns: ['*']
|
|
23
|
+
container-security:
|
|
24
|
+
applies-to: security-updates
|
|
25
|
+
patterns: ['*']
|
|
26
|
+
ignore:
|
|
27
|
+
# The 0.6.3 launcher accepts uv >=0.12.2,<0.13.0.
|
|
28
|
+
# Widen this only alongside a compatible launcher release.
|
|
29
|
+
- dependency-name: astral-sh/uv
|
|
30
|
+
versions: ['>=0.13.0']
|
|
31
|
+
- package-ecosystem: github-actions
|
|
32
|
+
directory: /
|
|
33
|
+
schedule:
|
|
34
|
+
interval: weekly
|
|
35
|
+
day: monday
|
|
36
|
+
time: '04:23'
|
|
37
|
+
timezone: Etc/UTC
|
|
38
|
+
open-pull-requests-limit: 4
|
|
39
|
+
commit-message:
|
|
40
|
+
prefix: chore(ci)
|
|
41
|
+
pull-request-branch-name:
|
|
42
|
+
prefix: chore
|
|
43
|
+
template: '{prefix}/{name}'
|
|
44
|
+
groups:
|
|
45
|
+
actions-dependencies:
|
|
46
|
+
applies-to: version-updates
|
|
47
|
+
patterns: ['*']
|
|
48
|
+
actions-security:
|
|
49
|
+
applies-to: security-updates
|
|
50
|
+
patterns: ['*']
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
# Publication independently verifies/promotes the selected release tag.
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
inputs:
|
|
10
|
+
rebuild:
|
|
11
|
+
description: Run all checks and builds even if validated artifacts exist
|
|
12
|
+
type: boolean
|
|
13
|
+
default: false
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
pull-requests: read
|
|
18
|
+
actions: read
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
quality:
|
|
26
|
+
uses: ./.github/workflows/quality.yml
|
|
27
|
+
|
|
28
|
+
validate:
|
|
29
|
+
needs: quality
|
|
30
|
+
uses: ./.github/workflows/validate.yml
|
|
31
|
+
with:
|
|
32
|
+
reuse-stage: ${{ github.ref == 'refs/heads/main' && 'main' || 'none' }}
|
|
33
|
+
rebuild: ${{ inputs.rebuild || false }}
|
|
34
|
+
secrets: inherit
|
|
35
|
+
|
|
36
|
+
result:
|
|
37
|
+
name: CI result
|
|
38
|
+
if: always()
|
|
39
|
+
needs: [quality, validate]
|
|
40
|
+
runs-on: ubuntu-24.04
|
|
41
|
+
timeout-minutes: 2
|
|
42
|
+
steps:
|
|
43
|
+
# Require this check when configuring branch protection. A skipped
|
|
44
|
+
# validation job must not turn a failed prerequisite into a green check.
|
|
45
|
+
- name: Require successful checks and validation
|
|
46
|
+
env:
|
|
47
|
+
QUALITY_RESULT: ${{ needs.quality.result }}
|
|
48
|
+
VALIDATE_RESULT: ${{ needs.validate.result }}
|
|
49
|
+
run: |
|
|
50
|
+
echo "Quality: $QUALITY_RESULT; validation: $VALIDATE_RESULT"
|
|
51
|
+
test "$QUALITY_RESULT" = success
|
|
52
|
+
test "$VALIDATE_RESULT" = success
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Container security
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '23 3 * * *'
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: container-security-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
scan:
|
|
17
|
+
name: ${{ matrix.variant }} (${{ matrix.arch }})
|
|
18
|
+
runs-on: ubuntu-24.04
|
|
19
|
+
timeout-minutes: 20
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
variant: [standard, distroless]
|
|
24
|
+
arch: [amd64, arm64]
|
|
25
|
+
include:
|
|
26
|
+
- variant: standard
|
|
27
|
+
tag: latest
|
|
28
|
+
- variant: distroless
|
|
29
|
+
tag: distroless
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
32
|
+
with:
|
|
33
|
+
persist-credentials: false
|
|
34
|
+
- name: Select the public image
|
|
35
|
+
id: image
|
|
36
|
+
env:
|
|
37
|
+
OWNER: ${{ github.repository_owner }}
|
|
38
|
+
TAG: ${{ matrix.tag }}
|
|
39
|
+
run: echo "ref=ghcr.io/${OWNER,,}/toolframe:$TAG" >> "$GITHUB_OUTPUT"
|
|
40
|
+
- uses: ./.github/actions/scan-container
|
|
41
|
+
with:
|
|
42
|
+
image: ${{ steps.image.outputs.ref }}
|
|
43
|
+
platform: linux/${{ matrix.arch }}
|
|
44
|
+
image-source: remote
|
|
45
|
+
- name: Save findings and the inventory
|
|
46
|
+
if: always()
|
|
47
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
48
|
+
with:
|
|
49
|
+
name: container-security-${{ matrix.variant }}-${{ matrix.arch }}
|
|
50
|
+
path: build/security/
|
|
51
|
+
if-no-files-found: warn
|
|
52
|
+
retention-days: 7
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
name: Container images
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- Dockerfile
|
|
7
|
+
- .dockerignore
|
|
8
|
+
- .github/workflows/container.yml
|
|
9
|
+
- .github/workflows/container-security.yml
|
|
10
|
+
- .github/actions/scan-container/**
|
|
11
|
+
- scripts/*container*.py
|
|
12
|
+
- tests/test_container_*.py
|
|
13
|
+
workflow_call:
|
|
14
|
+
inputs:
|
|
15
|
+
publish:
|
|
16
|
+
type: boolean
|
|
17
|
+
default: false
|
|
18
|
+
release_artifacts:
|
|
19
|
+
description: Use the validated launcher artifacts from this workflow run
|
|
20
|
+
type: boolean
|
|
21
|
+
default: false
|
|
22
|
+
workflow_dispatch:
|
|
23
|
+
inputs:
|
|
24
|
+
publish:
|
|
25
|
+
description: Publish both tested variants to GHCR
|
|
26
|
+
type: boolean
|
|
27
|
+
default: false
|
|
28
|
+
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
build:
|
|
34
|
+
name: ${{ matrix.variant }} (${{ matrix.arch }})
|
|
35
|
+
runs-on: ${{ matrix.runner }}
|
|
36
|
+
timeout-minutes: 30
|
|
37
|
+
permissions:
|
|
38
|
+
contents: read
|
|
39
|
+
packages: write
|
|
40
|
+
strategy:
|
|
41
|
+
fail-fast: false
|
|
42
|
+
matrix:
|
|
43
|
+
variant: [standard, distroless]
|
|
44
|
+
arch: [amd64, arm64]
|
|
45
|
+
include:
|
|
46
|
+
- arch: amd64
|
|
47
|
+
runner: ubuntu-24.04
|
|
48
|
+
target: x86_64-unknown-linux-gnu
|
|
49
|
+
- arch: arm64
|
|
50
|
+
runner: ubuntu-24.04-arm
|
|
51
|
+
target: aarch64-unknown-linux-gnu
|
|
52
|
+
outputs:
|
|
53
|
+
version: ${{ steps.metadata.outputs.version }}
|
|
54
|
+
image: ${{ steps.metadata.outputs.image }}
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
57
|
+
with:
|
|
58
|
+
persist-credentials: false
|
|
59
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
60
|
+
with:
|
|
61
|
+
python-version: '3.14.7'
|
|
62
|
+
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069
|
|
63
|
+
- name: Read the version and registry namespace
|
|
64
|
+
id: metadata
|
|
65
|
+
env:
|
|
66
|
+
REPOSITORY_OWNER: ${{ github.repository_owner }}
|
|
67
|
+
GH_TOKEN: ${{ github.token }}
|
|
68
|
+
run: |
|
|
69
|
+
version=$(python -c 'import tomllib; print(tomllib.load(open("Cargo.toml", "rb"))["package"]["version"])')
|
|
70
|
+
# PRs exercise packaging with an available public runtime; source CI
|
|
71
|
+
# validates the unreleased Core independently.
|
|
72
|
+
if [ "$GITHUB_EVENT_NAME" = pull_request ]; then
|
|
73
|
+
tag=$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName --jq .tagName)
|
|
74
|
+
version=${tag#v}
|
|
75
|
+
fi
|
|
76
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
77
|
+
echo "image=ghcr.io/${REPOSITORY_OWNER,,}/toolframe" >> "$GITHUB_OUTPUT"
|
|
78
|
+
- name: Download the validated launcher from this publication run
|
|
79
|
+
if: inputs.release_artifacts
|
|
80
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
81
|
+
with:
|
|
82
|
+
name: validated-release
|
|
83
|
+
path: build/candidate/
|
|
84
|
+
- name: Verify the bundle and stage this platform's release
|
|
85
|
+
if: inputs.release_artifacts
|
|
86
|
+
env:
|
|
87
|
+
TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
|
|
88
|
+
TOOLFRAME_TARGET: ${{ matrix.target }}
|
|
89
|
+
run: >-
|
|
90
|
+
python scripts/ci/artifacts.py export --bundle build/candidate
|
|
91
|
+
--kind release --target "$TOOLFRAME_TARGET" --output build/container-release
|
|
92
|
+
- name: Stage the verified executable
|
|
93
|
+
env:
|
|
94
|
+
USE_ARTIFACTS: ${{ inputs.release_artifacts }}
|
|
95
|
+
ARCH: ${{ matrix.arch }}
|
|
96
|
+
VERSION: ${{ steps.metadata.outputs.version }}
|
|
97
|
+
run: |
|
|
98
|
+
options=()
|
|
99
|
+
if [ "$USE_ARTIFACTS" = true ]; then
|
|
100
|
+
options+=(--release-dir build/container-release)
|
|
101
|
+
fi
|
|
102
|
+
python scripts/prepare-container.py --architecture "$ARCH" --version "$VERSION" \
|
|
103
|
+
--repository "$GITHUB_REPOSITORY" "${options[@]}"
|
|
104
|
+
- name: Build the native image
|
|
105
|
+
env:
|
|
106
|
+
ARCH: ${{ matrix.arch }}
|
|
107
|
+
VARIANT: ${{ matrix.variant }}
|
|
108
|
+
VERSION: ${{ steps.metadata.outputs.version }}
|
|
109
|
+
run: |
|
|
110
|
+
docker buildx build --platform "linux/$ARCH" --target "$VARIANT" \
|
|
111
|
+
--pull --no-cache-filter runtime \
|
|
112
|
+
--build-arg "TOOLFRAME_VERSION=$VERSION" \
|
|
113
|
+
--build-arg "TOOLFRAME_REVISION=$GITHUB_SHA" \
|
|
114
|
+
--label "org.opencontainers.image.source=https://github.com/$GITHUB_REPOSITORY" \
|
|
115
|
+
--provenance=false --load --tag toolframe-check:local .
|
|
116
|
+
- name: Verify public interfaces, persistence and shutdown
|
|
117
|
+
env:
|
|
118
|
+
ARCH: ${{ matrix.arch }}
|
|
119
|
+
VARIANT: ${{ matrix.variant }}
|
|
120
|
+
run: |
|
|
121
|
+
python scripts/verify-container.py --image toolframe-check:local \
|
|
122
|
+
--variant "$VARIANT" --platform "linux/$ARCH" \
|
|
123
|
+
--output build/container-verification.json
|
|
124
|
+
- name: Save verification evidence
|
|
125
|
+
if: always()
|
|
126
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
127
|
+
with:
|
|
128
|
+
name: container-evidence-${{ matrix.variant }}-${{ matrix.arch }}
|
|
129
|
+
path: build/container-verification*
|
|
130
|
+
if-no-files-found: warn
|
|
131
|
+
retention-days: 7
|
|
132
|
+
- name: Scan the tested image before publication
|
|
133
|
+
uses: ./.github/actions/scan-container
|
|
134
|
+
with:
|
|
135
|
+
image: toolframe-check:local
|
|
136
|
+
platform: linux/${{ matrix.arch }}
|
|
137
|
+
image-source: docker
|
|
138
|
+
- name: Save security evidence
|
|
139
|
+
if: always()
|
|
140
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
141
|
+
with:
|
|
142
|
+
name: container-security-${{ matrix.variant }}-${{ matrix.arch }}
|
|
143
|
+
path: build/security/
|
|
144
|
+
if-no-files-found: warn
|
|
145
|
+
retention-days: 7
|
|
146
|
+
- name: Log in to GHCR
|
|
147
|
+
if: inputs.publish
|
|
148
|
+
uses: docker/login-action@783ae9cac559640a24c9212dfa6cd9e998252f9a
|
|
149
|
+
with:
|
|
150
|
+
registry: ghcr.io
|
|
151
|
+
username: ${{ github.actor }}
|
|
152
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
153
|
+
- name: Push the exact locally tested image
|
|
154
|
+
if: inputs.publish
|
|
155
|
+
env:
|
|
156
|
+
IMAGE: ${{ steps.metadata.outputs.image }}
|
|
157
|
+
ARCH: ${{ matrix.arch }}
|
|
158
|
+
VARIANT: ${{ matrix.variant }}
|
|
159
|
+
run: |
|
|
160
|
+
ref="$IMAGE:build-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-$VARIANT-$ARCH"
|
|
161
|
+
docker tag toolframe-check:local "$ref"
|
|
162
|
+
docker push "$ref"
|
|
163
|
+
mkdir -p build/digests
|
|
164
|
+
docker image inspect --format '{{index .RepoDigests 0}}' "$ref" \
|
|
165
|
+
> "build/digests/$VARIANT-$ARCH.txt"
|
|
166
|
+
- name: Save the tested image digest
|
|
167
|
+
if: inputs.publish
|
|
168
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
169
|
+
with:
|
|
170
|
+
name: container-digest-${{ matrix.variant }}-${{ matrix.arch }}
|
|
171
|
+
path: build/digests/*.txt
|
|
172
|
+
if-no-files-found: error
|
|
173
|
+
|
|
174
|
+
publish:
|
|
175
|
+
name: Publish multi-platform tags
|
|
176
|
+
needs: build
|
|
177
|
+
if: inputs.publish
|
|
178
|
+
runs-on: ubuntu-24.04
|
|
179
|
+
timeout-minutes: 10
|
|
180
|
+
permissions:
|
|
181
|
+
contents: read
|
|
182
|
+
packages: write
|
|
183
|
+
concurrency:
|
|
184
|
+
group: container-publish-${{ github.repository }}
|
|
185
|
+
cancel-in-progress: false
|
|
186
|
+
steps:
|
|
187
|
+
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069
|
|
188
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
189
|
+
with:
|
|
190
|
+
pattern: container-digest-*
|
|
191
|
+
merge-multiple: true
|
|
192
|
+
path: build/digests/
|
|
193
|
+
- uses: docker/login-action@783ae9cac559640a24c9212dfa6cd9e998252f9a
|
|
194
|
+
with:
|
|
195
|
+
registry: ghcr.io
|
|
196
|
+
username: ${{ github.actor }}
|
|
197
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
198
|
+
- name: Publish both architectures after all four checks pass
|
|
199
|
+
env:
|
|
200
|
+
IMAGE: ${{ needs.build.outputs.image }}
|
|
201
|
+
VERSION: ${{ needs.build.outputs.version }}
|
|
202
|
+
GH_TOKEN: ${{ github.token }}
|
|
203
|
+
GH_REPO: ${{ github.repository }}
|
|
204
|
+
run: |
|
|
205
|
+
latest=$(gh release view --repo "$GH_REPO" --json tagName --jq .tagName)
|
|
206
|
+
for variant in standard distroless; do
|
|
207
|
+
suffix=""
|
|
208
|
+
alias=latest
|
|
209
|
+
if [ "$variant" = distroless ]; then
|
|
210
|
+
suffix=-distroless
|
|
211
|
+
alias=distroless
|
|
212
|
+
fi
|
|
213
|
+
mapfile -t refs < <(cat build/digests/"$variant"-*.txt)
|
|
214
|
+
test "${#refs[@]}" -eq 2
|
|
215
|
+
tags=(--tag "$IMAGE:$VERSION$suffix")
|
|
216
|
+
if [ "$latest" = "v$VERSION" ] && [[ "$VERSION" != *-* ]]; then
|
|
217
|
+
tags+=(--tag "$IMAGE:$alias")
|
|
218
|
+
fi
|
|
219
|
+
docker buildx imagetools create "${tags[@]}" "${refs[@]}"
|
|
220
|
+
docker buildx imagetools inspect "$IMAGE:$VERSION$suffix"
|
|
221
|
+
done
|
|
@@ -76,6 +76,7 @@ jobs:
|
|
|
76
76
|
name: launcher-wheel-${{ matrix.target }}
|
|
77
77
|
path: build/launcher-dist/wheels/*.whl
|
|
78
78
|
if-no-files-found: error
|
|
79
|
+
overwrite: true
|
|
79
80
|
retention-days: 14
|
|
80
81
|
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
81
82
|
with:
|
|
@@ -86,6 +87,7 @@ jobs:
|
|
|
86
87
|
build/launcher-dist/release/*.json
|
|
87
88
|
build/launcher-dist/release/SHA256SUMS-*.txt
|
|
88
89
|
if-no-files-found: error
|
|
90
|
+
overwrite: true
|
|
89
91
|
retention-days: 14
|
|
90
92
|
- name: Retain acceptance evidence
|
|
91
93
|
if: always()
|
|
@@ -94,3 +96,4 @@ jobs:
|
|
|
94
96
|
name: launcher-evidence-${{ matrix.target }}
|
|
95
97
|
path: build/launcher-dist/*.json
|
|
96
98
|
if-no-files-found: warn
|
|
99
|
+
overwrite: true
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Pull request policy
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
# Keep a stable required check for title edits without repeating native CI.
|
|
6
|
+
pull_request:
|
|
7
|
+
types: [opened, synchronize, reopened, edited]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
pull-requests: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
commit-policy:
|
|
15
|
+
name: PR policy
|
|
16
|
+
runs-on: ubuntu-24.04
|
|
17
|
+
timeout-minutes: 10
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
24
|
+
with:
|
|
25
|
+
python-version: '3.14.7'
|
|
26
|
+
- uses: commit-check/commit-check-action@a61779784a953fd9047c001c102cfeac5cf26964 # commit-check 2.18.3
|
|
27
|
+
with:
|
|
28
|
+
message: true
|
|
29
|
+
branch: false
|
|
30
|
+
pr-title: true
|
|
31
|
+
pr-comments: false
|
|
@@ -11,9 +11,15 @@ on:
|
|
|
11
11
|
- pypi
|
|
12
12
|
default: testpypi
|
|
13
13
|
required: true
|
|
14
|
+
rebuild:
|
|
15
|
+
description: Validate and rebuild at the tag instead of promoting main artifacts
|
|
16
|
+
type: boolean
|
|
17
|
+
default: false
|
|
14
18
|
|
|
15
19
|
permissions:
|
|
16
20
|
contents: read
|
|
21
|
+
actions: read
|
|
22
|
+
pull-requests: read
|
|
17
23
|
|
|
18
24
|
concurrency:
|
|
19
25
|
group: publish-${{ github.ref }}-${{ inputs.index }}
|
|
@@ -33,9 +39,19 @@ jobs:
|
|
|
33
39
|
- name: Require the exact project version tag
|
|
34
40
|
run: python scripts/ci/check-release.py --ref "$GITHUB_REF"
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
quality:
|
|
37
43
|
needs: release-tag
|
|
44
|
+
permissions:
|
|
45
|
+
contents: read
|
|
46
|
+
pull-requests: read
|
|
47
|
+
uses: ./.github/workflows/quality.yml
|
|
48
|
+
|
|
49
|
+
validate:
|
|
50
|
+
needs: [release-tag, quality]
|
|
38
51
|
uses: ./.github/workflows/validate.yml
|
|
52
|
+
with:
|
|
53
|
+
reuse-stage: release
|
|
54
|
+
rebuild: ${{ inputs.rebuild }}
|
|
39
55
|
secrets: inherit
|
|
40
56
|
|
|
41
57
|
publish-core:
|
|
@@ -45,22 +61,24 @@ jobs:
|
|
|
45
61
|
environment:
|
|
46
62
|
name: ${{ inputs.index }}
|
|
47
63
|
permissions:
|
|
64
|
+
contents: read
|
|
48
65
|
id-token: write
|
|
49
66
|
steps:
|
|
50
|
-
-
|
|
67
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
68
|
+
with:
|
|
69
|
+
persist-credentials: false
|
|
70
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
71
|
+
with:
|
|
72
|
+
python-version: '3.14.7'
|
|
73
|
+
- name: Download the bundle validated in this run
|
|
51
74
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
52
75
|
with:
|
|
53
|
-
name:
|
|
54
|
-
path:
|
|
55
|
-
- name:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
files = list(Path('dist').iterdir())
|
|
60
|
-
assert len(list(Path('dist').glob('toolframe_core-*.whl'))) == 1
|
|
61
|
-
assert len(list(Path('dist').glob('toolframe_core-*.tar.gz'))) == 1
|
|
62
|
-
assert len(files) == 2
|
|
63
|
-
PY
|
|
76
|
+
name: validated-release
|
|
77
|
+
path: build/candidate/
|
|
78
|
+
- name: Verify and stage the exact Core distributions
|
|
79
|
+
env:
|
|
80
|
+
TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
|
|
81
|
+
run: python scripts/ci/artifacts.py export --bundle build/candidate --kind core --output dist
|
|
64
82
|
- name: Publish Core using its Trusted Publisher
|
|
65
83
|
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
66
84
|
with:
|
|
@@ -74,22 +92,24 @@ jobs:
|
|
|
74
92
|
environment:
|
|
75
93
|
name: ${{ inputs.index }}-launcher
|
|
76
94
|
permissions:
|
|
95
|
+
contents: read
|
|
77
96
|
id-token: write
|
|
78
97
|
steps:
|
|
79
|
-
-
|
|
98
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
99
|
+
with:
|
|
100
|
+
persist-credentials: false
|
|
101
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
102
|
+
with:
|
|
103
|
+
python-version: '3.14.7'
|
|
104
|
+
- name: Download the bundle validated in this run
|
|
80
105
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
81
106
|
with:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
from pathlib import Path
|
|
89
|
-
files = list(Path('dist').iterdir())
|
|
90
|
-
assert len(list(Path('dist').glob('toolframe-*.whl'))) == 4
|
|
91
|
-
assert len(files) == 4
|
|
92
|
-
PY
|
|
107
|
+
name: validated-release
|
|
108
|
+
path: build/candidate/
|
|
109
|
+
- name: Verify and stage all four exact native wheels
|
|
110
|
+
env:
|
|
111
|
+
TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
|
|
112
|
+
run: python scripts/ci/artifacts.py export --bundle build/candidate --kind wheel --output dist
|
|
93
113
|
- name: Publish the launcher using its Trusted Publisher
|
|
94
114
|
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
95
115
|
with:
|
|
@@ -104,11 +124,20 @@ jobs:
|
|
|
104
124
|
permissions:
|
|
105
125
|
contents: write
|
|
106
126
|
steps:
|
|
127
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
128
|
+
with:
|
|
129
|
+
persist-credentials: false
|
|
130
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
131
|
+
with:
|
|
132
|
+
python-version: '3.14.7'
|
|
107
133
|
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
108
134
|
with:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
name: validated-release
|
|
136
|
+
path: build/candidate/
|
|
137
|
+
- name: Verify and stage the exact release archives
|
|
138
|
+
env:
|
|
139
|
+
TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
|
|
140
|
+
run: python scripts/ci/artifacts.py export --bundle build/candidate --kind release --output releases
|
|
112
141
|
- name: Publish verified executables and checksums
|
|
113
142
|
env:
|
|
114
143
|
GH_TOKEN: ${{ github.token }}
|
|
@@ -126,3 +155,14 @@ jobs:
|
|
|
126
155
|
EOF
|
|
127
156
|
gh release create "$RELEASE_TAG" --verify-tag --title "Toolframe $RELEASE_TAG" \
|
|
128
157
|
--notes-file release-notes.txt releases/*.tar.gz releases/SHA256SUMS releases/manifest-*.json releases/*.whl
|
|
158
|
+
|
|
159
|
+
publish-containers:
|
|
160
|
+
needs: release-binaries
|
|
161
|
+
if: inputs.index == 'pypi'
|
|
162
|
+
permissions:
|
|
163
|
+
contents: read
|
|
164
|
+
packages: write
|
|
165
|
+
uses: ./.github/workflows/container.yml
|
|
166
|
+
with:
|
|
167
|
+
publish: true
|
|
168
|
+
release_artifacts: true
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Code quality
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
branch-policy:
|
|
11
|
+
runs-on: ubuntu-24.04
|
|
12
|
+
timeout-minutes: 5
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
15
|
+
with:
|
|
16
|
+
persist-credentials: false
|
|
17
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
18
|
+
with:
|
|
19
|
+
python-version: '3.14.7'
|
|
20
|
+
- name: Check the source branch or selected release tag
|
|
21
|
+
env:
|
|
22
|
+
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
|
23
|
+
run: |
|
|
24
|
+
if [ "$GITHUB_REF_TYPE" = tag ]; then
|
|
25
|
+
python scripts/ci/check-release.py --ref "$GITHUB_REF"
|
|
26
|
+
else
|
|
27
|
+
python scripts/check_branch_name.py "$BRANCH_NAME"
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
code-quality:
|
|
31
|
+
runs-on: ubuntu-24.04
|
|
32
|
+
timeout-minutes: 10
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
35
|
+
with:
|
|
36
|
+
persist-credentials: false
|
|
37
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
38
|
+
with:
|
|
39
|
+
version: '0.12.8'
|
|
40
|
+
enable-cache: false
|
|
41
|
+
- name: Check Python lint and formatting
|
|
42
|
+
run: uvx prek==0.5.5 run ruff-check ruff-format --all-files --show-diff-on-failure
|
|
43
|
+
|
|
44
|
+
commit-policy:
|
|
45
|
+
if: github.event_name == 'pull_request'
|
|
46
|
+
permissions:
|
|
47
|
+
contents: read
|
|
48
|
+
pull-requests: read
|
|
49
|
+
uses: ./.github/workflows/pr-policy.yml
|