Skip to content
Open
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
8 changes: 8 additions & 0 deletions bootstrap/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,11 @@
# Python

PYTHON_VERSION_DEFAULT = "3.14"

# uv

UV_VERSION = "0.12.10"

# CI

TEST_RUNNER_TAG_DEFAULT = "saas-linux-small-amd64"
8 changes: 8 additions & 0 deletions bootstrap/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
STAGE_ENV_NAME,
STAGE_ENV_SLUG,
TERRAFORM_BACKEND_TFC,
TEST_RUNNER_TAG_DEFAULT,
UV_VERSION,
)
from bootstrap.exceptions import BootstrapError
from bootstrap.helpers import format_gitlab_variable, format_tfvar
Expand Down Expand Up @@ -76,6 +78,8 @@ class Runner:
gitlab_namespace_path: str | None = None
gitlab_token: str | None = None
python_version: str = PYTHON_VERSION_DEFAULT
uv_version: str = UV_VERSION
test_runner_tag: str = TEST_RUNNER_TAG_DEFAULT
minos_service_image: str = MINOS_SERVICE_IMAGE
opentofu_component_version: str = OPENTOFU_COMPONENT_VERSION
opentofu_version: str = OPENTOFU_VERSION
Expand Down Expand Up @@ -146,6 +150,9 @@ def register_gitlab_project_variables(self, *args):

def collect_gitlab_variables(self):
"""Collect the GitLab group and project variables."""
self.register_gitlab_project_variables(
("TEST_RUNNER_TAG", self.test_runner_tag, False, False)
)
if self.sentry_dsn:
self.register_gitlab_project_variables(
("SENTRY_ORG", self.sentry_org),
Expand Down Expand Up @@ -243,6 +250,7 @@ def init_service(self):
),
"use_valkey": self.use_valkey and "true" or "false",
"use_vault": self.vault_url and "true" or "false",
"uv_version": self.uv_version,
},
output_dir=self.output_dir,
no_input=True,
Expand Down
1 change: 1 addition & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"postgres_create_database": "true",
"use_vault": "false",
"python_version": "3.14",
"uv_version": "0.12.10",
"minos_service_image": "registry.gitlab.com/20tab-open/minos/service:latest",
"opentofu_component_version": "3.11.0",
"opentofu_version": "1.10.6",
Expand Down
9 changes: 9 additions & 0 deletions tofu/gitlab/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ resource "gitlab_project" "main" {
namespace_id = data.gitlab_group.main.id
initialize_with_readme = false
shared_runners_enabled = true

container_expiration_policy {
enabled = true
cadence = "1d"
keep_n = 10
older_than = "7d"
name_regex_delete = ".*"
name_regex_keep = "^v.*"
}
}

resource "null_resource" "init_repo" {
Expand Down
81 changes: 71 additions & 10 deletions {{cookiecutter.project_dirname}}/.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,27 @@
opentofu_version: {{ cookiecutter.opentofu_version }}
no_plan: true

workflow:
rules:
- if: $CI_COMMIT_BRANCH == "develop"
variables:
IMAGE_REPO: development
IMAGE_REF: ${CI_COMMIT_SHA}
- if: $CI_COMMIT_BRANCH == "main"
variables:
IMAGE_REPO: staging
IMAGE_REF: ${CI_COMMIT_SHA}
- if: $CI_COMMIT_TAG
variables:
IMAGE_REPO: production
IMAGE_REF: v${CI_COMMIT_TAG}
- when: always
variables:
IMAGE_REPO: feature
IMAGE_REF: ${CI_COMMIT_SHA}

stages:
- Check
- Build
- Test
- Pact-verify
Expand All @@ -17,7 +37,7 @@ stages:
- Sentry

variables:
IMAGE_TAG: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}
IMAGE_TAG: ${CI_REGISTRY_IMAGE}/${IMAGE_REPO}:${IMAGE_REF}
BUILDAH_FORMAT: docker
BUILDAH_IMAGE: quay.io/buildah/stable:latest
BUILDAH_ISOLATION: chroot
Expand All @@ -26,6 +46,7 @@ variables:
DOCKER_BUILDKIT: 1
PROJECT_SLUG: {{ cookiecutter.project_slug }}
SERVICE_SLUG: {{ cookiecutter.service_slug }}
TEST_RUNNER_TAG: saas-linux-small-amd64
VERSION_BEFORE_REF: ${CI_COMMIT_BEFORE_SHA}
VAULT_ROLE: service-gitlab-job

Expand Down Expand Up @@ -124,22 +145,61 @@ sentry_release_production:
- <<: *sentry-rule
- *production-rules

# [Check]
# -----------------------------------------------------------------------------

.check:
stage: Check
image: ghcr.io/astral-sh/uv:{{ cookiecutter.uv_version }}-python{{ cookiecutter.python_version }}-trixie-slim
before_script:
- uv sync --frozen --only-group test --no-install-project
rules:
- if: $CI_PIPELINE_SOURCE == "push"

lint:
extends:
- .check
script:
- uv run --no-sync ruff format --check .
- uv run --no-sync ruff check .

