simrun 0.1.0__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.
- simrun-0.1.0/.bumpversion.toml +24 -0
- simrun-0.1.0/.github/CODEOWNERS +1 -0
- simrun-0.1.0/.github/actions/setup/action.yml +48 -0
- simrun-0.1.0/.github/dependabot.yml +55 -0
- simrun-0.1.0/.github/pull_request_template.md +13 -0
- simrun-0.1.0/.github/rulesets/apply.sh +43 -0
- simrun-0.1.0/.github/rulesets/develop.json +61 -0
- simrun-0.1.0/.github/rulesets/main.json +25 -0
- simrun-0.1.0/.github/rulesets/tags.json +16 -0
- simrun-0.1.0/.github/workflows/ci-cd.yml +277 -0
- simrun-0.1.0/.github/workflows/cluster.yml +82 -0
- simrun-0.1.0/.github/workflows/docs.yml +67 -0
- simrun-0.1.0/.github/workflows/lint.yml +63 -0
- simrun-0.1.0/.gitignore +40 -0
- simrun-0.1.0/.pre-commit-config.yaml +64 -0
- simrun-0.1.0/.python-version +1 -0
- simrun-0.1.0/.ruff.toml +56 -0
- simrun-0.1.0/.zenodo.json +33 -0
- simrun-0.1.0/CITATION.cff +22 -0
- simrun-0.1.0/CLAUDE.md +69 -0
- simrun-0.1.0/LICENSE +7 -0
- simrun-0.1.0/PKG-INFO +107 -0
- simrun-0.1.0/README.md +50 -0
- simrun-0.1.0/deploy/cluster/argo/controller-config.yaml +19 -0
- simrun-0.1.0/deploy/cluster/argo/kustomization.yaml +12 -0
- simrun-0.1.0/deploy/cluster/argo/namespace-install.yaml +192212 -0
- simrun-0.1.0/deploy/cluster/argo/workflow-rbac.yaml +31 -0
- simrun-0.1.0/deploy/cluster/buildkit.yaml +94 -0
- simrun-0.1.0/deploy/cluster/kueue/config.yaml +38 -0
- simrun-0.1.0/deploy/cluster/kueue/kustomization.yaml +9 -0
- simrun-0.1.0/deploy/cluster/kueue/manifests.yaml +28482 -0
- simrun-0.1.0/deploy/cluster/kueue/queues.yaml +57 -0
- simrun-0.1.0/deploy/cluster/kustomization.yaml +43 -0
- simrun-0.1.0/deploy/cluster/namespace.yaml +4 -0
- simrun-0.1.0/deploy/cluster/off-workers.yaml +16 -0
- simrun-0.1.0/deploy/cluster/priority-classes.yaml +88 -0
- simrun-0.1.0/deploy/cluster/simrun.yaml +224 -0
- simrun-0.1.0/deploy/cluster/store-settings.yaml +11 -0
- simrun-0.1.0/deploy/cluster/store.yaml +29 -0
- simrun-0.1.0/deploy/cluster/zot.yaml +95 -0
- simrun-0.1.0/deploy/k3d/buildkit.yaml +27 -0
- simrun-0.1.0/deploy/k3d/kustomization.yaml +61 -0
- simrun-0.1.0/deploy/k3d/on-server.yaml +10 -0
- simrun-0.1.0/deploy/k3d/quotas.yaml +24 -0
- simrun-0.1.0/deploy/k3d/store-claim.yaml +11 -0
- simrun-0.1.0/deploy/k3d/store.yaml +16 -0
- simrun-0.1.0/deploy/service/Dockerfile +39 -0
- simrun-0.1.0/docs/api/argo.md +3 -0
- simrun-0.1.0/docs/api/cgroup.md +3 -0
- simrun-0.1.0/docs/api/cli.md +3 -0
- simrun-0.1.0/docs/api/client.md +3 -0
- simrun-0.1.0/docs/api/config.md +3 -0
- simrun-0.1.0/docs/api/cwl.md +3 -0
- simrun-0.1.0/docs/api/demo.md +3 -0
- simrun-0.1.0/docs/api/environment.md +3 -0
- simrun-0.1.0/docs/api/index.md +46 -0
- simrun-0.1.0/docs/api/ledger.md +3 -0
- simrun-0.1.0/docs/api/mcp.md +3 -0
- simrun-0.1.0/docs/api/planner.md +3 -0
- simrun-0.1.0/docs/api/plugins.md +3 -0
- simrun-0.1.0/docs/api/plugins_builtin.md +3 -0
- simrun-0.1.0/docs/api/podspec.md +3 -0
- simrun-0.1.0/docs/api/resources.md +3 -0
- simrun-0.1.0/docs/api/service.app.md +3 -0
- simrun-0.1.0/docs/api/service.argo_backend.md +3 -0
- simrun-0.1.0/docs/api/service.auth.md +3 -0
- simrun-0.1.0/docs/api/service.backend.md +3 -0
- simrun-0.1.0/docs/api/service.compare.md +3 -0
- simrun-0.1.0/docs/api/service.controller.md +3 -0
- simrun-0.1.0/docs/api/service.index.md +3 -0
- simrun-0.1.0/docs/api/service.logs.md +3 -0
- simrun-0.1.0/docs/api/service.submission.md +3 -0
- simrun-0.1.0/docs/api/snapshot.md +3 -0
- simrun-0.1.0/docs/api/store.md +3 -0
- simrun-0.1.0/docs/api/testing.md +3 -0
- simrun-0.1.0/docs/api/worker.md +3 -0
- simrun-0.1.0/docs/api/workflow.md +3 -0
- simrun-0.1.0/docs/command-line.md +98 -0
- simrun-0.1.0/docs/concepts.md +93 -0
- simrun-0.1.0/docs/deployment.md +90 -0
- simrun-0.1.0/docs/development.md +199 -0
- simrun-0.1.0/docs/index.md +58 -0
- simrun-0.1.0/docs/installation.md +44 -0
- simrun-0.1.0/docs/mcp.md +36 -0
- simrun-0.1.0/docs/plugins.md +58 -0
- simrun-0.1.0/docs/release-notes.md +5 -0
- simrun-0.1.0/docs/robots.txt +9 -0
- simrun-0.1.0/docs/service.md +104 -0
- simrun-0.1.0/docs/testing.md +90 -0
- simrun-0.1.0/docs/web-app.md +86 -0
- simrun-0.1.0/docs/workflows.md +85 -0
- simrun-0.1.0/examples/squares.yaml +7 -0
- simrun-0.1.0/frontend/README.md +22 -0
- simrun-0.1.0/frontend/index.html +13 -0
- simrun-0.1.0/frontend/mockup/workflow-icons.js +43 -0
- simrun-0.1.0/frontend/mockup/workflow-studio.html +921 -0
- simrun-0.1.0/frontend/package-lock.json +3604 -0
- simrun-0.1.0/frontend/package.json +48 -0
- simrun-0.1.0/frontend/public/favicon.svg +1 -0
- simrun-0.1.0/frontend/src/App.vue +18 -0
- simrun-0.1.0/frontend/src/api/client.test.ts +63 -0
- simrun-0.1.0/frontend/src/api/client.ts +98 -0
- simrun-0.1.0/frontend/src/api/http.ts +44 -0
- simrun-0.1.0/frontend/src/api/openapi.json +3402 -0
- simrun-0.1.0/frontend/src/api/schema.d.ts +2379 -0
- simrun-0.1.0/frontend/src/api/sse.test.ts +266 -0
- simrun-0.1.0/frontend/src/api/sse.ts +233 -0
- simrun-0.1.0/frontend/src/auth.ts +53 -0
- simrun-0.1.0/frontend/src/components/AppIcon.vue +20 -0
- simrun-0.1.0/frontend/src/components/EditBar.test.ts +144 -0
- simrun-0.1.0/frontend/src/components/EditBar.vue +139 -0
- simrun-0.1.0/frontend/src/components/EditCanvas.fit.test.ts +68 -0
- simrun-0.1.0/frontend/src/components/EditCanvas.test.ts +93 -0
- simrun-0.1.0/frontend/src/components/EditCanvas.vue +274 -0
- simrun-0.1.0/frontend/src/components/EditInspector.test.ts +139 -0
- simrun-0.1.0/frontend/src/components/EditInspector.vue +55 -0
- simrun-0.1.0/frontend/src/components/EditNode.vue +111 -0
- simrun-0.1.0/frontend/src/components/EditTaskPanel.vue +212 -0
- simrun-0.1.0/frontend/src/components/EditWorkflowPanel.vue +91 -0
- simrun-0.1.0/frontend/src/components/Inspector.test.ts +383 -0
- simrun-0.1.0/frontend/src/components/Inspector.vue +111 -0
- simrun-0.1.0/frontend/src/components/InspectorLogs.vue +109 -0
- simrun-0.1.0/frontend/src/components/InspectorOutputs.vue +96 -0
- simrun-0.1.0/frontend/src/components/InspectorOverview.vue +138 -0
- simrun-0.1.0/frontend/src/components/InspectorRun.vue +111 -0
- simrun-0.1.0/frontend/src/components/LogoMark.vue +18 -0
- simrun-0.1.0/frontend/src/components/RunBar.test.ts +105 -0
- simrun-0.1.0/frontend/src/components/RunBar.vue +158 -0
- simrun-0.1.0/frontend/src/components/RunCanvas.vue +151 -0
- simrun-0.1.0/frontend/src/components/RunCard.vue +86 -0
- simrun-0.1.0/frontend/src/components/RunList.test.ts +99 -0
- simrun-0.1.0/frontend/src/components/RunList.vue +69 -0
- simrun-0.1.0/frontend/src/components/SchemaForm.test.ts +89 -0
- simrun-0.1.0/frontend/src/components/SchemaForm.vue +189 -0
- simrun-0.1.0/frontend/src/components/ServerStrip.test.ts +69 -0
- simrun-0.1.0/frontend/src/components/ServerStrip.vue +83 -0
- simrun-0.1.0/frontend/src/components/StatusPill.vue +23 -0
- simrun-0.1.0/frontend/src/components/TaskNode.test.ts +153 -0
- simrun-0.1.0/frontend/src/components/TaskNode.vue +162 -0
- simrun-0.1.0/frontend/src/components/TaskPalette.test.ts +67 -0
- simrun-0.1.0/frontend/src/components/TaskPalette.vue +75 -0
- simrun-0.1.0/frontend/src/components/TopBar.test.ts +51 -0
- simrun-0.1.0/frontend/src/components/TopBar.vue +89 -0
- simrun-0.1.0/frontend/src/lib/edit-graph.test.ts +140 -0
- simrun-0.1.0/frontend/src/lib/edit-graph.ts +178 -0
- simrun-0.1.0/frontend/src/lib/filters.test.ts +40 -0
- simrun-0.1.0/frontend/src/lib/filters.ts +42 -0
- simrun-0.1.0/frontend/src/lib/format.test.ts +106 -0
- simrun-0.1.0/frontend/src/lib/format.ts +88 -0
- simrun-0.1.0/frontend/src/lib/graph.test.ts +63 -0
- simrun-0.1.0/frontend/src/lib/graph.ts +106 -0
- simrun-0.1.0/frontend/src/lib/icons.ts +42 -0
- simrun-0.1.0/frontend/src/lib/inspect.test.ts +58 -0
- simrun-0.1.0/frontend/src/lib/inspect.ts +153 -0
- simrun-0.1.0/frontend/src/lib/kinds.ts +32 -0
- simrun-0.1.0/frontend/src/lib/progress.test.ts +41 -0
- simrun-0.1.0/frontend/src/lib/progress.ts +44 -0
- simrun-0.1.0/frontend/src/lib/schema-form.test.ts +72 -0
- simrun-0.1.0/frontend/src/lib/schema-form.ts +193 -0
- simrun-0.1.0/frontend/src/lib/status.ts +35 -0
- simrun-0.1.0/frontend/src/lib/workers.ts +52 -0
- simrun-0.1.0/frontend/src/main.ts +6 -0
- simrun-0.1.0/frontend/src/router.test.ts +64 -0
- simrun-0.1.0/frontend/src/router.ts +63 -0
- simrun-0.1.0/frontend/src/stores/edit.test.ts +418 -0
- simrun-0.1.0/frontend/src/stores/edit.ts +297 -0
- simrun-0.1.0/frontend/src/stores/live.test.ts +62 -0
- simrun-0.1.0/frontend/src/stores/live.ts +60 -0
- simrun-0.1.0/frontend/src/stores/run.test.ts +87 -0
- simrun-0.1.0/frontend/src/stores/run.ts +61 -0
- simrun-0.1.0/frontend/src/style.css +35 -0
- simrun-0.1.0/frontend/src/test/fixtures.ts +78 -0
- simrun-0.1.0/frontend/src/views/EditSessions.test.ts +79 -0
- simrun-0.1.0/frontend/src/views/EditSessions.vue +109 -0
- simrun-0.1.0/frontend/src/views/EditorView.test.ts +202 -0
- simrun-0.1.0/frontend/src/views/EditorView.vue +207 -0
- simrun-0.1.0/frontend/src/views/ExecutionsView.vue +97 -0
- simrun-0.1.0/frontend/src/views/LoginView.test.ts +82 -0
- simrun-0.1.0/frontend/src/views/LoginView.vue +78 -0
- simrun-0.1.0/frontend/tsconfig.json +14 -0
- simrun-0.1.0/frontend/tsconfig.node.json +18 -0
- simrun-0.1.0/frontend/vite.config.ts +24 -0
- simrun-0.1.0/pyproject.toml +142 -0
- simrun-0.1.0/release-notes/0.1.0.md +16 -0
- simrun-0.1.0/scripts/llms_txt.py +301 -0
- simrun-0.1.0/scripts/openapi.py +30 -0
- simrun-0.1.0/src/simrun/__init__.py +3 -0
- simrun-0.1.0/src/simrun/argo.py +449 -0
- simrun-0.1.0/src/simrun/build_constraints.txt +20 -0
- simrun-0.1.0/src/simrun/cgroup.py +77 -0
- simrun-0.1.0/src/simrun/cli.py +350 -0
- simrun-0.1.0/src/simrun/client.py +407 -0
- simrun-0.1.0/src/simrun/config.py +63 -0
- simrun-0.1.0/src/simrun/cwl.py +287 -0
- simrun-0.1.0/src/simrun/demo.py +106 -0
- simrun-0.1.0/src/simrun/edit.py +408 -0
- simrun-0.1.0/src/simrun/environment.py +370 -0
- simrun-0.1.0/src/simrun/ledger.py +286 -0
- simrun-0.1.0/src/simrun/mcp.py +161 -0
- simrun-0.1.0/src/simrun/planner.py +303 -0
- simrun-0.1.0/src/simrun/plugins.py +149 -0
- simrun-0.1.0/src/simrun/plugins_builtin.py +33 -0
- simrun-0.1.0/src/simrun/podspec.py +166 -0
- simrun-0.1.0/src/simrun/resources.py +270 -0
- simrun-0.1.0/src/simrun/service/__init__.py +1 -0
- simrun-0.1.0/src/simrun/service/app.py +1721 -0
- simrun-0.1.0/src/simrun/service/argo_backend.py +842 -0
- simrun-0.1.0/src/simrun/service/auth.py +93 -0
- simrun-0.1.0/src/simrun/service/backend.py +170 -0
- simrun-0.1.0/src/simrun/service/compare.py +77 -0
- simrun-0.1.0/src/simrun/service/controller.py +788 -0
- simrun-0.1.0/src/simrun/service/edits.py +406 -0
- simrun-0.1.0/src/simrun/service/index.py +292 -0
- simrun-0.1.0/src/simrun/service/logs.py +91 -0
- simrun-0.1.0/src/simrun/service/submission.py +349 -0
- simrun-0.1.0/src/simrun/snapshot.py +196 -0
- simrun-0.1.0/src/simrun/store.py +190 -0
- simrun-0.1.0/src/simrun/testing.py +263 -0
- simrun-0.1.0/src/simrun/worker.py +1097 -0
- simrun-0.1.0/src/simrun/workflow.py +188 -0
- simrun-0.1.0/tests/cluster/Dockerfile +12 -0
- simrun-0.1.0/tests/cluster/conftest.py +118 -0
- simrun-0.1.0/tests/cluster/k3d_cluster.py +495 -0
- simrun-0.1.0/tests/cluster/local.py +110 -0
- simrun-0.1.0/tests/cluster/test_capacity.py +96 -0
- simrun-0.1.0/tests/cluster/test_cluster.py +228 -0
- simrun-0.1.0/tests/cluster/test_service_image.py +199 -0
- simrun-0.1.0/tests/cluster/test_sources.py +321 -0
- simrun-0.1.0/tests/conftest.py +362 -0
- simrun-0.1.0/tests/service/test_api.py +896 -0
- simrun-0.1.0/tests/service/test_argo_backend.py +782 -0
- simrun-0.1.0/tests/service/test_compare.py +68 -0
- simrun-0.1.0/tests/service/test_controller.py +682 -0
- simrun-0.1.0/tests/service/test_editor_api.py +73 -0
- simrun-0.1.0/tests/service/test_edits.py +374 -0
- simrun-0.1.0/tests/service/test_events.py +102 -0
- simrun-0.1.0/tests/service/test_index.py +216 -0
- simrun-0.1.0/tests/service/test_web_api.py +397 -0
- simrun-0.1.0/tests/test_argo.py +515 -0
- simrun-0.1.0/tests/test_cgroup.py +45 -0
- simrun-0.1.0/tests/test_cli.py +115 -0
- simrun-0.1.0/tests/test_client.py +231 -0
- simrun-0.1.0/tests/test_config.py +20 -0
- simrun-0.1.0/tests/test_cwl.py +193 -0
- simrun-0.1.0/tests/test_deploy.py +61 -0
- simrun-0.1.0/tests/test_edit.py +464 -0
- simrun-0.1.0/tests/test_environment.py +329 -0
- simrun-0.1.0/tests/test_exec.py +146 -0
- simrun-0.1.0/tests/test_ledger.py +273 -0
- simrun-0.1.0/tests/test_mcp.py +127 -0
- simrun-0.1.0/tests/test_planner.py +196 -0
- simrun-0.1.0/tests/test_plugins.py +69 -0
- simrun-0.1.0/tests/test_ports.py +94 -0
- simrun-0.1.0/tests/test_resources.py +217 -0
- simrun-0.1.0/tests/test_snapshot.py +208 -0
- simrun-0.1.0/tests/test_store.py +53 -0
- simrun-0.1.0/tests/test_worker.py +883 -0
- simrun-0.1.0/tests/test_workflow.py +116 -0
- simrun-0.1.0/tox.ini +19 -0
- simrun-0.1.0/uv.lock +3130 -0
- simrun-0.1.0/zensical.toml +173 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[tool.bumpversion]
|
|
2
|
+
current_version = "0.1.0"
|
|
3
|
+
commit = true
|
|
4
|
+
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
5
|
+
serialize = ["{major}.{minor}.{patch}"]
|
|
6
|
+
search = "{current_version}"
|
|
7
|
+
replace = "{new_version}"
|
|
8
|
+
regex = false
|
|
9
|
+
ignore_missing_version = false
|
|
10
|
+
# no tag: the bump is merged into develop through a pull request, which
|
|
11
|
+
# rewrites the commit, so the tag is created on develop afterwards
|
|
12
|
+
tag = false
|
|
13
|
+
sign_tags = false
|
|
14
|
+
tag_name = "{new_version}"
|
|
15
|
+
tag_message = "Bump version: {current_version} → {new_version}"
|
|
16
|
+
allow_dirty = false
|
|
17
|
+
message = "Bump version: {current_version} → {new_version}"
|
|
18
|
+
commit_args = ""
|
|
19
|
+
|
|
20
|
+
[[tool.bumpversion.files]]
|
|
21
|
+
filename = "./src/simrun/__init__.py"
|
|
22
|
+
|
|
23
|
+
[[tool.bumpversion.files]]
|
|
24
|
+
filename = "./CITATION.cff"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @matthiaskoenig
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Set up the environment
|
|
2
|
+
description: >-
|
|
3
|
+
Install uv with its cache, set the python version of the job and sync the
|
|
4
|
+
environment of the project from uv.lock
|
|
5
|
+
inputs:
|
|
6
|
+
python-version:
|
|
7
|
+
description: the python version, e.g. 3.14
|
|
8
|
+
required: true
|
|
9
|
+
sync:
|
|
10
|
+
description: >-
|
|
11
|
+
the arguments of `uv sync --locked`, e.g. `--extra dev`; empty does not
|
|
12
|
+
sync
|
|
13
|
+
required: false
|
|
14
|
+
default: ""
|
|
15
|
+
save-cache:
|
|
16
|
+
description: >-
|
|
17
|
+
whether the job saves the cache of uv; jobs which share a key would race
|
|
18
|
+
for it and warn "Unable to reserve cache"
|
|
19
|
+
required: false
|
|
20
|
+
default: "false"
|
|
21
|
+
cache:
|
|
22
|
+
description: >-
|
|
23
|
+
whether the job uses the cache of uv at all; the release builds the
|
|
24
|
+
distributions without one, so nothing a cache holds ends up in them
|
|
25
|
+
required: false
|
|
26
|
+
default: "true"
|
|
27
|
+
runs:
|
|
28
|
+
using: composite
|
|
29
|
+
steps:
|
|
30
|
+
- name: Install uv and set the python version
|
|
31
|
+
# astral-sh/setup-uv publishes no floating major tag beyond v7
|
|
32
|
+
uses: astral-sh/setup-uv@v10.2.0
|
|
33
|
+
with:
|
|
34
|
+
python-version: ${{ inputs.python-version }}
|
|
35
|
+
enable-cache: ${{ inputs.cache }}
|
|
36
|
+
# the interpreter is cached with the packages instead of downloaded by every run
|
|
37
|
+
cache-python: ${{ inputs.cache }}
|
|
38
|
+
save-cache: ${{ inputs.save-cache }}
|
|
39
|
+
- name: Sync the environment from the lock (fails if uv.lock is out of date with pyproject.toml, run `uv lock`)
|
|
40
|
+
if: inputs.sync != ''
|
|
41
|
+
shell: bash
|
|
42
|
+
env:
|
|
43
|
+
SYNC: ${{ inputs.sync }}
|
|
44
|
+
# every job runs against the versions of uv.lock, the same ones as a
|
|
45
|
+
# local `uv sync`. `--locked` refuses to update the lock: a change of the
|
|
46
|
+
# dependencies in pyproject.toml has to come with the `uv lock` which
|
|
47
|
+
# records it. Word splitting of the arguments is intended
|
|
48
|
+
run: uv sync --locked $SYNC
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Keep the GitHub Actions used in the workflows and the locked python dependencies up to date,
|
|
2
|
+
# monthly, since every update pull request runs the checks.
|
|
3
|
+
# See https://docs.github.com/code-security/dependabot/dependabot-version-updates
|
|
4
|
+
version: 2
|
|
5
|
+
updates:
|
|
6
|
+
- package-ecosystem: "github-actions"
|
|
7
|
+
directory: "/"
|
|
8
|
+
schedule:
|
|
9
|
+
interval: "monthly"
|
|
10
|
+
# a single pull request for all action updates instead of one per action
|
|
11
|
+
groups:
|
|
12
|
+
github-actions:
|
|
13
|
+
patterns:
|
|
14
|
+
- "*"
|
|
15
|
+
open-pull-requests-limit: 5
|
|
16
|
+
commit-message:
|
|
17
|
+
prefix: "ci"
|
|
18
|
+
|
|
19
|
+
# the locked python dependencies (uv.lock), bumped together
|
|
20
|
+
- package-ecosystem: "uv"
|
|
21
|
+
directory: "/"
|
|
22
|
+
# only uv.lock is updated: the default would raise the lower bounds in
|
|
23
|
+
# pyproject.toml, which are what a user of the library installs against,
|
|
24
|
+
# so they are only ever changed by hand
|
|
25
|
+
versioning-strategy: lockfile-only
|
|
26
|
+
schedule:
|
|
27
|
+
interval: "monthly"
|
|
28
|
+
groups:
|
|
29
|
+
python-dependencies:
|
|
30
|
+
patterns:
|
|
31
|
+
- "*"
|
|
32
|
+
open-pull-requests-limit: 5
|
|
33
|
+
commit-message:
|
|
34
|
+
prefix: "build"
|
|
35
|
+
|
|
36
|
+
# the locked npm dependencies of the web app (frontend/package-lock.json), bumped together
|
|
37
|
+
- package-ecosystem: "npm"
|
|
38
|
+
directory: "/frontend"
|
|
39
|
+
schedule:
|
|
40
|
+
interval: "monthly"
|
|
41
|
+
ignore:
|
|
42
|
+
# vue-tsc and openapi-typescript need the API of the compiler in
|
|
43
|
+
# javascript, which TypeScript 7 (the native port) does not have
|
|
44
|
+
- dependency-name: "typescript"
|
|
45
|
+
update-types: ["version-update:semver-major"]
|
|
46
|
+
# the types of node follow the node of continuous integration (24)
|
|
47
|
+
- dependency-name: "@types/node"
|
|
48
|
+
update-types: ["version-update:semver-major"]
|
|
49
|
+
groups:
|
|
50
|
+
npm-dependencies:
|
|
51
|
+
patterns:
|
|
52
|
+
- "*"
|
|
53
|
+
open-pull-requests-limit: 5
|
|
54
|
+
commit-message:
|
|
55
|
+
prefix: "build"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- what does this change and why -->
|
|
4
|
+
|
|
5
|
+
## Checklist
|
|
6
|
+
|
|
7
|
+
- [ ] the pull request targets `develop`
|
|
8
|
+
- [ ] tests were added or updated for the change
|
|
9
|
+
- [ ] `pytest` and `ty check` pass locally, `tox run-parallel` runs the tests on every supported python
|
|
10
|
+
- [ ] the change to the cluster was tested on k3d (`SIMRUN_K3D=1 pytest -m cluster`) or the pull request has the label `cluster`
|
|
11
|
+
- [ ] `ruff check` and `ruff format` are clean, e.g., via `pre-commit run --all-files`
|
|
12
|
+
- [ ] public functions and classes have type annotations and a docstring
|
|
13
|
+
- [ ] user visible changes are in `release-notes/` and, if needed, in `docs/`
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Apply the repository policies of simrun: the merge settings of the
|
|
4
|
+
# repository and the rulesets in this directory. The script is idempotent, i.e.,
|
|
5
|
+
# a ruleset which already exists is updated instead of added a second time, so
|
|
6
|
+
# it can be run again after every change of the json files.
|
|
7
|
+
#
|
|
8
|
+
# The file name of a ruleset has to match the "name" in the json. A ruleset which
|
|
9
|
+
# is removed from this directory stays on the repository, delete it with
|
|
10
|
+
# `gh api -X DELETE repos/<owner>/<repo>/rulesets/<id>`.
|
|
11
|
+
#
|
|
12
|
+
# Requires the github cli (https://cli.github.com) authenticated as a user with
|
|
13
|
+
# admin permission on the repository:
|
|
14
|
+
#
|
|
15
|
+
# gh auth login
|
|
16
|
+
# .github/rulesets/apply.sh [owner/repo]
|
|
17
|
+
#
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
REPO="${1:-matthiaskoenig/simrun}"
|
|
21
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
|
|
23
|
+
echo "repository settings of ${REPO}"
|
|
24
|
+
gh api -X PATCH "repos/${REPO}" \
|
|
25
|
+
-F allow_auto_merge=true \
|
|
26
|
+
-F delete_branch_on_merge=true \
|
|
27
|
+
-F allow_update_branch=true \
|
|
28
|
+
-F allow_squash_merge=true \
|
|
29
|
+
-F allow_rebase_merge=true \
|
|
30
|
+
-F allow_merge_commit=false \
|
|
31
|
+
--silent
|
|
32
|
+
|
|
33
|
+
for path in "${DIR}"/*.json; do
|
|
34
|
+
name="$(basename "${path}" .json)"
|
|
35
|
+
id="$(gh api "repos/${REPO}/rulesets" --jq "map(select(.name == \"${name}\")) | .[0].id // empty")"
|
|
36
|
+
if [[ -n "${id}" ]]; then
|
|
37
|
+
gh api -X PUT "repos/${REPO}/rulesets/${id}" --input "${path}" --silent
|
|
38
|
+
echo "ruleset ${name} updated (${id})"
|
|
39
|
+
else
|
|
40
|
+
id="$(gh api -X POST "repos/${REPO}/rulesets" --input "${path}" --jq .id)"
|
|
41
|
+
echo "ruleset ${name} created (${id})"
|
|
42
|
+
fi
|
|
43
|
+
done
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "develop",
|
|
3
|
+
"target": "branch",
|
|
4
|
+
"enforcement": "active",
|
|
5
|
+
"bypass_actors": [],
|
|
6
|
+
"conditions": {
|
|
7
|
+
"ref_name": {
|
|
8
|
+
"include": [
|
|
9
|
+
"refs/heads/develop"
|
|
10
|
+
],
|
|
11
|
+
"exclude": []
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"rules": [
|
|
15
|
+
{
|
|
16
|
+
"type": "deletion"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"type": "non_fast_forward"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"type": "required_linear_history"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "pull_request",
|
|
26
|
+
"parameters": {
|
|
27
|
+
"required_approving_review_count": 0,
|
|
28
|
+
"dismiss_stale_reviews_on_push": true,
|
|
29
|
+
"require_code_owner_review": false,
|
|
30
|
+
"require_last_push_approval": false,
|
|
31
|
+
"required_review_thread_resolution": true,
|
|
32
|
+
"allowed_merge_methods": [
|
|
33
|
+
"squash",
|
|
34
|
+
"rebase"
|
|
35
|
+
],
|
|
36
|
+
"require_extra_approval_for_unattributed_changes": false
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"type": "required_status_checks",
|
|
41
|
+
"parameters": {
|
|
42
|
+
"strict_required_status_checks_policy": false,
|
|
43
|
+
"do_not_enforce_on_create": false,
|
|
44
|
+
"required_status_checks": [
|
|
45
|
+
{
|
|
46
|
+
"context": "tests"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"context": "ruff"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"context": "ty"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"context": "docs"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "main",
|
|
3
|
+
"target": "branch",
|
|
4
|
+
"enforcement": "active",
|
|
5
|
+
"bypass_actors": [],
|
|
6
|
+
"conditions": {
|
|
7
|
+
"ref_name": {
|
|
8
|
+
"include": [
|
|
9
|
+
"refs/heads/main"
|
|
10
|
+
],
|
|
11
|
+
"exclude": []
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"rules": [
|
|
15
|
+
{
|
|
16
|
+
"type": "deletion"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"type": "non_fast_forward"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"type": "required_linear_history"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tags",
|
|
3
|
+
"target": "tag",
|
|
4
|
+
"enforcement": "active",
|
|
5
|
+
"bypass_actors": [],
|
|
6
|
+
"conditions": {
|
|
7
|
+
"ref_name": {
|
|
8
|
+
"include": ["~ALL"],
|
|
9
|
+
"exclude": []
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"rules": [
|
|
13
|
+
{"type": "deletion"},
|
|
14
|
+
{"type": "non_fast_forward"}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
name: CI-CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
# feature branches are tested through their pull request, tags release
|
|
6
|
+
branches: [develop, main]
|
|
7
|
+
tags: ['*']
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [develop, main]
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
# least privilege by default, the release job raises what it needs
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
# a newer run supersedes the running one of the same pull request. A push is
|
|
18
|
+
# a group of its own, so it is never superseded: a release waits for the run
|
|
19
|
+
# of its commit on develop (see the job `tested`), and two merges in a row
|
|
20
|
+
# would otherwise leave the first commit untested. A release is never
|
|
21
|
+
# superseded either, every tag is a group of its own
|
|
22
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || format('{0}-{1}', github.ref, github.sha) }}
|
|
23
|
+
cancel-in-progress: true
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
test:
|
|
27
|
+
# a tag is not tested again, see the job `tested`
|
|
28
|
+
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
timeout-minutes: 30
|
|
31
|
+
strategy:
|
|
32
|
+
fail-fast: false
|
|
33
|
+
matrix:
|
|
34
|
+
# simrun runs on linux only (cgroups, k3s); every supported python
|
|
35
|
+
python-version: ["3.14", "3.15"]
|
|
36
|
+
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v7
|
|
39
|
+
with:
|
|
40
|
+
persist-credentials: false
|
|
41
|
+
- name: Set up the environment
|
|
42
|
+
# the dependencies are the versions of uv.lock, the package is installed
|
|
43
|
+
# as a wheel and not editable, so the tests run against what is
|
|
44
|
+
# published. The key of the cache has the os and the python version but
|
|
45
|
+
# not the job, so every entry of the matrix has a key of its own and
|
|
46
|
+
# saves it; the other jobs with python 3.14 (ty, docs, cluster) share the
|
|
47
|
+
# key of the entry 3.14 and only restore it
|
|
48
|
+
uses: ./.github/actions/setup
|
|
49
|
+
with:
|
|
50
|
+
python-version: ${{ matrix.python-version }}
|
|
51
|
+
sync: --extra dev --no-editable
|
|
52
|
+
save-cache: "true"
|
|
53
|
+
- name: Test
|
|
54
|
+
# in parallel on every core (`addopts` of pyproject.toml), without the
|
|
55
|
+
# tests on the cluster (`-m 'not cluster'` of `addopts`, see the job
|
|
56
|
+
# `cluster`); the slowest tests are listed at the end of the log
|
|
57
|
+
run: uv run --no-sync pytest --durations=15
|
|
58
|
+
|
|
59
|
+
install:
|
|
60
|
+
# the package as `pip install simrun` installs it, without extras: the
|
|
61
|
+
# environment of the test matrix has the extras of `dev`, which would hide
|
|
62
|
+
# a dependency the package needs and does not declare. It is the one job
|
|
63
|
+
# which does not use uv.lock: it resolves from pyproject.toml as the
|
|
64
|
+
# install of a user does, i.e. the newest releases within the bounds, so a
|
|
65
|
+
# release of a dependency which breaks simrun shows up here before
|
|
66
|
+
# dependabot moves the lock to it
|
|
67
|
+
name: plain install
|
|
68
|
+
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
timeout-minutes: 15
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v7
|
|
73
|
+
with:
|
|
74
|
+
persist-credentials: false
|
|
75
|
+
- name: Set up uv and python
|
|
76
|
+
uses: ./.github/actions/setup
|
|
77
|
+
with:
|
|
78
|
+
python-version: "3.14"
|
|
79
|
+
- name: Install the package without extras
|
|
80
|
+
run: |
|
|
81
|
+
uv venv "$RUNNER_TEMP/plain"
|
|
82
|
+
uv pip install --python "$RUNNER_TEMP/plain/bin/python" .
|
|
83
|
+
- name: Import every module and run the command line
|
|
84
|
+
# isolated (-I) and outside of the repository, so the package is the
|
|
85
|
+
# installed one and not the sources. Every module but `simrun.cwl`, whose
|
|
86
|
+
# export needs the extra `cwl`, imports at the top what it needs
|
|
87
|
+
working-directory: ${{ runner.temp }}
|
|
88
|
+
run: |
|
|
89
|
+
"$RUNNER_TEMP/plain/bin/python" -I -c '
|
|
90
|
+
import importlib, pkgutil, simrun
|
|
91
|
+
names = [m.name for m in pkgutil.walk_packages(simrun.__path__, "simrun.")]
|
|
92
|
+
for name in names:
|
|
93
|
+
importlib.import_module(name)
|
|
94
|
+
print(f"simrun {simrun.__version__}: {len(names)} modules imported")
|
|
95
|
+
'
|
|
96
|
+
"$RUNNER_TEMP/plain/bin/simrun" --help
|
|
97
|
+
"$RUNNER_TEMP/plain/bin/simrun" submit --help
|
|
98
|
+
|
|
99
|
+
frontend:
|
|
100
|
+
# the web app in frontend/: the versions of package-lock.json, the types,
|
|
101
|
+
# the tests and the build the service serves at /ui/
|
|
102
|
+
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
103
|
+
runs-on: ubuntu-latest
|
|
104
|
+
timeout-minutes: 15
|
|
105
|
+
defaults:
|
|
106
|
+
run:
|
|
107
|
+
working-directory: frontend
|
|
108
|
+
steps:
|
|
109
|
+
- uses: actions/checkout@v7
|
|
110
|
+
with:
|
|
111
|
+
persist-credentials: false
|
|
112
|
+
- name: Set up node
|
|
113
|
+
uses: actions/setup-node@v7
|
|
114
|
+
with:
|
|
115
|
+
node-version: 24
|
|
116
|
+
cache: npm
|
|
117
|
+
cache-dependency-path: frontend/package-lock.json
|
|
118
|
+
- name: Install the dependencies
|
|
119
|
+
run: npm ci
|
|
120
|
+
- name: Check the types
|
|
121
|
+
run: npm run typecheck
|
|
122
|
+
- name: Test
|
|
123
|
+
run: npm test
|
|
124
|
+
- name: Build
|
|
125
|
+
run: npm run build
|
|
126
|
+
- name: Check that the types of the API are those of openapi.json
|
|
127
|
+
# src/api/schema.d.ts is generated from src/api/openapi.json, which a
|
|
128
|
+
# test of the service keeps equal to the API; after a change of the API
|
|
129
|
+
# run `uv run python scripts/openapi.py`, then `npm run types`
|
|
130
|
+
run: |
|
|
131
|
+
npm run types
|
|
132
|
+
git diff --exit-code -- src/api/schema.d.ts
|
|
133
|
+
|
|
134
|
+
tests:
|
|
135
|
+
# the one check the branch protection requires; the names of the matrix
|
|
136
|
+
# jobs change with the matrix, this name does not, see .github/rulesets/
|
|
137
|
+
name: tests
|
|
138
|
+
needs: [test, install, frontend]
|
|
139
|
+
if: ${{ always() && !startsWith(github.ref, 'refs/tags/') }}
|
|
140
|
+
runs-on: ubuntu-latest
|
|
141
|
+
timeout-minutes: 5
|
|
142
|
+
steps:
|
|
143
|
+
- name: Check the results of the test matrix, of the plain install and of the web app
|
|
144
|
+
env:
|
|
145
|
+
RESULT: ${{ needs.test.result }}
|
|
146
|
+
INSTALL: ${{ needs.install.result }}
|
|
147
|
+
FRONTEND: ${{ needs.frontend.result }}
|
|
148
|
+
run: |
|
|
149
|
+
echo "test matrix: $RESULT, plain install: $INSTALL, web app: $FRONTEND"
|
|
150
|
+
test "$RESULT" = "success" && test "$INSTALL" = "success" && test "$FRONTEND" = "success"
|
|
151
|
+
|
|
152
|
+
cluster:
|
|
153
|
+
# the tests on a k3d cluster with Kueue, Argo Workflows and BuildKit, on a
|
|
154
|
+
# push to develop, on a release and when the workflow is started by hand.
|
|
155
|
+
# A pull request runs them with the label `cluster`, see cluster.yml
|
|
156
|
+
if: github.event_name != 'pull_request'
|
|
157
|
+
uses: ./.github/workflows/cluster.yml
|
|
158
|
+
|
|
159
|
+
tested:
|
|
160
|
+
# a release does not run the test matrix again. The tag is on a commit of
|
|
161
|
+
# develop, and the push of that commit ran the matrix on exactly this
|
|
162
|
+
# tree; the job waits for that run and fails unless it succeeded, so the
|
|
163
|
+
# tag can be pushed right after the merge of the release
|
|
164
|
+
name: tested on develop
|
|
165
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
166
|
+
runs-on: ubuntu-latest
|
|
167
|
+
timeout-minutes: 90
|
|
168
|
+
permissions:
|
|
169
|
+
actions: read # the runs of this workflow
|
|
170
|
+
contents: read
|
|
171
|
+
steps:
|
|
172
|
+
- uses: actions/checkout@v7
|
|
173
|
+
with:
|
|
174
|
+
fetch-depth: 0
|
|
175
|
+
persist-credentials: false
|
|
176
|
+
- name: Check that the tag is on develop
|
|
177
|
+
run: |
|
|
178
|
+
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/develop; then
|
|
179
|
+
echo "::error::$GITHUB_REF_NAME is not on develop, a release is tagged on develop"
|
|
180
|
+
exit 1
|
|
181
|
+
fi
|
|
182
|
+
- name: Wait for the run of the commit on develop
|
|
183
|
+
env:
|
|
184
|
+
GH_TOKEN: ${{ github.token }}
|
|
185
|
+
run: |
|
|
186
|
+
api="repos/$GITHUB_REPOSITORY/actions"
|
|
187
|
+
# the run starts with the merge, a tag pushed right after it may be first
|
|
188
|
+
run_id=""
|
|
189
|
+
for attempt in $(seq 1 20); do
|
|
190
|
+
run_id=$(gh api "$api/workflows/ci-cd.yml/runs?branch=develop&event=push&head_sha=$GITHUB_SHA" \
|
|
191
|
+
--jq '.workflow_runs[0].id // empty' || true)
|
|
192
|
+
[ -n "$run_id" ] && break
|
|
193
|
+
sleep 15
|
|
194
|
+
done
|
|
195
|
+
if [ -z "$run_id" ]; then
|
|
196
|
+
echo "::error::no CI-CD run of the push of $GITHUB_SHA to develop"
|
|
197
|
+
exit 1
|
|
198
|
+
fi
|
|
199
|
+
url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$run_id"
|
|
200
|
+
echo "waiting for $url"
|
|
201
|
+
# a failed request answers nothing, which is not `completed` either
|
|
202
|
+
until [ "$(gh api "$api/runs/$run_id" --jq .status || true)" = "completed" ]; do
|
|
203
|
+
sleep 30
|
|
204
|
+
done
|
|
205
|
+
conclusion=$(gh api "$api/runs/$run_id" --jq .conclusion)
|
|
206
|
+
echo "$url: $conclusion"
|
|
207
|
+
if [ "$conclusion" != "success" ]; then
|
|
208
|
+
echo "::error::the tests of $GITHUB_SHA on develop did not pass ($url); once they do, re-run the failed jobs of this release"
|
|
209
|
+
exit 1
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
release:
|
|
213
|
+
needs: [tested, cluster]
|
|
214
|
+
if: >-
|
|
215
|
+
${{ !cancelled() && startsWith(github.ref, 'refs/tags/')
|
|
216
|
+
&& needs.tested.result == 'success'
|
|
217
|
+
&& needs.cluster.result == 'success' }}
|
|
218
|
+
runs-on: ubuntu-latest
|
|
219
|
+
timeout-minutes: 15
|
|
220
|
+
environment:
|
|
221
|
+
name: pypi
|
|
222
|
+
url: https://pypi.org/p/simrun
|
|
223
|
+
permissions:
|
|
224
|
+
id-token: write # trusted publishing to PyPI
|
|
225
|
+
contents: write # create the GitHub release
|
|
226
|
+
steps:
|
|
227
|
+
- uses: actions/checkout@v7
|
|
228
|
+
with:
|
|
229
|
+
persist-credentials: false
|
|
230
|
+
- name: Set up uv
|
|
231
|
+
uses: ./.github/actions/setup
|
|
232
|
+
with:
|
|
233
|
+
python-version: "3.14"
|
|
234
|
+
cache: "false"
|
|
235
|
+
- name: Check that the tag is the version of the package
|
|
236
|
+
run: |
|
|
237
|
+
version=$(sed -n 's/^__version__ = "\(.*\)"$/\1/p' src/simrun/__init__.py)
|
|
238
|
+
if [ "$version" != "$GITHUB_REF_NAME" ]; then
|
|
239
|
+
echo "::error::the tag $GITHUB_REF_NAME is not the version $version of src/simrun/__init__.py"
|
|
240
|
+
exit 1
|
|
241
|
+
fi
|
|
242
|
+
- name: Build package
|
|
243
|
+
# the sdist and the wheel
|
|
244
|
+
run: uvx hatch build
|
|
245
|
+
- name: Check the package
|
|
246
|
+
run: uvx twine check --strict dist/*
|
|
247
|
+
- name: Publish to PyPI
|
|
248
|
+
# trusted publishing: the environment `pypi` of this repository is the
|
|
249
|
+
# publisher of the project on pypi.org, no token
|
|
250
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
251
|
+
with:
|
|
252
|
+
packages-dir: dist
|
|
253
|
+
- name: Create GitHub release
|
|
254
|
+
# the release triggers the archive on Zenodo
|
|
255
|
+
uses: softprops/action-gh-release@v3
|
|
256
|
+
with:
|
|
257
|
+
body_path: "release-notes/${{ github.ref_name }}.md"
|
|
258
|
+
files: dist/*
|
|
259
|
+
draft: false
|
|
260
|
+
prerelease: false
|
|
261
|
+
|
|
262
|
+
sync-main:
|
|
263
|
+
# main tracks the latest published release, see docs/development.md
|
|
264
|
+
needs: release
|
|
265
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
266
|
+
runs-on: ubuntu-latest
|
|
267
|
+
timeout-minutes: 5
|
|
268
|
+
permissions:
|
|
269
|
+
contents: write # fast-forward main to the released commit
|
|
270
|
+
steps:
|
|
271
|
+
- uses: actions/checkout@v7
|
|
272
|
+
with:
|
|
273
|
+
# a shallow clone cannot be pushed to another branch
|
|
274
|
+
fetch-depth: 0
|
|
275
|
+
- name: Fast-forward main to the release
|
|
276
|
+
# no --force: the push fails loudly if it would not be a fast-forward
|
|
277
|
+
run: git push origin HEAD:main
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: cluster
|
|
2
|
+
|
|
3
|
+
# The tests on a k3d cluster (`tests/cluster`): k3s with Kueue, Argo Workflows,
|
|
4
|
+
# BuildKit and a registry in docker, the service in the process of the tests.
|
|
5
|
+
# They take half an hour and are not part of the required checks: the job
|
|
6
|
+
# `cluster` of CI-CD calls this workflow on a push to develop, on a release,
|
|
7
|
+
# which waits for it, and when CI-CD is started by hand; a pull request runs it
|
|
8
|
+
# when it has the label `cluster`, once the label is added and with every push
|
|
9
|
+
# after it.
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
workflow_call:
|
|
13
|
+
pull_request:
|
|
14
|
+
branches: [develop, main]
|
|
15
|
+
types: [opened, synchronize, reopened, labeled]
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
cluster:
|
|
22
|
+
name: cluster
|
|
23
|
+
# a pull request without the label skips the job; adding another label to
|
|
24
|
+
# a pull request with the label does not run it again
|
|
25
|
+
if: >-
|
|
26
|
+
${{ github.event_name != 'pull_request'
|
|
27
|
+
|| (github.event.action == 'labeled' && github.event.label.name == 'cluster')
|
|
28
|
+
|| (github.event.action != 'labeled' && contains(github.event.pull_request.labels.*.name, 'cluster')) }}
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
timeout-minutes: 75
|
|
31
|
+
concurrency:
|
|
32
|
+
# a newer push to a pull request supersedes its running cluster tests;
|
|
33
|
+
# a push to develop and a release are groups of their own
|
|
34
|
+
group: cluster-${{ github.event.pull_request.number || github.run_id }}
|
|
35
|
+
cancel-in-progress: true
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v7
|
|
38
|
+
with:
|
|
39
|
+
persist-credentials: false
|
|
40
|
+
- name: Free the disk for the images
|
|
41
|
+
# the tests need about 20 GiB for the images of k3s, Kueue, Argo,
|
|
42
|
+
# BuildKit, the runs and the environments (`MIN_FREE_GB` of
|
|
43
|
+
# tests/cluster/k3d_cluster.py); the toolchains of the runner image
|
|
44
|
+
# which the tests do not use take more than that
|
|
45
|
+
run: |
|
|
46
|
+
df -h /
|
|
47
|
+
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /usr/local/.ghcup \
|
|
48
|
+
/opt/hostedtoolcache/CodeQL /usr/local/share/boost /usr/share/swift
|
|
49
|
+
docker system prune --all --force
|
|
50
|
+
df -h /
|
|
51
|
+
- name: Set up the environment
|
|
52
|
+
uses: ./.github/actions/setup
|
|
53
|
+
with:
|
|
54
|
+
python-version: "3.14"
|
|
55
|
+
sync: --extra dev
|
|
56
|
+
- name: Set up node
|
|
57
|
+
# the image of the service has the web app, built in frontend/
|
|
58
|
+
# (`build_service_image` of tests/cluster/k3d_cluster.py)
|
|
59
|
+
uses: actions/setup-node@v7
|
|
60
|
+
with:
|
|
61
|
+
node-version: 24
|
|
62
|
+
cache: npm
|
|
63
|
+
cache-dependency-path: frontend/package-lock.json
|
|
64
|
+
- name: Test on the k3d cluster
|
|
65
|
+
# the session downloads k3d and kubectl into .tools/bin and creates the
|
|
66
|
+
# cluster; the cluster is kept (`SIMRUN_K3D_KEEP=1`), the runner is
|
|
67
|
+
# thrown away, so the next step can describe it after a failure
|
|
68
|
+
env:
|
|
69
|
+
SIMRUN_K3D: "1"
|
|
70
|
+
SIMRUN_K3D_KEEP: "1"
|
|
71
|
+
run: uv run --no-sync pytest -m cluster tests/cluster --durations=0
|
|
72
|
+
- name: Describe the cluster after a failure
|
|
73
|
+
if: failure()
|
|
74
|
+
env:
|
|
75
|
+
KUBECONFIG: .tools/kubeconfig
|
|
76
|
+
run: |
|
|
77
|
+
kubectl=.tools/bin/kubectl
|
|
78
|
+
$kubectl get nodes -o wide || true
|
|
79
|
+
$kubectl get pods --all-namespaces -o wide || true
|
|
80
|
+
$kubectl get workflows,workloads --namespace simrun || true
|
|
81
|
+
$kubectl get events --all-namespaces --sort-by=.lastTimestamp | tail -n 200 || true
|
|
82
|
+
df -h / || true
|