Template repository for creating new SARA Python services.
Click Use this template on GitHub (or use gh repo create <name> --template equinor/sara-python-template) to bootstrap a new repo, then:
- Work through the Bootstrap checklist below to rename the package and register the service.
- Work through
equinor/armada/docs/new_repo_checklist.mdto configure repository settings, branch rulesets, environments, and secrets — GitHub templates only copy files, not repo configuration.
After creating a new repo from this template, replace the placeholders and configure the repo:
Replace every occurrence of sara-service (kebab-case, project name) and sara_service (snake_case, package name) with your service names.
NEW_KEBAB=sara-your-service
NEW_SNAKE=sara_your_service
# Rename the package directory
git mv sara_service "$NEW_SNAKE"
# Update string references in tracked files
git grep -l sara-service | xargs sed -i "s/sara-service/$NEW_KEBAB/g"
git grep -l sara_service | xargs sed -i "s/sara_service/$NEW_SNAKE/g"Then edit:
pyproject.toml—[project].name,[project].description,[project.urls].repository,[tool.setuptools.packages.find].include,[tool.isort].known_first_party.catalog-info.yaml—metadata.name,github.com/project-slug..github/workflows/deploy_to_development.yml,deploy_to_staging.yml,promote_to_production.yml—image_namevalues.
The default runs_on is ubuntu-latest (GitHub-hosted, ~14 GB disk). If your image includes torch/ML weights and exceeds that, set runs_on: ubuntu in deploy_to_development.yml and deploy_to_staging.yml to use Equinor's self-hosted runner. See sara-anonymizer for reference.
Create Development, Staging and Production under Settings → Environments. These are required, not optional: the federated credential that authenticates to the registry matches on the environment name, so a missing or differently-cased environment means the deploy cannot authenticate at all.
Add required reviewers on any of them you want to gate.
Publishing uses a federated credential, not a registry password. There is nothing secret to request.
- Add this repository to
automation/aks/gha-push-<env>.bicepparaminequinor/robotics-infrastructurefor each environment you publish to, and deploygha-push-identity.bicepfor that environment. - Set
ACR_PUSH_CLIENT_IDas an environment variable on each GitHub Environment, to the client ID ofrobotics-gha-push-<env>.
AZURE_TENANT_ID and AZURE_SUBSCRIPTION_ID are inherited from the organisation.
The only secret the workflows need is:
ANALYTICS_INFRASTRUCTURE_DEPLOY_KEY
If a deploy fails at azure/login, the usual causes are a missing id-token: write on some job in the call chain (a called workflow's token can never exceed its caller's), or an Actions allowlist that does not permit azure/login@* — the latter shows as startup_failure at 0s with no jobs, which looks like a syntax error but is not.
See equinor/armada/docs/new_repo_checklist.md for the full list of repository settings, branch rulesets, environments, and secrets used across sara-* repos.
Add a new overlay entry in equinor/robotics-infrastructure under k8s_kustomize/robotics/overlays/{development,staging,production}/kustomization.yaml pointing at robotics/sara-your-service.
The template includes a starter lockfile. After renaming the package and picking your initial dependencies in pyproject.toml, refresh and commit it:
uv lock
git add uv.lockKeep uv.lock committed: Docker builds use it with uv sync --frozen, and Dependabot maintains it alongside pyproject.toml.
Remove the bootstrap checklist from the README once the repo is set up.
Short description of what the service does.
uv sync
uv run python main.py --help
uv run pytestDeployment is fully handled by the workflows in .github/workflows/, which delegate to the reusable workflows in equinor/armada. See equinor/armada/.github/workflows/deploy_to_development.yml for the pipeline.
Dependabot is configured in .github/dependabot.yml for weekly Monday updates to Python dependencies (uv) and Docker images. Python patch and minor updates are bundled in python-patch-minor; major updates are bundled separately in python-major for explicit review, not one PR per dependency. Python version-update PRs are limited to five open PRs and use Dependabot's default three-day cooldown without an explicit cooldown setting.
Every uv entry uses allow: [{dependency-type: all}] so routine version updates include both direct and transitive dependencies, preserving the transitive coverage of uv lock --upgrade. If a service adds independent nested uv projects with their own pyproject.toml and uv.lock, copy the root uv entry for each project and set directory to its repository-relative path (for example, /tools/example). Retain the allow rule, schedule, groups, PR limit, and cooldown behavior in each entry.
Docker updates are grouped in docker-images; Python base-image major upgrades are ignored and must be handled manually. New services inherit Dependabot as their dependency-update system.