security:
extends:
- .check
script:
- uv run --no-sync bandit -c pyproject.toml --quiet --recursive .

audit:
extends:
- .check
script:
- uvx uv-secure --no-check-uv-tool --ignore-unfixed uv.lock

# [Build]
# -----------------------------------------------------------------------------

build:
stage: Build
image: ${BUILDAH_IMAGE}
rules:
- <<: *pipeline-push-rule
- when: always
variables:
STORAGE_DRIVER: overlay
before_script:
- echo "${CI_REGISTRY_PASSWORD}" | buildah login "${CI_REGISTRY}" --username "${CI_REGISTRY_USER}" --password-stdin
- |
TAGS="--tag=${IMAGE_TAG}"
if [ -n "$CI_COMMIT_TAG" ]; then
TAGS="$TAGS --tag=${CI_REGISTRY_IMAGE}:v${CI_COMMIT_TAG} --tag=${CI_REGISTRY_IMAGE}:latest"
IMAGE_TAGS="${IMAGE_TAG}"
if [ -n "$CI_COMMIT_TAG" ]; then IMAGE_TAGS="$IMAGE_TAGS ${CI_REGISTRY_IMAGE}/${IMAGE_REPO}:${CI_COMMIT_SHA}"; fi
BUILD_TAGS=""
for image_tag in $IMAGE_TAGS; do BUILD_TAGS="$BUILD_TAGS --tag=$image_tag"; done
CACHE_ARGS="--cache-from=${CI_REGISTRY_IMAGE}/cache"
if [ "$CI_COMMIT_BRANCH" = "develop" ] || [ "$CI_COMMIT_BRANCH" = "main" ]; then
CACHE_ARGS="$CACHE_ARGS --cache-to=${CI_REGISTRY_IMAGE}/cache"
fi
script:
- buildah bud --format="${BUILDAH_FORMAT}" --target=remote --layers $TAGS .
- buildah push --all "${IMAGE_TAG}"
- buildah bud --format="${BUILDAH_FORMAT}" --target=remote --layers $CACHE_ARGS $BUILD_TAGS .
- for image_tag in $IMAGE_TAGS; do buildah push "$image_tag"; done
after_script:
- buildah logout ${CI_REGISTRY}

Expand All @@ -162,9 +222,12 @@ test:
extends:
- .test
stage: Test
tags:
- ${TEST_RUNNER_TAG}
rules:
- if: $CI_PIPELINE_SOURCE == "push"
script:
- uv run mypy .
- ./scripts/test.sh
coverage: '/^TOTAL.*\s+(\d+\%)$/'
artifacts:
Expand Down Expand Up @@ -352,7 +415,7 @@ deploy_production:
.rollback:
extends: .deploy
variables:
TF_VAR_image: "${CI_REGISTRY_IMAGE}:${CI_COMMIT_BEFORE_SHA}"
TF_VAR_image: "${CI_REGISTRY_IMAGE}/${IMAGE_REPO}:${CI_COMMIT_BEFORE_SHA}"

rollback_development:
extends:
Expand Down Expand Up @@ -436,11 +499,9 @@ create-version-tag_production:
- .sentry
stage: Sentry
script:
- RELEASE_START=$(date -d "${CI_PIPELINE_CREATED_AT}" +%s)
- RELEASE_END=$(date +%s)
- >
sentry-cli releases deploys "${CI_COMMIT_SHA}"
new --env "${ENV_NAME}" --time $((RELEASE_END-RELEASE_START))
new --env "${ENV_NAME}" --started "${CI_PIPELINE_CREATED_AT}"

sentry_success_development:
extends:
Expand Down
2 changes: 1 addition & 1 deletion {{cookiecutter.project_dirname}}/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/astral-sh/uv:python{{ cookiecutter.python_version }}-bookworm-slim AS base
FROM ghcr.io/astral-sh/uv:{{ cookiecutter.uv_version }}-python{{ cookiecutter.python_version }}-trixie-slim AS base

LABEL company="20tab" project="{{ cookiecutter.project_slug }}" service="{{ cookiecutter.service_slug }}" stage="base"

Expand Down
2 changes: 1 addition & 1 deletion {{cookiecutter.project_dirname}}/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ showoutdated:
uv tree --all-groups --outdated | grep --color=always "(latest:.*)" || true

# Run the test suite
test *ARGS:
test *ARGS: check
./scripts/test.sh {% raw %}{{ARGS}}{% endraw %}

# Upgrade all libraries
Expand Down
1 change: 1 addition & 0 deletions {{cookiecutter.project_dirname}}/scripts/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ uv run ruff format --check .
uv run ruff check .
uv run mypy .
uv run bandit -c pyproject.toml --quiet --recursive .
uvx uv-secure --no-check-uv-tool --ignore-unfixed uv.lock
9 changes: 6 additions & 3 deletions {{cookiecutter.project_dirname}}/scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

set -uo pipefail

./scripts/check.sh
./scripts/coverage.sh "$@"
./scripts/report.sh
status=0

./scripts/coverage.sh "$@" || status=1
./scripts/report.sh || status=1

exit "${status}"
Loading