5 Commits
Author SHA1 Message Date
zemion d4bbdd079f Release v0.1.18
Module Package Release / publish-packages (push) Successful in 13s
2026-08-05 21:07:45 +02:00
zemion ec3ebd2d3d Release v0.1.17
Module Package Release / publish-packages (push) Successful in 12s
2026-08-05 20:34:03 +02:00
zemion 619af7ecb0 Release v0.1.16
Module Package Release / publish-packages (push) Successful in 12s
2026-08-05 19:52:10 +02:00
zemion e6ca2fbd8b Release v0.1.15
Module Package Release / publish-packages (push) Successful in 11s
2026-08-04 15:10:19 +02:00
zemion 3ba0e5ce40 Make package publication retries hash-safe 2026-08-04 14:32:19 +02:00
5 changed files with 91 additions and 13 deletions
+79 -1
View File
@@ -163,6 +163,78 @@ jobs:
with: with:
name: module-packages-${{ gitea.ref_name }} name: module-packages-${{ gitea.ref_name }}
path: dist/package-artifacts.json path: dist/package-artifacts.json
- name: Check immutable registry state
shell: bash
env:
PACKAGE_TOKEN: ${{ secrets.GOVOPLAN_PACKAGE_TOKEN }}
run: |
set -euo pipefail
test -n "$PACKAGE_TOKEN"
python - <<'PY'
import hashlib
import json
import os
from pathlib import Path
import tomllib
from urllib.error import HTTPError
from urllib.parse import quote
from urllib.request import Request, urlopen
api_root = "https://git.add-ideas.de/api/v1/packages/GovOPlaN"
token = os.environ["PACKAGE_TOKEN"]
def should_publish(kind, name, version, path):
package_url = "/".join(
(api_root, kind, quote(name, safe=""), quote(version, safe=""), "files")
)
request = Request(
package_url,
headers={"Accept": "application/json", "Authorization": f"token {token}"},
)
try:
with urlopen(request, timeout=30) as response:
files = json.load(response)
except HTTPError as exc:
if exc.code == 404:
print(f"{kind} package {name}=={version} is not published yet")
return True
raise
if not isinstance(files, list) or len(files) != 1:
raise SystemExit(
f"immutable {kind} package {name}=={version} has an unexpected file set"
)
expected_sha256 = hashlib.sha256(path.read_bytes()).hexdigest()
if files[0].get("sha256") != expected_sha256:
raise SystemExit(
f"immutable {kind} package {name}=={version} already exists with a different SHA-256"
)
print(f"verified existing {kind} package {name}=={version} ({expected_sha256})")
return False
project = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))["project"]
wheels = tuple(Path("dist").glob("*.whl"))
if len(wheels) != 1:
raise SystemExit("release build must contain exactly one wheel")
publish_pypi = should_publish(
"pypi", str(project["name"]), str(project["version"]), wheels[0]
)
tarballs = tuple(Path("dist").glob("*.tgz"))
if len(tarballs) > 1:
raise SystemExit("release build must contain at most one npm package")
publish_npm = False
if tarballs:
webui = json.loads(
Path(".package-webui/package.json").read_text(encoding="utf-8")
)
publish_npm = should_publish(
"npm", str(webui["name"]), str(webui["version"]), tarballs[0]
)
with Path(os.environ["GITEA_ENV"]).open("a", encoding="utf-8") as env_file:
env_file.write(f"PUBLISH_PYPI={int(publish_pypi)}\n")
env_file.write(f"PUBLISH_NPM={int(publish_npm)}\n")
PY
- name: Publish wheel and WebUI package - name: Publish wheel and WebUI package
shell: bash shell: bash
env: env:
@@ -172,13 +244,17 @@ jobs:
set -euo pipefail set -euo pipefail
test -n "$PACKAGE_USERNAME" test -n "$PACKAGE_USERNAME"
test -n "$PACKAGE_TOKEN" test -n "$PACKAGE_TOKEN"
if [[ "$PUBLISH_PYPI" == 1 ]]; then
TWINE_USERNAME="$PACKAGE_USERNAME" TWINE_PASSWORD="$PACKAGE_TOKEN" \ TWINE_USERNAME="$PACKAGE_USERNAME" TWINE_PASSWORD="$PACKAGE_TOKEN" \
python -m twine upload --non-interactive \ python -m twine upload --non-interactive \
--repository-url https://git.add-ideas.de/api/packages/GovOPlaN/pypi \ --repository-url https://git.add-ideas.de/api/packages/GovOPlaN/pypi \
dist/*.whl dist/*.whl
else
echo "Exact wheel is already present; skipping immutable retry."
fi
shopt -s nullglob shopt -s nullglob
webui_packages=(dist/*.tgz) webui_packages=(dist/*.tgz)
if (( ${#webui_packages[@]} )); then if (( ${#webui_packages[@]} )) && [[ "$PUBLISH_NPM" == 1 ]]; then
npmrc="$(mktemp)" npmrc="$(mktemp)"
trap 'rm -f "$npmrc"' EXIT trap 'rm -f "$npmrc"' EXIT
chmod 600 "$npmrc" chmod 600 "$npmrc"
@@ -189,4 +265,6 @@ jobs:
NPM_CONFIG_USERCONFIG="$npmrc" npm publish "./${webui_packages[0]}" \ NPM_CONFIG_USERCONFIG="$npmrc" npm publish "./${webui_packages[0]}" \
--ignore-scripts --access public \ --ignore-scripts --access public \
--registry https://git.add-ideas.de/api/packages/GovOPlaN/npm/ --registry https://git.add-ideas.de/api/packages/GovOPlaN/npm/
elif (( ${#webui_packages[@]} )); then
echo "Exact WebUI package is already present; skipping immutable retry."
fi fi
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@govoplan/forms-runtime", "name": "@govoplan/forms-runtime",
"version": "0.1.14", "version": "0.1.18",
"private": true, "private": true,
"description": "Definition-aware form submissions and service launch for GovOPlaN.", "description": "Definition-aware form submissions and service launch for GovOPlaN.",
"type": "module", "type": "module",
+4 -4
View File
@@ -4,16 +4,16 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "govoplan-forms-runtime" name = "govoplan-forms-runtime"
version = "0.1.14" version = "0.1.18"
description = "Definition-aware form submissions and service launch for GovOPlaN." description = "Definition-aware form submissions and service launch for GovOPlaN."
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
license = { file = "LICENSE" } license = { file = "LICENSE" }
authors = [{ name = "GovOPlaN" }] authors = [{ name = "GovOPlaN" }]
dependencies = [ dependencies = [
"govoplan-core>=0.1.14", "govoplan-core>=0.1.18",
"govoplan-access>=0.1.8", "govoplan-access>=0.1.18",
"govoplan-forms>=0.1.14", "govoplan-forms>=0.1.18",
] ]
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
@@ -44,7 +44,7 @@ from govoplan_forms_runtime.backend.service import (
MODULE_ID = "forms_runtime" MODULE_ID = "forms_runtime"
MODULE_NAME = "Forms Runtime" MODULE_NAME = "Forms Runtime"
MODULE_VERSION = "0.1.14" MODULE_VERSION = "0.1.18"
PARTICIPATE_SCOPE = "forms_runtime:submission:participate" PARTICIPATE_SCOPE = "forms_runtime:submission:participate"
READ_SCOPE = "forms_runtime:workspace:read" READ_SCOPE = "forms_runtime:workspace:read"
WRITE_SCOPE = "forms_runtime:workspace:write" WRITE_SCOPE = "forms_runtime:workspace:write"
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@govoplan/forms-runtime-webui", "name": "@govoplan/forms-runtime-webui",
"version": "0.1.14", "version": "0.1.18",
"private": true, "private": true,
"type": "module", "type": "module",
"main": "src/index.ts", "main": "src/index.ts",
@@ -14,7 +14,7 @@
"./styles/forms-runtime.css": "./src/styles/forms-runtime.css" "./styles/forms-runtime.css": "./src/styles/forms-runtime.css"
}, },
"peerDependencies": { "peerDependencies": {
"@govoplan/core-webui": "^0.1.14", "@govoplan/core-webui": "^0.1.18",
"lucide-react": "^1.23.0", "lucide-react": "^1.23.0",
"react": ">=19.2.7 <20", "react": ">=19.2.7 <20",
"react-dom": ">=19.2.7 <20", "react-dom": ">=19.2.7 <20",