ossplate 0.1.9__py3-none-win_amd64.whl
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.
- ossplate/__init__.py +3 -0
- ossplate/bin/win32-x64/ossplate.exe +0 -0
- ossplate/cli.py +55 -0
- ossplate/scaffold/.github/workflows/ci.yml +111 -0
- ossplate/scaffold/.github/workflows/publish-npm.yml +72 -0
- ossplate/scaffold/.github/workflows/publish.yml +173 -0
- ossplate/scaffold/.github/workflows/release.yml +117 -0
- ossplate/scaffold/.gitignore +9 -0
- ossplate/scaffold/.pre-commit-config.yaml +9 -0
- ossplate/scaffold/CONTRIBUTING.md +53 -0
- ossplate/scaffold/LICENSE +9 -0
- ossplate/scaffold/README.md +81 -0
- ossplate/scaffold/assets/illustrations/chestplate.svg +6 -0
- ossplate/scaffold/core-rs/Cargo.lock +338 -0
- ossplate/scaffold/core-rs/Cargo.toml +28 -0
- ossplate/scaffold/core-rs/src/main.rs +1730 -0
- ossplate/scaffold/docs/README.md +16 -0
- ossplate/scaffold/docs/adrs/0001-rust-core-thin-wrappers.md +21 -0
- ossplate/scaffold/docs/adrs/0002-sync-owns-bounded-identity.md +31 -0
- ossplate/scaffold/docs/adrs/0003-curated-scaffold-payload.md +21 -0
- ossplate/scaffold/docs/architecture.md +89 -0
- ossplate/scaffold/docs/customizing-the-template.md +121 -0
- ossplate/scaffold/docs/releases.md +91 -0
- ossplate/scaffold/docs/testing.md +76 -0
- ossplate/scaffold/ossplate.toml +15 -0
- ossplate/scaffold/scripts/bump-version.mjs +53 -0
- ossplate/scaffold/scripts/release-plan.mjs +94 -0
- ossplate/scaffold/scripts/verify.sh +36 -0
- ossplate/scaffold/wrapper-js/README.md +30 -0
- ossplate/scaffold/wrapper-js/bin/ossplate.js +5 -0
- ossplate/scaffold/wrapper-js/package-lock.json +51 -0
- ossplate/scaffold/wrapper-js/package.json +43 -0
- ossplate/scaffold/wrapper-js/src/index.ts +69 -0
- ossplate/scaffold/wrapper-js/tsconfig.json +14 -0
- ossplate/scaffold/wrapper-py/README.md +30 -0
- ossplate/scaffold/wrapper-py/hatch_build.py +97 -0
- ossplate/scaffold/wrapper-py/pyproject.toml +40 -0
- ossplate/scaffold/wrapper-py/src/ossplate/__init__.py +3 -0
- ossplate/scaffold/wrapper-py/src/ossplate/cli.py +55 -0
- ossplate-0.1.9.dist-info/METADATA +44 -0
- ossplate-0.1.9.dist-info/RECORD +43 -0
- ossplate-0.1.9.dist-info/WHEEL +4 -0
- ossplate-0.1.9.dist-info/entry_points.txt +2 -0
ossplate/__init__.py
ADDED
|
Binary file
|
ossplate/cli.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
from importlib import resources
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
ENV_OVERRIDE = "OSSPLATE_BINARY"
|
|
11
|
+
TEMPLATE_ROOT_ENV = "OSSPLATE_TEMPLATE_ROOT"
|
|
12
|
+
TARGETS = {
|
|
13
|
+
("Darwin", "arm64"): ("darwin-arm64", "ossplate"),
|
|
14
|
+
("Darwin", "x86_64"): ("darwin-x64", "ossplate"),
|
|
15
|
+
("Linux", "x86_64"): ("linux-x64", "ossplate"),
|
|
16
|
+
("Windows", "AMD64"): ("win32-x64", "ossplate.exe"),
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_packaged_binary_path(base_dir: Path | None = None) -> str:
|
|
21
|
+
base_dir = base_dir or Path(resources.files("ossplate"))
|
|
22
|
+
env_override = os.environ.get(ENV_OVERRIDE)
|
|
23
|
+
if env_override:
|
|
24
|
+
return env_override
|
|
25
|
+
|
|
26
|
+
system = platform.system()
|
|
27
|
+
machine = platform.machine()
|
|
28
|
+
target = TARGETS.get((system, machine))
|
|
29
|
+
if target is None:
|
|
30
|
+
raise RuntimeError(f"Unsupported platform/arch: {system}/{machine}")
|
|
31
|
+
|
|
32
|
+
folder, executable = target
|
|
33
|
+
binary_path = base_dir / "bin" / folder / executable
|
|
34
|
+
if not binary_path.exists():
|
|
35
|
+
raise RuntimeError(f"Bundled ossplate binary not found at {binary_path}")
|
|
36
|
+
return str(binary_path)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def get_binary_path() -> str:
|
|
40
|
+
return get_packaged_binary_path()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def cli(args: tuple[str, ...]) -> int:
|
|
44
|
+
env = os.environ.copy()
|
|
45
|
+
env.setdefault(TEMPLATE_ROOT_ENV, str(Path(resources.files("ossplate")) / "scaffold"))
|
|
46
|
+
result = subprocess.run([get_binary_path(), *args], check=False, env=env)
|
|
47
|
+
return result.returncode
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def main() -> None:
|
|
51
|
+
raise SystemExit(cli(tuple(sys.argv[1:])))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if __name__ == "__main__":
|
|
55
|
+
main()
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# ossplate:workflow-name:start
|
|
2
|
+
name: Ossplate CI
|
|
3
|
+
# ossplate:workflow-name:end
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- main
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
template-readiness:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v5
|
|
16
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
17
|
+
- uses: actions/setup-node@v5
|
|
18
|
+
with:
|
|
19
|
+
node-version: '24'
|
|
20
|
+
- run: cargo run --quiet --manifest-path core-rs/Cargo.toml -- validate
|
|
21
|
+
- run: cargo run --quiet --manifest-path core-rs/Cargo.toml -- sync --check
|
|
22
|
+
- run: node --test ./scripts/validate-template-readiness.test.mjs
|
|
23
|
+
|
|
24
|
+
rust:
|
|
25
|
+
needs: template-readiness
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v5
|
|
29
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
30
|
+
- run: cargo fmt --check
|
|
31
|
+
working-directory: ./core-rs
|
|
32
|
+
- run: cargo clippy -- -D warnings
|
|
33
|
+
working-directory: ./core-rs
|
|
34
|
+
- run: cargo test
|
|
35
|
+
working-directory: ./core-rs
|
|
36
|
+
|
|
37
|
+
js:
|
|
38
|
+
needs: template-readiness
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v5
|
|
42
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
43
|
+
- uses: actions/setup-node@v5
|
|
44
|
+
with:
|
|
45
|
+
node-version: '24'
|
|
46
|
+
cache: npm
|
|
47
|
+
cache-dependency-path: ./wrapper-js/package-lock.json
|
|
48
|
+
- run: npm ci
|
|
49
|
+
working-directory: ./wrapper-js
|
|
50
|
+
- run: npm run build
|
|
51
|
+
working-directory: ./wrapper-js
|
|
52
|
+
- run: npm test
|
|
53
|
+
working-directory: ./wrapper-js
|
|
54
|
+
- run: npm pack --dry-run
|
|
55
|
+
working-directory: ./wrapper-js
|
|
56
|
+
|
|
57
|
+
python:
|
|
58
|
+
needs: template-readiness
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v5
|
|
62
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
63
|
+
- uses: actions/setup-node@v5
|
|
64
|
+
with:
|
|
65
|
+
node-version: '24'
|
|
66
|
+
- uses: actions/setup-python@v6
|
|
67
|
+
with:
|
|
68
|
+
python-version: '3.11'
|
|
69
|
+
- name: Test and build
|
|
70
|
+
run: |
|
|
71
|
+
python -m pip install --upgrade pip
|
|
72
|
+
pip install -e .
|
|
73
|
+
pip install build
|
|
74
|
+
python -m unittest discover -s tests -p 'test_*.py'
|
|
75
|
+
working-directory: ./wrapper-py
|
|
76
|
+
|
|
77
|
+
python-wheel:
|
|
78
|
+
needs: template-readiness
|
|
79
|
+
strategy:
|
|
80
|
+
fail-fast: false
|
|
81
|
+
matrix:
|
|
82
|
+
include:
|
|
83
|
+
- runner: ubuntu-latest
|
|
84
|
+
target: linux-x64
|
|
85
|
+
- runner: macos-14
|
|
86
|
+
target: darwin-arm64
|
|
87
|
+
- runner: macos-15-intel
|
|
88
|
+
target: darwin-x64
|
|
89
|
+
- runner: windows-latest
|
|
90
|
+
target: win32-x64
|
|
91
|
+
runs-on: ${{ matrix.runner }}
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/checkout@v5
|
|
94
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
95
|
+
- uses: actions/setup-node@v5
|
|
96
|
+
with:
|
|
97
|
+
node-version: '24'
|
|
98
|
+
- uses: actions/setup-python@v6
|
|
99
|
+
with:
|
|
100
|
+
python-version: '3.11'
|
|
101
|
+
- name: Build core binary
|
|
102
|
+
run: cargo build --manifest-path core-rs/Cargo.toml
|
|
103
|
+
- name: Validate wheel artifact
|
|
104
|
+
env:
|
|
105
|
+
OSSPLATE_PY_TARGET: ${{ matrix.target }}
|
|
106
|
+
run: |
|
|
107
|
+
python -m pip install --upgrade pip
|
|
108
|
+
pip install -e .
|
|
109
|
+
pip install build
|
|
110
|
+
python -m unittest discover -s tests -p 'test_*.py'
|
|
111
|
+
working-directory: ./wrapper-py
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# ossplate:workflow-name:start
|
|
2
|
+
name: Ossplate publish-npm
|
|
3
|
+
# ossplate:workflow-name:end
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
release:
|
|
7
|
+
types: [published]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish-npm:
|
|
12
|
+
if: >
|
|
13
|
+
github.event_name == 'workflow_dispatch' ||
|
|
14
|
+
github.event_name == 'release'
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
id-token: write
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
- uses: actions/setup-node@v5
|
|
22
|
+
with:
|
|
23
|
+
node-version: '24'
|
|
24
|
+
registry-url: 'https://registry.npmjs.org'
|
|
25
|
+
cache: npm
|
|
26
|
+
cache-dependency-path: ./wrapper-js/package-lock.json
|
|
27
|
+
- name: Detect published version
|
|
28
|
+
id: published
|
|
29
|
+
working-directory: ./wrapper-js
|
|
30
|
+
run: |
|
|
31
|
+
NAME=$(node -p "require('./package.json').name")
|
|
32
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
33
|
+
echo "name=$NAME" >> "$GITHUB_OUTPUT"
|
|
34
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
35
|
+
if npm view "$NAME@$VERSION" version >/dev/null 2>&1; then
|
|
36
|
+
echo "already=true" >> "$GITHUB_OUTPUT"
|
|
37
|
+
echo "::notice title=npm::${NAME}@${VERSION} is already published; skipping."
|
|
38
|
+
else
|
|
39
|
+
echo "already=false" >> "$GITHUB_OUTPUT"
|
|
40
|
+
fi
|
|
41
|
+
- if: steps.published.outputs.already != 'true'
|
|
42
|
+
run: npm ci
|
|
43
|
+
working-directory: ./wrapper-js
|
|
44
|
+
- name: Publish to npm
|
|
45
|
+
if: steps.published.outputs.already != 'true'
|
|
46
|
+
working-directory: ./wrapper-js
|
|
47
|
+
env:
|
|
48
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
49
|
+
run: |
|
|
50
|
+
logfile=$(mktemp)
|
|
51
|
+
cleanup() {
|
|
52
|
+
rm -f "$logfile"
|
|
53
|
+
}
|
|
54
|
+
trap cleanup EXIT
|
|
55
|
+
set +e
|
|
56
|
+
npm publish --access public --provenance 2>&1 | tee "$logfile"
|
|
57
|
+
status=${PIPESTATUS[0]}
|
|
58
|
+
set -e
|
|
59
|
+
if [ "$status" -eq 0 ]; then
|
|
60
|
+
echo "::notice title=npm::published with OIDC trusted publishing."
|
|
61
|
+
exit 0
|
|
62
|
+
fi
|
|
63
|
+
if [ -z "${NODE_AUTH_TOKEN:-}" ]; then
|
|
64
|
+
echo "::error title=npm::OIDC publish failed and NPM_TOKEN is not configured."
|
|
65
|
+
exit "$status"
|
|
66
|
+
fi
|
|
67
|
+
if grep -qiE "already exists|cannot publish over|previously published" "$logfile"; then
|
|
68
|
+
echo "::notice title=npm::package version already exists; skipping."
|
|
69
|
+
exit 0
|
|
70
|
+
fi
|
|
71
|
+
echo "::warning title=npm::OIDC publish failed; retrying with NPM_TOKEN fallback."
|
|
72
|
+
npm publish --access public
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# ossplate:workflow-name:start
|
|
2
|
+
name: Ossplate publishing
|
|
3
|
+
# ossplate:workflow-name:end
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
release:
|
|
7
|
+
types: [published]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build-pypi-wheel:
|
|
12
|
+
if: >
|
|
13
|
+
github.event_name == 'workflow_dispatch' ||
|
|
14
|
+
github.event_name == 'release'
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
include:
|
|
19
|
+
- runner: ubuntu-latest
|
|
20
|
+
target: linux-x64
|
|
21
|
+
- runner: macos-14
|
|
22
|
+
target: darwin-arm64
|
|
23
|
+
- runner: macos-15-intel
|
|
24
|
+
target: darwin-x64
|
|
25
|
+
- runner: windows-latest
|
|
26
|
+
target: win32-x64
|
|
27
|
+
runs-on: ${{ matrix.runner }}
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v5
|
|
32
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
33
|
+
- uses: actions/setup-node@v5
|
|
34
|
+
with:
|
|
35
|
+
node-version: '24'
|
|
36
|
+
- uses: actions/setup-python@v6
|
|
37
|
+
with:
|
|
38
|
+
python-version: '3.11'
|
|
39
|
+
- name: Build core binary
|
|
40
|
+
run: cargo build --manifest-path core-rs/Cargo.toml
|
|
41
|
+
- name: Build wheel
|
|
42
|
+
env:
|
|
43
|
+
OSSPLATE_PY_TARGET: ${{ matrix.target }}
|
|
44
|
+
run: |
|
|
45
|
+
python -m pip install --upgrade pip
|
|
46
|
+
pip install build
|
|
47
|
+
python -m build --wheel --outdir dist/${{ matrix.target }}
|
|
48
|
+
working-directory: ./wrapper-py
|
|
49
|
+
- uses: actions/upload-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
name: pypi-wheel-${{ matrix.target }}
|
|
52
|
+
path: ./wrapper-py/dist/${{ matrix.target }}/*.whl
|
|
53
|
+
|
|
54
|
+
build-pypi-sdist:
|
|
55
|
+
if: >
|
|
56
|
+
github.event_name == 'workflow_dispatch' ||
|
|
57
|
+
github.event_name == 'release'
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
permissions:
|
|
60
|
+
contents: read
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@v5
|
|
63
|
+
- uses: actions/setup-python@v6
|
|
64
|
+
with:
|
|
65
|
+
python-version: '3.11'
|
|
66
|
+
- name: Build sdist
|
|
67
|
+
run: |
|
|
68
|
+
python -m pip install --upgrade pip
|
|
69
|
+
pip install build
|
|
70
|
+
python -m build --sdist --outdir dist/sdist
|
|
71
|
+
working-directory: ./wrapper-py
|
|
72
|
+
- uses: actions/upload-artifact@v4
|
|
73
|
+
with:
|
|
74
|
+
name: pypi-sdist
|
|
75
|
+
path: ./wrapper-py/dist/sdist/*.tar.gz
|
|
76
|
+
|
|
77
|
+
publish-pypi:
|
|
78
|
+
if: >
|
|
79
|
+
github.event_name == 'workflow_dispatch' ||
|
|
80
|
+
github.event_name == 'release'
|
|
81
|
+
needs:
|
|
82
|
+
- build-pypi-wheel
|
|
83
|
+
- build-pypi-sdist
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
permissions:
|
|
86
|
+
contents: read
|
|
87
|
+
id-token: write
|
|
88
|
+
steps:
|
|
89
|
+
- uses: actions/download-artifact@v4
|
|
90
|
+
with:
|
|
91
|
+
pattern: pypi-*
|
|
92
|
+
path: ./dist
|
|
93
|
+
merge-multiple: true
|
|
94
|
+
- name: Publish to PyPI
|
|
95
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
96
|
+
with:
|
|
97
|
+
packages-dir: ./dist/
|
|
98
|
+
skip-existing: true
|
|
99
|
+
attestations: false
|
|
100
|
+
|
|
101
|
+
publish-cargo:
|
|
102
|
+
if: >
|
|
103
|
+
github.event_name == 'workflow_dispatch' ||
|
|
104
|
+
github.event_name == 'release'
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
permissions:
|
|
107
|
+
contents: read
|
|
108
|
+
id-token: write
|
|
109
|
+
steps:
|
|
110
|
+
- uses: actions/checkout@v5
|
|
111
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
112
|
+
- name: Authenticate with crates.io via OIDC
|
|
113
|
+
id: auth
|
|
114
|
+
continue-on-error: true
|
|
115
|
+
uses: rust-lang/crates-io-auth-action@v1
|
|
116
|
+
- name: Detect published crate version
|
|
117
|
+
id: version
|
|
118
|
+
working-directory: ./core-rs
|
|
119
|
+
run: |
|
|
120
|
+
CRATE_NAME=$(python3 - <<'PY'
|
|
121
|
+
import tomllib
|
|
122
|
+
with open("Cargo.toml", "rb") as f:
|
|
123
|
+
data = tomllib.load(f)
|
|
124
|
+
print(data["package"]["name"])
|
|
125
|
+
PY
|
|
126
|
+
)
|
|
127
|
+
CRATE_VERSION=$(python3 - <<'PY'
|
|
128
|
+
import tomllib
|
|
129
|
+
with open("Cargo.toml", "rb") as f:
|
|
130
|
+
data = tomllib.load(f)
|
|
131
|
+
print(data["package"]["version"])
|
|
132
|
+
PY
|
|
133
|
+
)
|
|
134
|
+
echo "name=$CRATE_NAME" >> "$GITHUB_OUTPUT"
|
|
135
|
+
echo "version=$CRATE_VERSION" >> "$GITHUB_OUTPUT"
|
|
136
|
+
if curl -fsSL "https://crates.io/api/v1/crates/${CRATE_NAME}/${CRATE_VERSION}" >/dev/null 2>&1; then
|
|
137
|
+
echo "already=true" >> "$GITHUB_OUTPUT"
|
|
138
|
+
echo "::notice title=cargo::${CRATE_NAME} ${CRATE_VERSION} is already published; skipping."
|
|
139
|
+
else
|
|
140
|
+
echo "already=false" >> "$GITHUB_OUTPUT"
|
|
141
|
+
fi
|
|
142
|
+
- name: Publish to crates.io
|
|
143
|
+
if: steps.version.outputs.already != 'true'
|
|
144
|
+
working-directory: ./core-rs
|
|
145
|
+
env:
|
|
146
|
+
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token || secrets.CARGO_TOKEN }}
|
|
147
|
+
run: |
|
|
148
|
+
logfile=$(mktemp)
|
|
149
|
+
cleanup() {
|
|
150
|
+
rm -f "$logfile"
|
|
151
|
+
}
|
|
152
|
+
trap cleanup EXIT
|
|
153
|
+
if [ -n "${{ steps.auth.outputs.token }}" ]; then
|
|
154
|
+
echo "::notice title=cargo::using crates.io OIDC token from trusted publishing."
|
|
155
|
+
else
|
|
156
|
+
echo "::notice title=cargo::OIDC token unavailable; falling back to CARGO_TOKEN secret."
|
|
157
|
+
fi
|
|
158
|
+
set +e
|
|
159
|
+
cargo publish 2>&1 | tee "$logfile"
|
|
160
|
+
status=${PIPESTATUS[0]}
|
|
161
|
+
set -e
|
|
162
|
+
if [ "$status" -eq 0 ]; then
|
|
163
|
+
exit 0
|
|
164
|
+
fi
|
|
165
|
+
if grep -q "status 429 Too Many Requests" "$logfile"; then
|
|
166
|
+
echo "::warning title=cargo::crates.io rate limit hit. Treating this publish attempt as non-blocking."
|
|
167
|
+
exit 0
|
|
168
|
+
fi
|
|
169
|
+
if grep -qi "already exists on crates.io index" "$logfile"; then
|
|
170
|
+
echo "::notice title=cargo::crate version already exists; skipping."
|
|
171
|
+
exit 0
|
|
172
|
+
fi
|
|
173
|
+
exit "$status"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# ossplate:workflow-name:start
|
|
2
|
+
name: Ossplate release
|
|
3
|
+
# ossplate:workflow-name:end
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
workflow_run:
|
|
7
|
+
workflows: ["Ossplate CI"]
|
|
8
|
+
types: [completed]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: release-main
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
actions: write
|
|
17
|
+
contents: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
release:
|
|
21
|
+
if: >
|
|
22
|
+
github.event_name == 'workflow_dispatch' ||
|
|
23
|
+
(
|
|
24
|
+
github.event_name == 'workflow_run' &&
|
|
25
|
+
github.event.workflow_run.conclusion == 'success' &&
|
|
26
|
+
github.event.workflow_run.head_branch == 'main'
|
|
27
|
+
)
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v5
|
|
31
|
+
with:
|
|
32
|
+
ref: main
|
|
33
|
+
fetch-depth: 0
|
|
34
|
+
- uses: actions/setup-node@v5
|
|
35
|
+
with:
|
|
36
|
+
node-version: '24'
|
|
37
|
+
- name: Ensure release matches the validated commit
|
|
38
|
+
id: validated
|
|
39
|
+
run: |
|
|
40
|
+
HEAD_SHA=$(git rev-parse HEAD)
|
|
41
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
42
|
+
echo "::notice title=release::manual dispatch requested; validating current main HEAD."
|
|
43
|
+
echo "validated_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"
|
|
44
|
+
echo "proceed=true" >> "$GITHUB_OUTPUT"
|
|
45
|
+
else
|
|
46
|
+
if [ "$HEAD_SHA" != "${{ github.event.workflow_run.head_sha }}" ]; then
|
|
47
|
+
echo "::notice title=release::main advanced beyond the validated commit; waiting for the newer CI run."
|
|
48
|
+
echo "proceed=false" >> "$GITHUB_OUTPUT"
|
|
49
|
+
else
|
|
50
|
+
echo "validated_sha=${{ github.event.workflow_run.head_sha }}" >> "$GITHUB_OUTPUT"
|
|
51
|
+
echo "proceed=true" >> "$GITHUB_OUTPUT"
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
- name: Skip release commits
|
|
55
|
+
id: commit
|
|
56
|
+
if: steps.validated.outputs.proceed == 'true'
|
|
57
|
+
run: |
|
|
58
|
+
SUBJECT=$(git log -1 --pretty=%s "${{ steps.validated.outputs.validated_sha }}")
|
|
59
|
+
echo "subject=$SUBJECT" >> "$GITHUB_OUTPUT"
|
|
60
|
+
if echo "$SUBJECT" | grep -q '^Release ossplate '; then
|
|
61
|
+
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
62
|
+
else
|
|
63
|
+
echo "skip=false" >> "$GITHUB_OUTPUT"
|
|
64
|
+
fi
|
|
65
|
+
- name: Plan version bump
|
|
66
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true'
|
|
67
|
+
id: plan
|
|
68
|
+
run: |
|
|
69
|
+
PLAN=$(node ./scripts/release-plan.mjs)
|
|
70
|
+
echo "$PLAN"
|
|
71
|
+
echo "should_release=$(printf '%s' "$PLAN" | node -e "process.stdout.write(String(JSON.parse(require('fs').readFileSync(0, 'utf8')).shouldRelease))")" >> "$GITHUB_OUTPUT"
|
|
72
|
+
echo "next_version=$(printf '%s' "$PLAN" | node -e "process.stdout.write(JSON.parse(require('fs').readFileSync(0, 'utf8')).nextVersion)")" >> "$GITHUB_OUTPUT"
|
|
73
|
+
- name: Set up git identity
|
|
74
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true' && steps.plan.outputs.should_release == 'true'
|
|
75
|
+
run: |
|
|
76
|
+
git config user.name "github-actions[bot]"
|
|
77
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
78
|
+
- name: Bump versions
|
|
79
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true' && steps.plan.outputs.should_release == 'true'
|
|
80
|
+
run: node ./scripts/bump-version.mjs "${{ steps.plan.outputs.next_version }}"
|
|
81
|
+
- name: Install JavaScript dependencies
|
|
82
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true' && steps.plan.outputs.should_release == 'true'
|
|
83
|
+
run: npm ci --prefix wrapper-js
|
|
84
|
+
- name: Verify release state
|
|
85
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true' && steps.plan.outputs.should_release == 'true'
|
|
86
|
+
run: ./scripts/verify.sh
|
|
87
|
+
- name: Commit and tag release
|
|
88
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true' && steps.plan.outputs.should_release == 'true'
|
|
89
|
+
run: |
|
|
90
|
+
VERSION="${{ steps.plan.outputs.next_version }}"
|
|
91
|
+
git add -A
|
|
92
|
+
git commit -m "Release ossplate ${VERSION} [skip ci]"
|
|
93
|
+
git tag "v${VERSION}"
|
|
94
|
+
git push origin main
|
|
95
|
+
git push origin "v${VERSION}"
|
|
96
|
+
- name: Create GitHub release
|
|
97
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true' && steps.plan.outputs.should_release == 'true'
|
|
98
|
+
env:
|
|
99
|
+
GH_TOKEN: ${{ github.token }}
|
|
100
|
+
run: |
|
|
101
|
+
VERSION="${{ steps.plan.outputs.next_version }}"
|
|
102
|
+
if gh release view "v${VERSION}" >/dev/null 2>&1; then
|
|
103
|
+
echo "::notice title=release::GitHub release v${VERSION} already exists; skipping."
|
|
104
|
+
exit 0
|
|
105
|
+
fi
|
|
106
|
+
gh release create "v${VERSION}" \
|
|
107
|
+
--title "v${VERSION}" \
|
|
108
|
+
--notes "Automated release for ossplate ${VERSION}."
|
|
109
|
+
- name: Dispatch publish workflows
|
|
110
|
+
if: steps.validated.outputs.proceed == 'true' && steps.commit.outputs.skip != 'true' && steps.plan.outputs.should_release == 'true'
|
|
111
|
+
env:
|
|
112
|
+
GH_TOKEN: ${{ github.token }}
|
|
113
|
+
run: |
|
|
114
|
+
VERSION="${{ steps.plan.outputs.next_version }}"
|
|
115
|
+
gh workflow run publish.yml --ref main
|
|
116
|
+
gh workflow run publish-npm.yml --ref main
|
|
117
|
+
echo "::notice title=release::dispatched publish workflows for v${VERSION}."
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Use the root verification flow before committing changes:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
./scripts/verify.sh
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Optional local hook setup:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -m pip install pre-commit
|
|
13
|
+
pre-commit install --hook-type pre-push
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
That enables a local `pre-push` hook which runs `./scripts/verify.sh`.
|
|
17
|
+
|
|
18
|
+
That script mirrors the local release-confidence gate:
|
|
19
|
+
|
|
20
|
+
- Rust format, clippy, and tests
|
|
21
|
+
- `ossplate validate` and `ossplate sync --check`
|
|
22
|
+
- JavaScript wrapper tests and package dry-run
|
|
23
|
+
- Python wrapper tests
|
|
24
|
+
|
|
25
|
+
Useful operator commands:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cargo run --manifest-path core-rs/Cargo.toml -- validate
|
|
29
|
+
cargo run --manifest-path core-rs/Cargo.toml -- sync --check
|
|
30
|
+
cargo run --manifest-path core-rs/Cargo.toml -- sync
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Release bump rules:
|
|
34
|
+
|
|
35
|
+
- `feat:` triggers a minor bump
|
|
36
|
+
- `fix:`, `docs:`, `refactor:`, `test:`, `chore:`, `build:`, `ci:` and similar commits trigger a patch bump
|
|
37
|
+
- `!` in a conventional commit header or `BREAKING CHANGE` in the body triggers a major bump
|
|
38
|
+
- `[major]`, `[minor]`, and `[patch]` override the inferred bump level
|
|
39
|
+
|
|
40
|
+
Read this next:
|
|
41
|
+
|
|
42
|
+
- [`docs/architecture.md`](./docs/architecture.md)
|
|
43
|
+
- [`docs/testing.md`](./docs/testing.md)
|
|
44
|
+
- [`docs/releases.md`](./docs/releases.md)
|
|
45
|
+
- [`docs/adrs/0002-sync-owns-bounded-identity.md`](./docs/adrs/0002-sync-owns-bounded-identity.md)
|
|
46
|
+
|
|
47
|
+
Current ownership model:
|
|
48
|
+
|
|
49
|
+
- `ossplate.toml` is the canonical identity source
|
|
50
|
+
- `sync` owns Rust/npm/Python metadata surfaces
|
|
51
|
+
- `sync` owns the root `README.md` identity block between `ossplate:readme-identity` markers
|
|
52
|
+
- `sync` owns the top-level workflow display names between `ossplate:workflow-name` markers
|
|
53
|
+
- workflow logic, auth, triggers, and job structure remain manual
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
|
|
4
|
+
|
|
5
|
+
In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
8
|
+
|
|
9
|
+
For more information, please refer to <http://unlicense.org/>
|