ossplate 0.1.9__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.
- ossplate-0.1.9/.gitignore +9 -0
- ossplate-0.1.9/PKG-INFO +44 -0
- ossplate-0.1.9/README.md +30 -0
- ossplate-0.1.9/hatch_build.py +97 -0
- ossplate-0.1.9/ossplate/bin/linux-x64/ossplate +0 -0
- ossplate-0.1.9/pyproject.toml +40 -0
- ossplate-0.1.9/src/ossplate/__init__.py +3 -0
- ossplate-0.1.9/src/ossplate/bin/darwin-arm64/ossplate +0 -0
- ossplate-0.1.9/src/ossplate/bin/darwin-x64/ossplate +3 -0
- ossplate-0.1.9/src/ossplate/bin/linux-x64/ossplate +0 -0
- ossplate-0.1.9/src/ossplate/bin/win32-x64/ossplate.exe +3 -0
- ossplate-0.1.9/src/ossplate/cli.py +55 -0
- ossplate-0.1.9/src/ossplate/scaffold/.github/workflows/ci.yml +111 -0
- ossplate-0.1.9/src/ossplate/scaffold/.github/workflows/publish-npm.yml +72 -0
- ossplate-0.1.9/src/ossplate/scaffold/.github/workflows/publish.yml +173 -0
- ossplate-0.1.9/src/ossplate/scaffold/.github/workflows/release.yml +117 -0
- ossplate-0.1.9/src/ossplate/scaffold/.gitignore +9 -0
- ossplate-0.1.9/src/ossplate/scaffold/.pre-commit-config.yaml +9 -0
- ossplate-0.1.9/src/ossplate/scaffold/CONTRIBUTING.md +53 -0
- ossplate-0.1.9/src/ossplate/scaffold/LICENSE +9 -0
- ossplate-0.1.9/src/ossplate/scaffold/README.md +81 -0
- ossplate-0.1.9/src/ossplate/scaffold/assets/illustrations/chestplate.svg +6 -0
- ossplate-0.1.9/src/ossplate/scaffold/core-rs/Cargo.lock +338 -0
- ossplate-0.1.9/src/ossplate/scaffold/core-rs/Cargo.toml +28 -0
- ossplate-0.1.9/src/ossplate/scaffold/core-rs/src/main.rs +1730 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/README.md +16 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/adrs/0001-rust-core-thin-wrappers.md +21 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/adrs/0002-sync-owns-bounded-identity.md +31 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/adrs/0003-curated-scaffold-payload.md +21 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/architecture.md +89 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/customizing-the-template.md +121 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/releases.md +91 -0
- ossplate-0.1.9/src/ossplate/scaffold/docs/testing.md +76 -0
- ossplate-0.1.9/src/ossplate/scaffold/ossplate.toml +15 -0
- ossplate-0.1.9/src/ossplate/scaffold/scripts/bump-version.mjs +53 -0
- ossplate-0.1.9/src/ossplate/scaffold/scripts/release-plan.mjs +94 -0
- ossplate-0.1.9/src/ossplate/scaffold/scripts/verify.sh +36 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-js/README.md +30 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-js/bin/ossplate.js +5 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-js/package-lock.json +51 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-js/package.json +43 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-js/src/index.ts +69 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-js/tsconfig.json +14 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-py/README.md +30 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-py/hatch_build.py +97 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-py/pyproject.toml +40 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-py/src/ossplate/__init__.py +3 -0
- ossplate-0.1.9/src/ossplate/scaffold/wrapper-py/src/ossplate/cli.py +55 -0
- ossplate-0.1.9/tests/fixtures/ossplate-stub.sh +18 -0
- ossplate-0.1.9/tests/test_cli.py +237 -0
ossplate-0.1.9/PKG-INFO
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ossplate
|
|
3
|
+
Version: 0.1.9
|
|
4
|
+
Summary: Build one project, ship it everywhere.
|
|
5
|
+
Project-URL: Homepage, https://github.com/stefdevscore/ossplate
|
|
6
|
+
Project-URL: Repository, https://github.com/stefdevscore/ossplate
|
|
7
|
+
Author-email: Stef <stefdevscore@github.com>
|
|
8
|
+
License: Unlicense
|
|
9
|
+
Classifier: License :: Public Domain
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# Ossplate
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<img src="https://raw.githubusercontent.com/stefdevscore/ossplate/main/assets/illustrations/chestplate.svg" alt="Ossplate armor" width="320">
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
`ossplate` helps you start and maintain a project that ships the same CLI through Rust, npm, and PyPI.
|
|
22
|
+
|
|
23
|
+
Use it to:
|
|
24
|
+
|
|
25
|
+
- create a new scaffolded project
|
|
26
|
+
- initialize an existing directory
|
|
27
|
+
- validate project identity and metadata
|
|
28
|
+
- keep owned files in sync
|
|
29
|
+
|
|
30
|
+
Common commands:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
ossplate version
|
|
34
|
+
ossplate create <target>
|
|
35
|
+
ossplate init --path <dir>
|
|
36
|
+
ossplate validate
|
|
37
|
+
ossplate sync --check
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Learn more:
|
|
41
|
+
|
|
42
|
+
- [Main documentation](../docs/README.md)
|
|
43
|
+
- [Testing guide](../docs/testing.md)
|
|
44
|
+
- [Architecture](../docs/architecture.md)
|
ossplate-0.1.9/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Ossplate
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/stefdevscore/ossplate/main/assets/illustrations/chestplate.svg" alt="Ossplate armor" width="320">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
`ossplate` helps you start and maintain a project that ships the same CLI through Rust, npm, and PyPI.
|
|
8
|
+
|
|
9
|
+
Use it to:
|
|
10
|
+
|
|
11
|
+
- create a new scaffolded project
|
|
12
|
+
- initialize an existing directory
|
|
13
|
+
- validate project identity and metadata
|
|
14
|
+
- keep owned files in sync
|
|
15
|
+
|
|
16
|
+
Common commands:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
ossplate version
|
|
20
|
+
ossplate create <target>
|
|
21
|
+
ossplate init --path <dir>
|
|
22
|
+
ossplate validate
|
|
23
|
+
ossplate sync --check
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Learn more:
|
|
27
|
+
|
|
28
|
+
- [Main documentation](../docs/README.md)
|
|
29
|
+
- [Testing guide](../docs/testing.md)
|
|
30
|
+
- [Architecture](../docs/architecture.md)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import subprocess
|
|
6
|
+
import sysconfig
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
11
|
+
except ModuleNotFoundError: # pragma: no cover - exercised in local unit tests without hatchling
|
|
12
|
+
class BuildHookInterface: # type: ignore[override]
|
|
13
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
BUILD_TARGET_ENV = "OSSPLATE_PY_TARGET"
|
|
17
|
+
TARGETS = {
|
|
18
|
+
"darwin-arm64": "ossplate",
|
|
19
|
+
"darwin-x64": "ossplate",
|
|
20
|
+
"linux-x64": "ossplate",
|
|
21
|
+
"win32-x64": "ossplate.exe",
|
|
22
|
+
}
|
|
23
|
+
HOST_TARGETS = {
|
|
24
|
+
("Darwin", "arm64"): "darwin-arm64",
|
|
25
|
+
("Darwin", "x86_64"): "darwin-x64",
|
|
26
|
+
("Linux", "x86_64"): "linux-x64",
|
|
27
|
+
("Windows", "AMD64"): "win32-x64",
|
|
28
|
+
("Windows", "x86_64"): "win32-x64",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class CustomBuildHook(BuildHookInterface):
|
|
33
|
+
def initialize(self, version: str, build_data: dict) -> None:
|
|
34
|
+
repo_root = Path(self.root).resolve().parent
|
|
35
|
+
script = repo_root / "scripts" / "stage-distribution-assets.mjs"
|
|
36
|
+
try:
|
|
37
|
+
subprocess.run(["node", str(script)], cwd=repo_root, check=True)
|
|
38
|
+
except FileNotFoundError as error:
|
|
39
|
+
raise RuntimeError("node is required to stage distribution assets for wrapper-py builds") from error
|
|
40
|
+
|
|
41
|
+
target = resolve_build_target()
|
|
42
|
+
binary_name = TARGETS[target]
|
|
43
|
+
binary_source = repo_root / "wrapper-js" / "bin" / target / binary_name
|
|
44
|
+
if not binary_source.exists():
|
|
45
|
+
raise RuntimeError(
|
|
46
|
+
f"required ossplate binary for target {target} is missing at {binary_source}"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
build_data["pure_python"] = False
|
|
50
|
+
build_data["tag"] = f"py3-none-{platform_tag_for_target(target)}"
|
|
51
|
+
force_include = build_data.setdefault("force_include", {})
|
|
52
|
+
force_include[str(binary_source)] = f"ossplate/bin/{target}/{binary_name}"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def resolve_build_target() -> str:
|
|
56
|
+
target = os.environ.get(BUILD_TARGET_ENV)
|
|
57
|
+
if target:
|
|
58
|
+
if target not in TARGETS:
|
|
59
|
+
raise RuntimeError(f"unsupported {BUILD_TARGET_ENV} value: {target}")
|
|
60
|
+
return target
|
|
61
|
+
|
|
62
|
+
host = HOST_TARGETS.get((platform.system(), platform.machine()))
|
|
63
|
+
if host is None:
|
|
64
|
+
raise RuntimeError(
|
|
65
|
+
f"unsupported host platform for wrapper-py wheel build: {platform.system()}/{platform.machine()}"
|
|
66
|
+
)
|
|
67
|
+
return host
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def platform_tag_for_target(target: str) -> str:
|
|
71
|
+
if target == "linux-x64":
|
|
72
|
+
return linux_platform_tag()
|
|
73
|
+
if target == "darwin-arm64":
|
|
74
|
+
return macos_platform_tag("arm64")
|
|
75
|
+
if target == "darwin-x64":
|
|
76
|
+
return macos_platform_tag("x86_64")
|
|
77
|
+
if target == "win32-x64":
|
|
78
|
+
return "win_amd64"
|
|
79
|
+
raise RuntimeError(f"unsupported target for wheel tag generation: {target}")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def linux_platform_tag() -> str:
|
|
83
|
+
libc_name, libc_version = platform.libc_ver()
|
|
84
|
+
if libc_name != "glibc" or not libc_version:
|
|
85
|
+
raise RuntimeError("linux wheel builds require glibc to derive a manylinux platform tag")
|
|
86
|
+
|
|
87
|
+
major, minor, *_rest = libc_version.split(".")
|
|
88
|
+
return f"manylinux_{major}_{minor}_x86_64"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def macos_platform_tag(arch: str) -> str:
|
|
92
|
+
tag = sysconfig.get_platform().replace("-", "_").replace(".", "_")
|
|
93
|
+
if "universal2" in tag:
|
|
94
|
+
return tag.replace("universal2", arch)
|
|
95
|
+
if tag.endswith("_x86_64") or tag.endswith("_arm64"):
|
|
96
|
+
return tag.rsplit("_", 1)[0] + f"_{arch}"
|
|
97
|
+
return f"{tag}_{arch}"
|
|
Binary file
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ossplate"
|
|
7
|
+
version = "0.1.9"
|
|
8
|
+
description = "Build one project, ship it everywhere."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "Unlicense" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Stef", email = "stefdevscore@github.com" }
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"License :: Public Domain",
|
|
18
|
+
"Operating System :: OS Independent"
|
|
19
|
+
]
|
|
20
|
+
dependencies = []
|
|
21
|
+
|
|
22
|
+
[project.urls]
|
|
23
|
+
Homepage = "https://github.com/stefdevscore/ossplate"
|
|
24
|
+
Repository = "https://github.com/stefdevscore/ossplate"
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
ossplate = "ossplate.cli:main"
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.targets.wheel]
|
|
30
|
+
packages = ["src/ossplate"]
|
|
31
|
+
artifacts = [
|
|
32
|
+
"src/ossplate/scaffold/**",
|
|
33
|
+
]
|
|
34
|
+
exclude = [
|
|
35
|
+
"src/ossplate/bin/**",
|
|
36
|
+
]
|
|
37
|
+
pure_python = false
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.hooks.custom]
|
|
40
|
+
path = "hatch_build.py"
|
|
Binary file
|
|
Binary file
|
|
@@ -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"
|