Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 40 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ on:
tags: ["v*"]
pull_request:
workflow_dispatch:
workflow_call:
inputs:
publishing:
type: boolean
default: false

jobs:
# The payload path reads JSON that is generated, not committed: the SysML Toolkit's exports of
Expand Down Expand Up @@ -145,6 +150,7 @@ jobs:
node examples/typescript/tutorial.mjs
node examples/queries/typescript/demo.mjs --payload | diff - examples/queries/expected/report.txt
node ts/toolkit_checks.mjs
node ts/library_checks.mjs

- name: TS strict type check
working-directory: ts
Expand Down Expand Up @@ -187,6 +193,7 @@ jobs:
javac --enable-preview --release 21 -d /tmp/java-out $(find java/src -name '*.java')
java --enable-preview -cp /tmp/java-out org.openmbee.sysml.checks.Checks
java --enable-preview -cp /tmp/java-out org.openmbee.sysml.checks.ToolkitChecks
java --enable-preview -cp /tmp/java-out org.openmbee.sysml.checks.LibraryChecks
javac --enable-preview --release 21 -cp /tmp/java-out -d /tmp/java-out examples/queries/java/*.java
java --enable-preview -cp /tmp/java-out QueriesDemo --payload | diff - examples/queries/expected/report.txt

Expand All @@ -204,6 +211,7 @@ jobs:
g++ -std=c++17 -Wall -Werror -O0 -I cpp/include -I vendor \
cpp/checks/checks.cpp cpp/checks/conformance.g.cpp -o /tmp/cpp-checks
g++ -std=c++17 -Wall -Werror -I cpp/include -I vendor cpp/checks/toolkit_checks.cpp -o /tmp/cpp-toolkit-checks && /tmp/cpp-toolkit-checks
g++ -std=c++17 -Wall -Werror -I cpp/include -I vendor cpp/checks/library_checks.cpp -o /tmp/cpp-library-checks && /tmp/cpp-library-checks
/tmp/cpp-checks
g++ -std=c++17 -Wall -Werror -I cpp/include -I vendor examples/queries/cpp/demo.cpp -o /tmp/queries-demo -ldl
/tmp/queries-demo --payload | diff - examples/queries/expected/report.txt
Expand All @@ -219,6 +227,7 @@ jobs:
# on main, and when started by hand (Actions, "Run workflow"), not on every push.
if: >-
github.event_name == 'workflow_dispatch' ||
inputs.publishing == true ||
startsWith(github.ref, 'refs/tags/v') ||
github.ref == 'refs/heads/main'
strategy:
Expand Down Expand Up @@ -392,10 +401,13 @@ jobs:
python tools/package_abi.py wasm32-unknown-unknown --out "$RUNNER_TEMP/dist"
fi

# The wheel carries the standard library models, so every runner fetches them here (the Linux
# one already has them, for the Annex A test).
- name: Python wheel for this platform, installed and read through
run: |
git -c core.longpaths=true -C ../sysml-toolkit submodule update --init --depth 1 spec-refs/SysML-v2-Release
python -m pip install --quiet build wheel
python tools/package.py python --target ${{ matrix.target }} --out "$RUNNER_TEMP/dist"
python tools/package.py python --target ${{ matrix.target }} --library-dir ../sysml-toolkit/spec-refs/SysML-v2-Release/sysml.library --out "$RUNNER_TEMP/dist"
python tools/check_packages.py python --dist "$RUNNER_TEMP/dist"

# Packages that are the same on every platform and carry no native library: built and checked
Expand All @@ -405,7 +417,7 @@ jobs:
if: runner.os == 'Linux'
run: |
python tools/package.py sdist --out "$RUNNER_TEMP/dist"
python tools/package.py npm --out "$RUNNER_TEMP/dist"
python tools/package.py npm --library-dir ../sysml-toolkit/spec-refs/SysML-v2-Release/sysml.library --out "$RUNNER_TEMP/dist"
python tools/check_packages.py npm --dist "$RUNNER_TEMP/dist"

- uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -442,11 +454,33 @@ jobs:
pattern: packages-*
path: ${{ runner.temp }}/abi
merge-multiple: true
# The packages carry the standard library models: the specification's release, from the
# pinned SysML Toolkit's submodule.
- name: Read the SysML Toolkit pin
id: pin
run: |
python - >> "$GITHUB_OUTPUT" <<'EOF'
import json
k = json.load(open("vendor/sysml-toolkit/PIN.json"))["toolkit"]
print("repository=" + k["repository"].removeprefix("https://github.com/"))
print("tag=" + k["tag"])
print("commit=" + k["commit"])
EOF
- uses: actions/checkout@v4
with:
repository: ${{ steps.pin.outputs.repository }}
ref: ${{ steps.pin.outputs.tag }}
path: sysml-toolkit
- name: The SysML Toolkit checkout is the pinned commit, with the specification's library
run: |
test "$(git -C sysml-toolkit rev-parse HEAD)" = "${{ steps.pin.outputs.commit }}"
git -C sysml-toolkit submodule update --init --depth 1 spec-refs/SysML-v2-Release
- name: Jar, NuGet package and C++ archive, with every platform's binding library
run: |
python tools/package.py java --javac22 "$JAVA_HOME_25_X64/bin/javac" --abi-archives "$RUNNER_TEMP/abi" --out "$RUNNER_TEMP/dist"
python tools/package.py csharp --abi-archives "$RUNNER_TEMP/abi" --out "$RUNNER_TEMP/dist"
python tools/package.py cpp --abi-archives "$RUNNER_TEMP/abi" --out "$RUNNER_TEMP/dist"
L=sysml-toolkit/spec-refs/SysML-v2-Release/sysml.library
python tools/package.py java --javac22 "$JAVA_HOME_25_X64/bin/javac" --abi-archives "$RUNNER_TEMP/abi" --library-dir "$L" --out "$RUNNER_TEMP/dist"
python tools/package.py csharp --abi-archives "$RUNNER_TEMP/abi" --library-dir "$L" --out "$RUNNER_TEMP/dist"
python tools/package.py cpp --abi-archives "$RUNNER_TEMP/abi" --library-dir "$L" --out "$RUNNER_TEMP/dist"
python - <<'EOF'
import glob, os, sys, zipfile
libs = ("sysmlv2_abi.dll", "libsysmlv2_abi.so", "libsysmlv2_abi.dylib")
Expand Down Expand Up @@ -540,7 +574,7 @@ jobs:
# A version tag publishes a draft release with every package and the changelog section as its
# notes; the draft is made public by hand. A tag with a suffix (v0.1.0-rc1) is a prerelease.
release:
if: startsWith(github.ref, 'refs/tags/v')
if: startsWith(github.ref, 'refs/tags/v') && inputs.publishing != true
needs: [example-json, generate-and-test, csharp, java, cpp, toolkit, portable, portable-check]
runs-on: ubuntu-latest
permissions:
Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Validate distributions
on:
workflow_call:
permissions:
contents: read
jobs:
build:
# The shared CI contains the tag-only draft-release job, disabled by publishing.
permissions:
contents: write
uses: ./.github/workflows/ci.yml
with:
publishing: true
validate:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/download-artifact@v4
with:
pattern: packages-*
path: packages/
merge-multiple: true
- name: Select Python distributions
run: |
mkdir dist
cp packages/sysml-*.whl packages/sysml-*.tar.gz dist/
- run: python -m pip install build twine
- run: python -m twine check --strict dist/*
- name: Check package name, version and platform coverage
run: python tools/check_python_distributions.py dist
- name: Build and check wheel from source distribution
run: |
python -m pip wheel --no-deps dist/*.tar.gz --wheel-dir "$RUNNER_TEMP/sdist-wheels"
python -m twine check --strict "$RUNNER_TEMP"/sdist-wheels/*
python -m venv "$RUNNER_TEMP/sdist-test"
"$RUNNER_TEMP/sdist-test/bin/python" -m pip install "$RUNNER_TEMP"/sdist-wheels/*.whl
cd "$RUNNER_TEMP"
"$RUNNER_TEMP/sdist-test/bin/python" -c "from sysml import Model, PayloadLibrary; from sysml.classes import PartUsage; assert Model.from_full_json([]).all() == []"
- uses: actions/upload-artifact@v4
with:
name: distributions
path: dist/*
if-no-files-found: error
40 changes: 40 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Publish sysml
on:
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
jobs:
build:
permissions:
contents: write
uses: ./.github/workflows/package.yml
testpypi:
if: github.event_name == 'workflow_dispatch'
needs: build
runs-on: ubuntu-latest
environment: testpypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: distributions
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
pypi:
if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags/v')
needs: build
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: distributions
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
27 changes: 27 additions & 0 deletions .github/workflows/test-sysml.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Test sysml
on:
push:
branches: [main, develop, 'release/**']
pull_request:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: python -m pip install -e '.[dev]'
# Native and generated-example checks run in the shared CI pipeline.
- run: python -m pytest -v --tb=short --junitxml=test-results/results.xml
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.python-version }}
path: test-results/
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ python/sysml/_native/
ts/sysmlv2_abi.wasm
ts/LICENSE
ts/NOTICE
python/sysml/stdlib/
ts/stdlib/

# Query example build outputs
examples/queries/java/out/
Expand All @@ -31,3 +33,4 @@ examples/sysml.library.full.json
# Binding libraries tools/package.py stages for the NuGet package
csharp/*/runtimes/
csharp/*/THIRD-PARTY/
csharp/*/stdlib/
14 changes: 12 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Changelog

