Public Access
89 lines
3.0 KiB
Python
89 lines
3.0 KiB
Python
"""Emit bounded runner-resource lease env for CI molecule jobs.
|
|
|
|
Producer side of the S08 lease contract (consumer: GRM-173
|
|
``runner-cleanup.sh``). The runner's scoped cleanup honors
|
|
``org.oblachno.lease-until`` (epoch seconds) and ``org.oblachno.owner``
|
|
labels on containers, volumes, and networks. Molecule runs on the runner
|
|
host's rootless Docker socket, so objects it creates must carry the lease
|
|
labels at creation time — Docker labels cannot be added post-hoc.
|
|
|
|
This module computes ``MOLECULE_LEASE_UNTIL`` and ``MOLECULE_OWNER``,
|
|
which ``molecule.yml`` platform ``labels:`` entries consume via
|
|
``${MOLECULE_LEASE_UNTIL:-0}`` / ``${MOLECULE_OWNER:-molecule-local}``
|
|
interpolation, and appends them to ``$GITHUB_ENV`` so every later CI step
|
|
inherits them. A lease-until of ``0`` (the interpolation default for
|
|
local runs) is already expired, keeping today's unleased behavior.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import socket
|
|
import time
|
|
|
|
import click
|
|
|
|
#: Docker label contract consumed by runner-cleanup.sh (GRM-173).
|
|
LEASE_UNTIL_LABEL = "org.oblachno.lease-until"
|
|
OWNER_LABEL = "org.oblachno.owner"
|
|
|
|
#: Env vars consumed by molecule.yml platform ``labels:`` entries.
|
|
LEASE_UNTIL_ENV = "MOLECULE_LEASE_UNTIL"
|
|
OWNER_ENV = "MOLECULE_OWNER"
|
|
|
|
#: Default lease duration — covers the longest molecule job window.
|
|
DEFAULT_TTL_SECONDS = 4 * 3600
|
|
|
|
|
|
def lease_owner() -> str:
|
|
"""Identify the owning CI run for the ``org.oblachno.owner`` label.
|
|
|
|
act_runner exposes GitHub-compatible ``GITHUB_*`` env vars;
|
|
``GITEA_*`` names are checked first for forward compatibility.
|
|
"""
|
|
run_id = os.environ.get("GITEA_RUN_ID") or os.environ.get("GITHUB_RUN_ID")
|
|
job = os.environ.get("GITEA_JOB") or os.environ.get("GITHUB_JOB")
|
|
if run_id:
|
|
return f"run-{run_id}-{job or 'job'}"
|
|
return f"local-{socket.gethostname()}"
|
|
|
|
|
|
def lease_env(ttl: int = DEFAULT_TTL_SECONDS, now: int | None = None) -> dict[str, str]:
|
|
"""Return the lease env dict for the current run."""
|
|
base = int(time.time()) if now is None else now
|
|
return {
|
|
LEASE_UNTIL_ENV: str(base + ttl),
|
|
OWNER_ENV: lease_owner(),
|
|
}
|
|
|
|
|
|
def emit_github_env(env: dict[str, str]) -> int:
|
|
"""Append lease env to ``$GITHUB_ENV``; return lines written (0 if unset)."""
|
|
github_env = os.environ.get("GITHUB_ENV")
|
|
if not github_env:
|
|
return 0
|
|
with open(github_env, "a", encoding="utf-8") as f:
|
|
for key, value in env.items():
|
|
f.write(f"{key}={value}\n")
|
|
return len(env)
|
|
|
|
|
|
@click.command()
|
|
@click.option(
|
|
"--ttl",
|
|
default=DEFAULT_TTL_SECONDS,
|
|
type=int,
|
|
help=f"Lease duration in seconds (default: {DEFAULT_TTL_SECONDS}).",
|
|
)
|
|
def main(ttl: int) -> None:
|
|
"""Print lease env vars and export them to $GITHUB_ENV when set."""
|
|
env = lease_env(ttl)
|
|
for key, value in env.items():
|
|
click.echo(f"{key}={value}")
|
|
if emit_github_env(env):
|
|
click.echo(f"Exported {len(env)} lease vars to GITHUB_ENV")
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
main()
|