## 0.1.0, preview
## 0.1.0

The first release.

Expand Down Expand Up @@ -37,6 +37,15 @@ The first release.
element id. The SysML Toolkit backend reads the standard library from a directory in every
language, and in JavaScript also from the library's files given as sources, in a browser as well.
A model file or library directory that does not exist is named in the error.
- The standard library at hand in every language, as the first step of a program: every package
carries its models (`standard_library()` in Python, `standardLibrary()` in JavaScript,
`StandardLibrary.directory()` in Java, `StandardLibrary.Directory()` in C#, and in C++
`sysml::standard_library()` for the archive's `sysml.library/` copied beside the program), and
`standard_library_json()` and its counterparts download the library JSON from the release on their
first call, check it against the SHA-256 GitHub states for it, and keep it in a cache all languages
share (C++ reads the cache, and downloads nothing). `SYSML_LIBRARY_JSON`, `SYSML_LIBRARY_DIR` (C++)
and `SYSML_CACHE_DIR` name other places. The packages that carry the models declare their license
as Apache-2.0 AND EPL-2.0.
- The standard library, `sysml_library-<version>.zip`, in the two forms the backends read: the
library models as the SysML v2 release has them (`sysml.library/`, for the SysML Toolkit), and the
library as full-form JSON written by the SysML Toolkit under the element ids KerML 9.1 and
Expand Down Expand Up @@ -125,4 +134,5 @@ Platforms and packages:
on Windows by hand.
- On macOS a library downloaded through a web browser is quarantined; remove the attribute with
`xattr -d com.apple.quarantine`.
- The packages are release assets only; they are not on the language registries yet.
- Python is on PyPI (`pip install sysml`); the other packages are release assets, not on their
language registries yet.
76 changes: 76 additions & 0 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Publishing sysml

The Python distribution and import name are both `sysml`. Publication runs from
`Open-MBEE/sysml-sdk`, using `.github/workflows/publish.yml`.

## One-time registry setup

Create GitHub environments named `pypi` and `testpypi` in `Open-MBEE/sysml-sdk`.
Configure a trusted publisher separately on PyPI and TestPyPI:

| Field | PyPI | TestPyPI |
|---|---|---|
| Project name | `sysml` | `sysml` |
| Repository owner | `Open-MBEE` | `Open-MBEE` |
| Repository name | `sysml-sdk` | `sysml-sdk` |
| Workflow filename | `publish.yml` | `publish.yml` |
| Environment | `pypi` | `testpypi` |

For a new project use a pending publisher in the registry's account publishing
settings; for an existing project its owner must add the publisher in the project's
publishing settings. The project name must be available or controlled by the publisher's
account. No API token secrets are required.

See [PyPI trusted publisher setup](https://docs.pypi.org/trusted-publishers/adding-a-publisher/)
and [creating a project](https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/).

## TestPyPI

Run **Publish sysml** manually in GitHub Actions, selecting the branch or tag to test.
Every manual run targets TestPyPI. Each published version must be unique; update
`pyproject.toml` before uploading a version already present on that registry.

```sh
python -m pip install --index-url https://test.pypi.org/simple/ sysml==0.1.0
```

## PyPI

Set the version in `pyproject.toml`, keep the other language versions and changelog
consistent, and push its matching tag (for example `v0.1.0`). Existing CI builds and
checks all release assets and creates a draft GitHub release. Publish that draft to
trigger **Publish sysml**, which rebuilds and validates before uploading to PyPI.
Publishing does not create another draft release.

After committing the release version and changelog, create and push the tag:

```sh
git tag v0.1.0
git push origin v0.1.0
```

Wait for the tag's **CI** run to succeed, open the draft under the repository's
**Releases**, and select **Publish release**. Watch **Publish sysml** in **Actions**;
its `pypi` job uploads the distributions. A manual workflow run uploads to TestPyPI,
even when you select a release tag.

After publication, verify installation in a fresh virtual environment:

```sh
python -m venv .venv-pypi-check
# Activate: source .venv-pypi-check/bin/activate (Linux/macOS)
# or .venv-pypi-check\Scripts\Activate.ps1 (PowerShell)
python -m pip install sysml==0.1.0
python -c "from importlib.metadata import version; from sysml import Model; print(version('sysml'))"
```

Replace `0.1.0` with the release version. Uploaded distribution files cannot be
overwritten; use a new version when correcting a published package.

The shared packaging workflow reuses the full CI pipeline, including native backend
and installed-package checks. It publishes exactly four native platform wheels and
one source distribution. Twine validates metadata, package names and versions are
checked, release tags must match `pyproject.toml`, and the source distribution is
rebuilt and imported outside the checkout before publication. Source installations
provide the payload backend; use a supported platform wheel for the bundled Toolkit
backend. The standard library remains a separate GitHub release asset.
Loading
Loading