From e72778a07341a5233aa8e84aaf965174e2260a12 Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Thu, 11 Jun 2026 20:17:22 +0200 Subject: [PATCH 1/8] Add Praktika CI configuration --- .gitignore | 1 + ci/infrastructure/projects.py | 232 ++++++++++++++++++++++++++++++++++ ci/settings/settings.py | 29 +++++ ci/workflows/main_ci.py | 20 +++ ci/workflows/pull_request.py | 21 +++ 5 files changed, 303 insertions(+) create mode 100644 ci/infrastructure/projects.py create mode 100644 ci/settings/settings.py create mode 100644 ci/workflows/main_ci.py create mode 100644 ci/workflows/pull_request.py diff --git a/.gitignore b/.gitignore index 4148b04..3927231 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .tools/ build/ compile_commands.json +ci/tmp/ diff --git a/ci/infrastructure/projects.py b/ci/infrastructure/projects.py new file mode 100644 index 0000000..b4b6bce --- /dev/null +++ b/ci/infrastructure/projects.py @@ -0,0 +1,232 @@ +import base64 + +from ci.settings.settings import PROJECT_NAME, PROJECT_SLUG +from praktika.infrastructure import Components, ImageBuilder, Storage, VPC +from praktika.infrastructure.cloud import CloudInfrastructure + + +CI_VPC_NAME = f"{PROJECT_SLUG}-ci" +_RUNTIME_BASE_VENV = "praktika-runtime" + +# until published in pip +_PRAKTIKA_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika-0.1.2-py3-none-any.whl" +# until published in pip +_PRAKTIKA_CONTROLLER_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika_controller-0.1.1-py3-none-any.whl" + + +def _write_file_from_base64(path: str, content: str) -> str: + payload = base64.b64encode(content.encode("utf-8")).decode("ascii") + return f"printf '%s' '{payload}' | base64 -d > {path}" + + +def _controller_image_component(name: str): + launcher = """#!/usr/bin/env bash +set -euo pipefail + +TOKEN=$(curl -fsS -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 60") +REGION=${AWS_DEFAULT_REGION:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region)} +INSTANCE_ID=${INSTANCE_ID:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)} +PRAKTIKA_CONTROLLER_ROLE=${PRAKTIKA_CONTROLLER_ROLE:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/praktika_role || true)} +PRAKTIKA_CONTROLLER_QUEUE=${PRAKTIKA_CONTROLLER_QUEUE:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/praktika_queue || true)} +PRAKTIKA_PROJECT_SLUG=${PRAKTIKA_PROJECT_SLUG:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/praktika_project_slug || true)} +if [ -z "$PRAKTIKA_CONTROLLER_ROLE" ] || [ -z "$PRAKTIKA_CONTROLLER_QUEUE" ]; then + echo "praktika_role or praktika_queue instance tag is unavailable" >&2 + exit 1 +fi +export HOME=/root +export AWS_DEFAULT_REGION="$REGION" +export INSTANCE_ID="$INSTANCE_ID" +export PRAKTIKA_PROJECT_SLUG +export PRAKTIKA_CONTROLLER_ROLE +export PRAKTIKA_CONTROLLER_QUEUE +exec /usr/local/bin/praktika-controller +""" + cloudwatch = """{ + "logs": { + "logs_collected": { + "files": { + "collect_list": [ + { + "file_path": "/var/log/praktika-controller.log", + "log_group_name": "/praktika/controller", + "log_stream_name": "{instance_id}", + "timezone": "UTC" + } + ] + } + } + } +} +""" + unit = """[Unit] +Description=Praktika Controller +After=network.target docker.service + +[Service] +Type=simple +Environment=HOME=/root +ExecStart=/usr/local/bin/praktika-controller-start +Restart=always +RestartSec=5 +StandardOutput=append:/var/log/praktika-controller.log +StandardError=append:/var/log/praktika-controller.log + +[Install] +WantedBy=multi-user.target +""" + commands = [ + "dnf install -y python3 python3-pip python3.12 python3.12-pip git jq awscli", + "dnf install -y amazon-cloudwatch-agent", + "ln -sf /usr/bin/python3.12 /usr/local/bin/python3", + "curl -fsSL https://cli.github.com/packages/rpm/gh-cli.repo -o /etc/yum.repos.d/gh-cli.repo", + "dnf install -y gh", + "dnf install -y docker", + "usermod -aG docker ec2-user || true", + "systemctl enable docker || true", + "mkdir -p /opt/praktika /opt/praktika/work /opt/praktika/base-venvs", + f"python3.12 -m venv /opt/praktika/base-venvs/{_RUNTIME_BASE_VENV}", + f"/opt/praktika/base-venvs/{_RUNTIME_BASE_VENV}/bin/python -m pip install --upgrade pip setuptools wheel", + f"/opt/praktika/base-venvs/{_RUNTIME_BASE_VENV}/bin/python -m pip install 'pytest>=7.0.0' {_PRAKTIKA_WHL}", + f"python3.12 -m pip install --force-reinstall {_PRAKTIKA_CONTROLLER_WHL} --break-system-packages", + "mkdir -p /etc/praktika", + "touch /var/log/praktika-controller.log", + "chmod 0644 /var/log/praktika-controller.log", + _write_file_from_base64( + "/usr/local/bin/praktika-controller-start", launcher + ), + "chmod 0755 /usr/local/bin/praktika-controller-start", + _write_file_from_base64( + "/etc/praktika/amazon-cloudwatch-agent.json", cloudwatch + ), + _write_file_from_base64( + "/etc/systemd/system/praktika-controller.service", unit + ), + "systemctl daemon-reload || true", + ] + return { + "name": name, + "platform": "Linux", + "description": "Install runner packages and bake the Praktika controller service", + "commands": commands, + } + + +def _image_builders(): + image_recipe_version = "1.0.1" + return [ + ImageBuilder.Config( + name="ci-arm64-image", + image_recipe_name="ci-arm64-image-recipe", + image_recipe_version=image_recipe_version, + inline_components=[ + _controller_image_component("controller-image"), + ], + infrastructure_configuration_name="ci-arm64-imagebuilder-infra", + instance_profile_name="arm-small-profile", + instance_types=["t4g.small"], + vpc_name=CI_VPC_NAME, + security_group_names=[f"{CI_VPC_NAME}-sg"], + distribution_configuration_name="ci-arm64-imagebuilder-dist", + ami_name="ci-arm64-{{ imagebuilder:buildDate }}", + ami_tags={"praktika_resource_tag": "controller", "arch": "arm64"}, + image_pipeline_name="ci-arm64-imagebuilder-pipeline", + ), + ImageBuilder.Config( + name="ci-x86_64-image", + image_recipe_name="ci-x86_64-image-recipe", + image_recipe_version=image_recipe_version, + inline_components=[ + _controller_image_component("controller-image"), + ], + infrastructure_configuration_name="ci-x86_64-imagebuilder-infra", + instance_profile_name="amd-small-profile", + instance_types=["t3.small"], + vpc_name=CI_VPC_NAME, + security_group_names=[f"{CI_VPC_NAME}-sg"], + distribution_configuration_name="ci-x86_64-imagebuilder-dist", + ami_name="ci-x86_64-{{ imagebuilder:buildDate }}", + ami_tags={"praktika_resource_tag": "controller", "arch": "x86_64"}, + image_pipeline_name="ci-x86_64-imagebuilder-pipeline", + ), + ] + + +_GH_TOKEN_MINTER = Components.GitHubTokenMinter( + repositories=[PROJECT_NAME], +) +_IMAGE_BUILDERS = _image_builders() +_IMAGE_BUILDERS_BY_NAME = {builder.name: builder for builder in _IMAGE_BUILDERS} + +PROJECTS = [ + CloudInfrastructure.Config( + name=PROJECT_NAME, + min_praktika_version="0.1.2", + vpcs=[ + VPC.Config( + name=CI_VPC_NAME, + subnets=[ + VPC.Subnet(availability_zone="eu-north-1a"), + ], + ) + ], + storages=[ + Storage.Config( + name="artifacts-eu-north-1", + retention_days=30, + public=True, + ), + ], + report_pages=[Components.report_page_config], + image_builders=_IMAGE_BUILDERS, + github_token_minters=[_GH_TOKEN_MINTER], + orchestrator_pool=Components.OrchestratorPool( + instance_type="t4g.small", + vpc_name=CI_VPC_NAME, + scaling=Components.OrchestratorPool.Scaling.Auto, + size=0, + max_size=50, + capacity_reserve=1, + image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], + ), + runner_pools=[ + Components.RunnerPool( + name="arm-small", + instance_type="t4g.small", + vpc_name=CI_VPC_NAME, + scaling=Components.RunnerPool.Scaling.Auto, + size=0, + max_size=50, + image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], + ), + Components.RunnerPool( + name="amd-small", + instance_type="t3.small", + vpc_name=CI_VPC_NAME, + scaling=Components.RunnerPool.Scaling.Auto, + size=0, + max_size=50, + image_builder=_IMAGE_BUILDERS_BY_NAME["ci-x86_64-image"], + ), + Components.RunnerPool( + name="arm-medium", + instance_type="c7g.4xlarge", + vpc_name=CI_VPC_NAME, + scaling=Components.RunnerPool.Scaling.Auto, + size=0, + max_size=50, + volume_size_gb=30, + image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], + ), + Components.RunnerPool( + name="amd-medium", + instance_type="c7a.4xlarge", + vpc_name=CI_VPC_NAME, + scaling=Components.RunnerPool.Scaling.Auto, + size=0, + max_size=50, + volume_size_gb=30, + image_builder=_IMAGE_BUILDERS_BY_NAME["ci-x86_64-image"], + ), + ], + ) +] diff --git a/ci/settings/settings.py b/ci/settings/settings.py new file mode 100644 index 0000000..9a447aa --- /dev/null +++ b/ci/settings/settings.py @@ -0,0 +1,29 @@ +class RunnerLabels: + SMALL_ARM = "arm-small" + SMALL_AMD = "amd-small" + MEDIUM_ARM = "arm-medium" + MEDIUM_AMD = "amd-medium" + + +PROJECT_NAME = "silk" +PROJECT_SLUG = "silk" +MAIN_BRANCH = "main" + +CI_CONFIG_RUNS_ON = [RunnerLabels.SMALL_ARM] + +AWS_REGION = "eu-north-1" +AWS_ACCOUNT_ID = "420943511422" +AWS_PROFILE = "Box" + +S3_ARTIFACT_BUCKET = f"{PROJECT_SLUG}-artifacts-eu-north-1" +S3_REPORT_BUCKET = S3_ARTIFACT_BUCKET +CACHE_S3_PATH = f"{S3_ARTIFACT_BUCKET}/ci_cache" +S3_BUCKET_TO_HTTP_ENDPOINT = { + S3_REPORT_BUCKET: f"{S3_REPORT_BUCKET}.s3.amazonaws.com", +} + +USE_CUSTOM_GH_AUTH = True +GH_AUTH_LAMBDA_NAME = f"{PROJECT_SLUG}-gh-token" +GH_AUTH_LAMBDA_REGION = AWS_REGION +PRAKTIKA_BASE_VENV = "praktika-runtime" + diff --git a/ci/workflows/main_ci.py b/ci/workflows/main_ci.py new file mode 100644 index 0000000..333ebb8 --- /dev/null +++ b/ci/workflows/main_ci.py @@ -0,0 +1,20 @@ +from praktika import Job, Workflow +from ci.settings.settings import RunnerLabels + + +WORKFLOWS = [ + Workflow.Config( + name="Main CI", + event=Workflow.Event.PUSH, + branches=["main"], + jobs=[ + Job.Config( + name="Smoke Test", + runs_on=[RunnerLabels.SMALL_ARM], + command='python3 -c \'print("hello from main ci")\'', + ), + ], + enable_report=True, + enable_exit_code_result=True, + ) +] diff --git a/ci/workflows/pull_request.py b/ci/workflows/pull_request.py new file mode 100644 index 0000000..374cbee --- /dev/null +++ b/ci/workflows/pull_request.py @@ -0,0 +1,21 @@ +from praktika import Job, Workflow +from ci.settings.settings import RunnerLabels + + +WORKFLOWS = [ + Workflow.Config( + name="Pull Request CI", + event=Workflow.Event.PULL_REQUEST, + base_branches=["main"], + jobs=[ + Job.Config( + name="Smoke Test", + runs_on=[RunnerLabels.SMALL_ARM], + command='python3 -c \'print("hello from praktika")\'', + ), + ], + enable_report=True, + enable_gh_summary_comment=True, + enable_exit_code_result=True, + ) +] From 2f09d112df83fa8e8c8286954d4540304be33171 Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Thu, 11 Jun 2026 22:25:24 +0200 Subject: [PATCH 2/8] Migrate pull request CI jobs to Praktika workflow Co-Authored-By: Claude Sonnet 4.6 --- .claude/skills/check-ci/SKILL.md | 50 ++++++ .github/workflows/ci.yml | 2 - ci/infrastructure/projects.py | 256 +++++++++++++++---------------- ci/jobs/fmt_job.py | 7 + ci/jobs/test_job.py | 68 ++++++++ ci/settings/settings.py | 4 +- ci/workflows/pull_request.py | 48 +++++- 7 files changed, 293 insertions(+), 142 deletions(-) create mode 100644 .claude/skills/check-ci/SKILL.md create mode 100644 ci/jobs/fmt_job.py create mode 100644 ci/jobs/test_job.py diff --git a/.claude/skills/check-ci/SKILL.md b/.claude/skills/check-ci/SKILL.md new file mode 100644 index 0000000..a00a156 --- /dev/null +++ b/.claude/skills/check-ci/SKILL.md @@ -0,0 +1,50 @@ +--- +name: check-ci +description: Fetch and report CI results for a silk PR. Use when the user asks to investigate, address, or fix CI failures, or refers to a PR without specifying what's broken. +--- + +Always fetch the CI result JSON before reading code or proposing fixes. + +## Determining PR, sha, and workflow name + +**From a Praktika report URL** (e.g. `https://silk-artifacts-eu-north-1.s3.amazonaws.com/json.html?PR=12&sha=abc123&name_0=Pull%20Request%20CI`): +- Extract `PR`, `sha`, `name_0` from query params +- Normalize `name_0`: lowercase + spaces → underscores (e.g. `"Pull Request CI"` → `"pull_request_ci"`) + +**From a bare PR number:** +- Run `gh pr view {PR} --json headRefOid --jq '.headRefOid'` to get the latest sha +- Use `pull_request_ci` as the normalized workflow name + +## Building the JSON URL + +``` +https://silk-artifacts-eu-north-1.s3.amazonaws.com/PRs/{PR}/{sha}/{normalized}/result_{normalized}.json +``` + +Fetch this URL with WebFetch. + +## Result structure + +The JSON is a serialized `praktika.Result`: + +``` +{ + "name": str, + "status": str, # OK | FAIL | ERROR | SKIPPED | UNKNOWN | XFAIL | XPASS | PENDING | RUNNING | DROPPED + "start_time": float?, + "duration": float?, + "info": str, + "results": [...], # nested Result objects, same shape, recursive + "files": [...], + "links": [...], + "ext": { + "labels": [{"name": str, "link": str?, "hint": str?}, ...], + "warnings": [...], + "errors": [...], + "report_url": str?, + ... + } +} +``` + +Walk the `results` tree recursively to find all failing jobs and sub-jobs. Use the `info` field of failing nodes as the primary signal for what went wrong before touching any code. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 028416c..bc3fcce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,6 @@ name: CI on: push: branches: [main] - pull_request: - branches: [main] workflow_dispatch: jobs: diff --git a/ci/infrastructure/projects.py b/ci/infrastructure/projects.py index b4b6bce..922ea3e 100644 --- a/ci/infrastructure/projects.py +++ b/ci/infrastructure/projects.py @@ -1,152 +1,148 @@ -import base64 - -from ci.settings.settings import PROJECT_NAME, PROJECT_SLUG -from praktika.infrastructure import Components, ImageBuilder, Storage, VPC +from ci.settings.settings import PROJECT_NAME, PROJECT_SLUG, PRAKTIKA_BASE_VENV +from praktika.infrastructure import Components, Storage, VPC from praktika.infrastructure.cloud import CloudInfrastructure -CI_VPC_NAME = f"{PROJECT_SLUG}-ci" -_RUNTIME_BASE_VENV = "praktika-runtime" - -# until published in pip -_PRAKTIKA_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika-0.1.2-py3-none-any.whl" # until published in pip _PRAKTIKA_CONTROLLER_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika_controller-0.1.1-py3-none-any.whl" -def _write_file_from_base64(path: str, content: str) -> str: - payload = base64.b64encode(content.encode("utf-8")).decode("ascii") - return f"printf '%s' '{payload}' | base64 -d > {path}" +def _silk_ci_dependencies_component(): + return { + "name": "silk-ci-dependencies", + "platform": "Linux", + "description": "Install Silk CI toolchains and build dependencies", + "commands": [ + "export DEBIAN_FRONTEND=noninteractive", + ( + "wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key " + "> /etc/apt/trusted.gpg.d/apt.llvm.org.asc" + ), + ( + ". /etc/os-release && echo \"deb http://apt.llvm.org/" + "${VERSION_CODENAME}/ llvm-toolchain-${VERSION_CODENAME}-21 main\" " + "> /etc/apt/sources.list.d/llvm-21.list" + ), + ( + "wget -qO- https://apt.kitware.com/keys/" + "kitware-archive-latest.asc > /etc/apt/trusted.gpg.d/kitware.asc" + ), + ( + ". /etc/os-release && echo \"deb https://apt.kitware.com/ubuntu/ " + "${VERSION_CODENAME} main\" > /etc/apt/sources.list.d/kitware.list" + ), + ( + "DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::Lock::Timeout=60 " + "install -y software-properties-common" + ), + "add-apt-repository -y ppa:ubuntu-toolchain-r/test", + "apt-get -o DPkg::Lock::Timeout=60 update -q", + ( + "DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::Lock::Timeout=60 " + "install -y clang-21 clang-format-21 llvm-21 cmake " + "libstdc++-13-dev ninja-build ccache libboost-dev " + "libdouble-conversion-dev libelf-dev zlib1g-dev" + ), + ], + } -def _controller_image_component(name: str): - launcher = """#!/usr/bin/env bash -set -euo pipefail +def _silk_ci_image_test_component(): + return Components.create_image_test_component( + name="silk-ci-image-test", + description="Validate Silk CI toolchains and build dependencies", + commands=[ + "test -d /opt/praktika/work", + "test -w /opt/praktika/work", + "test -x /usr/bin/clang-21", + "test -x /usr/bin/clang-format-21", + "test -x /usr/bin/cmake", + "test -x /usr/bin/ninja", + "test -x /usr/bin/ccache", + "clang-21 --version", + "clang-format-21 --version", + "cmake --version", + "ninja --version", + "ccache --version", + ( + "for package in llvm-21 libstdc++-13-dev libboost-dev " + "libdouble-conversion-dev libelf-dev zlib1g-dev; do " + "dpkg-query -W -f='${Status}\\n' \"$package\" " + "| grep -qx 'install ok installed'; done" + ), + ], + ) -TOKEN=$(curl -fsS -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 60") -REGION=${AWS_DEFAULT_REGION:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region)} -INSTANCE_ID=${INSTANCE_ID:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)} -PRAKTIKA_CONTROLLER_ROLE=${PRAKTIKA_CONTROLLER_ROLE:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/praktika_role || true)} -PRAKTIKA_CONTROLLER_QUEUE=${PRAKTIKA_CONTROLLER_QUEUE:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/praktika_queue || true)} -PRAKTIKA_PROJECT_SLUG=${PRAKTIKA_PROJECT_SLUG:-$(curl -fsS -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/tags/instance/praktika_project_slug || true)} -if [ -z "$PRAKTIKA_CONTROLLER_ROLE" ] || [ -z "$PRAKTIKA_CONTROLLER_QUEUE" ]; then - echo "praktika_role or praktika_queue instance tag is unavailable" >&2 - exit 1 -fi -export HOME=/root -export AWS_DEFAULT_REGION="$REGION" -export INSTANCE_ID="$INSTANCE_ID" -export PRAKTIKA_PROJECT_SLUG -export PRAKTIKA_CONTROLLER_ROLE -export PRAKTIKA_CONTROLLER_QUEUE -exec /usr/local/bin/praktika-controller -""" - cloudwatch = """{ - "logs": { - "logs_collected": { - "files": { - "collect_list": [ - { - "file_path": "/var/log/praktika-controller.log", - "log_group_name": "/praktika/controller", - "log_stream_name": "{instance_id}", - "timezone": "UTC" - } - ] - } - } - } -} -""" - unit = """[Unit] -Description=Praktika Controller -After=network.target docker.service -[Service] -Type=simple -Environment=HOME=/root -ExecStart=/usr/local/bin/praktika-controller-start -Restart=always -RestartSec=5 -StandardOutput=append:/var/log/praktika-controller.log -StandardError=append:/var/log/praktika-controller.log +def _praktika_controller_image_test_component(): + controller = "praktika-controller" + start_script = f"/usr/local/bin/${{controller}}-start" + service_unit = f"/etc/systemd/system/${{controller}}.service" + return Components.create_image_test_component( + name="silk-praktika-controller-image-test", + description="Validate Praktika controller runtime and boot wiring", + commands=[ + f"controller={controller}; command -v \"$controller\"", + ( + f"controller={controller}; " + "python3.12 -m pip show \"$controller\"" + ), + f"controller={controller}; test -x {start_script}", + f"controller={controller}; bash -n {start_script}", + f"controller={controller}; test -f {service_unit}", + ( + f"controller={controller}; " + f"grep -qx \"ExecStart={start_script}\" {service_unit}" + ), + ( + f"controller={controller}; " + f"grep -qx \"StandardOutput=append:/var/log/${{controller}}.log\" {service_unit}" + ), + ( + f"controller={controller}; " + f"grep -qx \"StandardError=append:/var/log/${{controller}}.log\" {service_unit}" + ), + ( + "test -x /usr/local/bin/praktika-configure-cloudwatch-agent " + "&& bash -n /usr/local/bin/praktika-configure-cloudwatch-agent" + ), + "test -x /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl", + ], + ) -[Install] -WantedBy=multi-user.target -""" - commands = [ - "dnf install -y python3 python3-pip python3.12 python3.12-pip git jq awscli", - "dnf install -y amazon-cloudwatch-agent", - "ln -sf /usr/bin/python3.12 /usr/local/bin/python3", - "curl -fsSL https://cli.github.com/packages/rpm/gh-cli.repo -o /etc/yum.repos.d/gh-cli.repo", - "dnf install -y gh", - "dnf install -y docker", - "usermod -aG docker ec2-user || true", - "systemctl enable docker || true", - "mkdir -p /opt/praktika /opt/praktika/work /opt/praktika/base-venvs", - f"python3.12 -m venv /opt/praktika/base-venvs/{_RUNTIME_BASE_VENV}", - f"/opt/praktika/base-venvs/{_RUNTIME_BASE_VENV}/bin/python -m pip install --upgrade pip setuptools wheel", - f"/opt/praktika/base-venvs/{_RUNTIME_BASE_VENV}/bin/python -m pip install 'pytest>=7.0.0' {_PRAKTIKA_WHL}", - f"python3.12 -m pip install --force-reinstall {_PRAKTIKA_CONTROLLER_WHL} --break-system-packages", - "mkdir -p /etc/praktika", - "touch /var/log/praktika-controller.log", - "chmod 0644 /var/log/praktika-controller.log", - _write_file_from_base64( - "/usr/local/bin/praktika-controller-start", launcher - ), - "chmod 0755 /usr/local/bin/praktika-controller-start", - _write_file_from_base64( - "/etc/praktika/amazon-cloudwatch-agent.json", cloudwatch - ), - _write_file_from_base64( - "/etc/systemd/system/praktika-controller.service", unit - ), - "systemctl daemon-reload || true", + +def _silk_ci_image_components(): + return [ + _silk_ci_dependencies_component(), + _silk_ci_image_test_component(), + _praktika_controller_image_test_component(), ] - return { - "name": name, - "platform": "Linux", - "description": "Install runner packages and bake the Praktika controller service", - "commands": commands, - } def _image_builders(): - image_recipe_version = "1.0.1" + image_recipe_version = "1.0.5" + prebuilt_venvs = [ + Components.create_praktika_venv_config( + PRAKTIKA_BASE_VENV, + "0.1.2", + ), + ] return [ - ImageBuilder.Config( + Components.create_ubuntu_image_builder_config( name="ci-arm64-image", - image_recipe_name="ci-arm64-image-recipe", - image_recipe_version=image_recipe_version, - inline_components=[ - _controller_image_component("controller-image"), - ], - infrastructure_configuration_name="ci-arm64-imagebuilder-infra", - instance_profile_name="arm-small-profile", + version=image_recipe_version, + controller_package=_PRAKTIKA_CONTROLLER_WHL, + prebuilt_venvs=prebuilt_venvs, instance_types=["t4g.small"], - vpc_name=CI_VPC_NAME, - security_group_names=[f"{CI_VPC_NAME}-sg"], - distribution_configuration_name="ci-arm64-imagebuilder-dist", - ami_name="ci-arm64-{{ imagebuilder:buildDate }}", - ami_tags={"praktika_resource_tag": "controller", "arch": "arm64"}, - image_pipeline_name="ci-arm64-imagebuilder-pipeline", + components=_silk_ci_image_components(), ), - ImageBuilder.Config( + Components.create_ubuntu_image_builder_config( name="ci-x86_64-image", - image_recipe_name="ci-x86_64-image-recipe", - image_recipe_version=image_recipe_version, - inline_components=[ - _controller_image_component("controller-image"), - ], - infrastructure_configuration_name="ci-x86_64-imagebuilder-infra", - instance_profile_name="amd-small-profile", + version=image_recipe_version, + controller_package=_PRAKTIKA_CONTROLLER_WHL, + prebuilt_venvs=prebuilt_venvs, instance_types=["t3.small"], - vpc_name=CI_VPC_NAME, - security_group_names=[f"{CI_VPC_NAME}-sg"], - distribution_configuration_name="ci-x86_64-imagebuilder-dist", - ami_name="ci-x86_64-{{ imagebuilder:buildDate }}", - ami_tags={"praktika_resource_tag": "controller", "arch": "x86_64"}, - image_pipeline_name="ci-x86_64-imagebuilder-pipeline", + components=_silk_ci_image_components(), ), ] @@ -163,7 +159,6 @@ def _image_builders(): min_praktika_version="0.1.2", vpcs=[ VPC.Config( - name=CI_VPC_NAME, subnets=[ VPC.Subnet(availability_zone="eu-north-1a"), ], @@ -181,7 +176,6 @@ def _image_builders(): github_token_minters=[_GH_TOKEN_MINTER], orchestrator_pool=Components.OrchestratorPool( instance_type="t4g.small", - vpc_name=CI_VPC_NAME, scaling=Components.OrchestratorPool.Scaling.Auto, size=0, max_size=50, @@ -192,7 +186,6 @@ def _image_builders(): Components.RunnerPool( name="arm-small", instance_type="t4g.small", - vpc_name=CI_VPC_NAME, scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, @@ -201,7 +194,6 @@ def _image_builders(): Components.RunnerPool( name="amd-small", instance_type="t3.small", - vpc_name=CI_VPC_NAME, scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, @@ -210,7 +202,6 @@ def _image_builders(): Components.RunnerPool( name="arm-medium", instance_type="c7g.4xlarge", - vpc_name=CI_VPC_NAME, scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, @@ -220,7 +211,6 @@ def _image_builders(): Components.RunnerPool( name="amd-medium", instance_type="c7a.4xlarge", - vpc_name=CI_VPC_NAME, scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, diff --git a/ci/jobs/fmt_job.py b/ci/jobs/fmt_job.py new file mode 100644 index 0000000..93245f6 --- /dev/null +++ b/ci/jobs/fmt_job.py @@ -0,0 +1,7 @@ +from praktika.result import Result + +if __name__ == "__main__": + Result.from_commands_run( + name="Check formatting", + command=["./bb fmt --check"], + ).complete_job() diff --git a/ci/jobs/test_job.py b/ci/jobs/test_job.py new file mode 100644 index 0000000..97a6582 --- /dev/null +++ b/ci/jobs/test_job.py @@ -0,0 +1,68 @@ +import sys + +from praktika.result import Result + +_CONFIGS = { + "coverage": { + "test": "./bb -b debug test --coverage", + }, + "release": { + "configure": "./bb -b release configure --build-poco --build-jemalloc", + "test": "./bb -b release test", + "bench": "./bb -b release bench", + "perf": "./bb -v -b release perf file net http", + }, + "tsan": { + "configure": "./bb -b release -s thread configure --build-poco", + "test": "./bb -b release -s thread test", + "bench": "./bb -b release -s thread bench", + "perf": "./bb -v -b release -s thread perf file net http", + }, + "asan": { + "test": "./bb -b release -s address test", + }, + "ubsan": { + "test": "./bb -b release -s undefined test", + }, + "msan": { + "test": "./bb -b release -s memory test", + }, +} + +if __name__ == "__main__": + build = sys.argv[1] + config = _CONFIGS[build] + results = [] + + if "configure" in config: + results.append( + Result.from_commands_run( + name="Configure", + command=[config["configure"]], + ) + ) + + results.append( + Result.from_commands_run( + name="Build and test", + command=[config["test"]], + ) + ) + + if "bench" in config: + results.append( + Result.from_commands_run( + name="Bench", + command=[config["bench"]], + ) + ) + + if "perf" in config: + results.append( + Result.from_commands_run( + name="Perf", + command=[config["perf"]], + ) + ) + + Result.create_from(results=results).complete_job() diff --git a/ci/settings/settings.py b/ci/settings/settings.py index 9a447aa..52f2381 100644 --- a/ci/settings/settings.py +++ b/ci/settings/settings.py @@ -15,7 +15,7 @@ class RunnerLabels: AWS_ACCOUNT_ID = "420943511422" AWS_PROFILE = "Box" -S3_ARTIFACT_BUCKET = f"{PROJECT_SLUG}-artifacts-eu-north-1" +S3_ARTIFACT_BUCKET = f"{PROJECT_SLUG}-artifacts-{AWS_REGION}" S3_REPORT_BUCKET = S3_ARTIFACT_BUCKET CACHE_S3_PATH = f"{S3_ARTIFACT_BUCKET}/ci_cache" S3_BUCKET_TO_HTTP_ENDPOINT = { @@ -25,5 +25,5 @@ class RunnerLabels: USE_CUSTOM_GH_AUTH = True GH_AUTH_LAMBDA_NAME = f"{PROJECT_SLUG}-gh-token" GH_AUTH_LAMBDA_REGION = AWS_REGION -PRAKTIKA_BASE_VENV = "praktika-runtime" +PRAKTIKA_BASE_VENV = "praktika-runtime-0.1.2" diff --git a/ci/workflows/pull_request.py b/ci/workflows/pull_request.py index 374cbee..2d5e01e 100644 --- a/ci/workflows/pull_request.py +++ b/ci/workflows/pull_request.py @@ -1,6 +1,46 @@ from praktika import Job, Workflow from ci.settings.settings import RunnerLabels +FMT_JOB = Job.Config( + name="Formatting", + runs_on=[RunnerLabels.SMALL_ARM], + command="python3 ./ci/jobs/fmt_job.py", + digest_config=Job.CacheDigestConfig( + include_paths=["src", "include"], + ), +) + +_TEST_DIGEST = Job.CacheDigestConfig( + include_paths=["src", "include", "CMakeLists.txt", "CMakePresets.json", "bb"], + with_git_submodules=True, +) + +_TEST_ARM = Job.Config( + name="Test ARM", + runs_on=[RunnerLabels.SMALL_ARM], + command="python3 ./ci/jobs/test_job.py {PARAMETER}", + needs_submodules=True, + timeout=2 * 3600, + digest_config=_TEST_DIGEST, +) + +_TEST_AMD = Job.Config( + name="Test AMD", + runs_on=[RunnerLabels.SMALL_AMD], + command="python3 ./ci/jobs/test_job.py {PARAMETER}", + needs_submodules=True, + timeout=2 * 3600, + digest_config=_TEST_DIGEST, +) + +_BUILD_VARIANTS = [ + Job.ParamSet(parameter="coverage"), + Job.ParamSet(parameter="release"), + Job.ParamSet(parameter="tsan"), + Job.ParamSet(parameter="asan"), + Job.ParamSet(parameter="ubsan"), + Job.ParamSet(parameter="msan"), +] WORKFLOWS = [ Workflow.Config( @@ -8,11 +48,9 @@ event=Workflow.Event.PULL_REQUEST, base_branches=["main"], jobs=[ - Job.Config( - name="Smoke Test", - runs_on=[RunnerLabels.SMALL_ARM], - command='python3 -c \'print("hello from praktika")\'', - ), + FMT_JOB, + *_TEST_ARM.parametrize(*_BUILD_VARIANTS), + *_TEST_AMD.parametrize(*_BUILD_VARIANTS), ], enable_report=True, enable_gh_summary_comment=True, From f3ffcfe0c728a75081fe1b6f168a43ad1e564a01 Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Mon, 15 Jun 2026 12:01:13 +0200 Subject: [PATCH 3/8] Enable submodule cache in Praktika CI Co-Authored-By: Claude Sonnet 4.6 --- ci/infrastructure/projects.py | 35 +++++++++++++++++++++++++++++++---- ci/settings/settings.py | 1 + ci/workflows/pull_request.py | 1 + 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/ci/infrastructure/projects.py b/ci/infrastructure/projects.py index 922ea3e..2fa67ce 100644 --- a/ci/infrastructure/projects.py +++ b/ci/infrastructure/projects.py @@ -4,9 +4,31 @@ # until published in pip +_PRAKTIKA_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika-0.1.2-py3-none-any.whl" _PRAKTIKA_CONTROLLER_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika_controller-0.1.1-py3-none-any.whl" +def _runner_user_data(): + return "\n".join( + [ + "#!/usr/bin/env bash", + "set -xeuo pipefail", + "", + "# Force-reinstall praktika so the runner uses the version pinned here", + "# rather than whatever was baked into the AMI at image-build time.", + ( + f"/opt/praktika/base-venvs/{PRAKTIKA_BASE_VENV}/bin/python " + f"-m pip install --force-reinstall {_PRAKTIKA_WHL}" + ), + "# Add any host customization you need above this line.", + "/usr/local/bin/praktika-configure-cloudwatch-agent", + "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/etc/praktika/amazon-cloudwatch-agent.json -s", + "systemctl enable --now praktika-controller", + "", + ] + ) + + def _silk_ci_dependencies_component(): return { "name": "silk-ci-dependencies", @@ -180,24 +202,29 @@ def _image_builders(): size=0, max_size=50, capacity_reserve=1, + volume_size_gb=100, image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], ), runner_pools=[ Components.RunnerPool( name="arm-small", - instance_type="t4g.small", + instance_type="t4g.medium", scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, + volume_size_gb=100, image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], + user_data=_runner_user_data(), ), Components.RunnerPool( name="amd-small", - instance_type="t3.small", + instance_type="t3.medium", scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, + volume_size_gb=100, image_builder=_IMAGE_BUILDERS_BY_NAME["ci-x86_64-image"], + user_data=_runner_user_data(), ), Components.RunnerPool( name="arm-medium", @@ -205,7 +232,7 @@ def _image_builders(): scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, - volume_size_gb=30, + volume_size_gb=100, image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], ), Components.RunnerPool( @@ -214,7 +241,7 @@ def _image_builders(): scaling=Components.RunnerPool.Scaling.Auto, size=0, max_size=50, - volume_size_gb=30, + volume_size_gb=100, image_builder=_IMAGE_BUILDERS_BY_NAME["ci-x86_64-image"], ), ], diff --git a/ci/settings/settings.py b/ci/settings/settings.py index 52f2381..3b03154 100644 --- a/ci/settings/settings.py +++ b/ci/settings/settings.py @@ -18,6 +18,7 @@ class RunnerLabels: S3_ARTIFACT_BUCKET = f"{PROJECT_SLUG}-artifacts-{AWS_REGION}" S3_REPORT_BUCKET = S3_ARTIFACT_BUCKET CACHE_S3_PATH = f"{S3_ARTIFACT_BUCKET}/ci_cache" +ENABLE_SUBMODULE_CACHE = True S3_BUCKET_TO_HTTP_ENDPOINT = { S3_REPORT_BUCKET: f"{S3_REPORT_BUCKET}.s3.amazonaws.com", } diff --git a/ci/workflows/pull_request.py b/ci/workflows/pull_request.py index 2d5e01e..aa89cf4 100644 --- a/ci/workflows/pull_request.py +++ b/ci/workflows/pull_request.py @@ -52,6 +52,7 @@ *_TEST_ARM.parametrize(*_BUILD_VARIANTS), *_TEST_AMD.parametrize(*_BUILD_VARIANTS), ], + enable_cache=True, enable_report=True, enable_gh_summary_comment=True, enable_exit_code_result=True, From e14473780bd6574a2fdb665c0cb11ca52ffdc0fb Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Mon, 15 Jun 2026 16:36:28 +0200 Subject: [PATCH 4/8] Restore cached submodules before Praktika tests --- ci/workflows/pull_request.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ci/workflows/pull_request.py b/ci/workflows/pull_request.py index aa89cf4..b370c5a 100644 --- a/ci/workflows/pull_request.py +++ b/ci/workflows/pull_request.py @@ -15,11 +15,38 @@ with_git_submodules=True, ) +_CHECKOUT_TEST_SUBMODULES = r""" +set -euo pipefail +git submodule sync +git submodule update --init --no-fetch --depth=1 --jobs 8 \ + contrib/benchmark \ + contrib/bpftool \ + contrib/cxxopts \ + contrib/googletest \ + contrib/libbacktrace \ + contrib/libbpf \ + contrib/librseq \ + contrib/liburing + +case "$JOB_NAME" in + *"(release)"*) + git submodule update --init --no-fetch --depth=1 --jobs 8 contrib/poco contrib/jemalloc + ;; + *"(tsan)"*) + git submodule update --init --no-fetch --depth=1 --jobs 8 contrib/poco + ;; + *"(msan)"*) + git submodule update --init --no-fetch --depth=1 --jobs 8 contrib/llvm-project + ;; +esac +""" + _TEST_ARM = Job.Config( name="Test ARM", runs_on=[RunnerLabels.SMALL_ARM], command="python3 ./ci/jobs/test_job.py {PARAMETER}", needs_submodules=True, + pre_hooks=[_CHECKOUT_TEST_SUBMODULES], timeout=2 * 3600, digest_config=_TEST_DIGEST, ) @@ -29,6 +56,7 @@ runs_on=[RunnerLabels.SMALL_AMD], command="python3 ./ci/jobs/test_job.py {PARAMETER}", needs_submodules=True, + pre_hooks=[_CHECKOUT_TEST_SUBMODULES], timeout=2 * 3600, digest_config=_TEST_DIGEST, ) From 8475ebc2d5d26a25ec948f11930eee2ad1d65546 Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Mon, 15 Jun 2026 16:52:38 +0200 Subject: [PATCH 5/8] Use short submodule checkout hook in CI --- ci/jobs/init_submodules.py | 51 ++++++++++++++++++++++++++++++++++++ ci/workflows/pull_request.py | 35 +++++++------------------ 2 files changed, 60 insertions(+), 26 deletions(-) create mode 100644 ci/jobs/init_submodules.py diff --git a/ci/jobs/init_submodules.py b/ci/jobs/init_submodules.py new file mode 100644 index 0000000..f277232 --- /dev/null +++ b/ci/jobs/init_submodules.py @@ -0,0 +1,51 @@ +import os +import subprocess + + +COMMON_SUBMODULES = [ + "contrib/benchmark", + "contrib/bpftool", + "contrib/cxxopts", + "contrib/googletest", + "contrib/libbacktrace", + "contrib/libbpf", + "contrib/librseq", + "contrib/liburing", +] + +EXTRA_SUBMODULES_BY_BUILD = { + "release": ["contrib/poco", "contrib/jemalloc"], + "tsan": ["contrib/poco"], + "msan": ["contrib/llvm-project"], +} + + +def run(*args): + print("+", " ".join(args), flush=True) + subprocess.run(args, check=True) + + +def checkout_submodules(paths): + run( + "git", + "submodule", + "update", + "--init", + "--no-fetch", + "--depth=1", + "--jobs", + "8", + *paths, + ) + + +if __name__ == "__main__": + job_name = os.environ["JOB_NAME"] + + run("git", "submodule", "sync") + checkout_submodules(COMMON_SUBMODULES) + + for build, paths in EXTRA_SUBMODULES_BY_BUILD.items(): + if f"({build})" in job_name: + checkout_submodules(paths) + break diff --git a/ci/workflows/pull_request.py b/ci/workflows/pull_request.py index b370c5a..504615f 100644 --- a/ci/workflows/pull_request.py +++ b/ci/workflows/pull_request.py @@ -11,35 +11,18 @@ ) _TEST_DIGEST = Job.CacheDigestConfig( - include_paths=["src", "include", "CMakeLists.txt", "CMakePresets.json", "bb"], + include_paths=[ + "src", + "include", + "CMakeLists.txt", + "CMakePresets.json", + "bb", + "ci/jobs/init_submodules.py", + ], with_git_submodules=True, ) -_CHECKOUT_TEST_SUBMODULES = r""" -set -euo pipefail -git submodule sync -git submodule update --init --no-fetch --depth=1 --jobs 8 \ - contrib/benchmark \ - contrib/bpftool \ - contrib/cxxopts \ - contrib/googletest \ - contrib/libbacktrace \ - contrib/libbpf \ - contrib/librseq \ - contrib/liburing - -case "$JOB_NAME" in - *"(release)"*) - git submodule update --init --no-fetch --depth=1 --jobs 8 contrib/poco contrib/jemalloc - ;; - *"(tsan)"*) - git submodule update --init --no-fetch --depth=1 --jobs 8 contrib/poco - ;; - *"(msan)"*) - git submodule update --init --no-fetch --depth=1 --jobs 8 contrib/llvm-project - ;; -esac -""" +_CHECKOUT_TEST_SUBMODULES = "python3 ./ci/jobs/init_submodules.py" _TEST_ARM = Job.Config( name="Test ARM", From 7db8a1deb745fd0ea13ec300142de9e79ce86476 Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Mon, 15 Jun 2026 17:32:25 +0200 Subject: [PATCH 6/8] Read Praktika job name from Info --- ci/infrastructure/projects.py | 2 +- ci/jobs/init_submodules.py | 5 +++-- ci/workflows/pull_request.py | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ci/infrastructure/projects.py b/ci/infrastructure/projects.py index 2fa67ce..f3cc225 100644 --- a/ci/infrastructure/projects.py +++ b/ci/infrastructure/projects.py @@ -142,7 +142,7 @@ def _silk_ci_image_components(): def _image_builders(): - image_recipe_version = "1.0.5" + image_recipe_version = "1.0.6" prebuilt_venvs = [ Components.create_praktika_venv_config( PRAKTIKA_BASE_VENV, diff --git a/ci/jobs/init_submodules.py b/ci/jobs/init_submodules.py index f277232..81010ed 100644 --- a/ci/jobs/init_submodules.py +++ b/ci/jobs/init_submodules.py @@ -1,6 +1,7 @@ -import os import subprocess +from praktika.info import Info + COMMON_SUBMODULES = [ "contrib/benchmark", @@ -40,7 +41,7 @@ def checkout_submodules(paths): if __name__ == "__main__": - job_name = os.environ["JOB_NAME"] + job_name = Info().job_name run("git", "submodule", "sync") checkout_submodules(COMMON_SUBMODULES) diff --git a/ci/workflows/pull_request.py b/ci/workflows/pull_request.py index 504615f..1f4a21e 100644 --- a/ci/workflows/pull_request.py +++ b/ci/workflows/pull_request.py @@ -26,7 +26,7 @@ _TEST_ARM = Job.Config( name="Test ARM", - runs_on=[RunnerLabels.SMALL_ARM], + runs_on=[RunnerLabels.MEDIUM_ARM], command="python3 ./ci/jobs/test_job.py {PARAMETER}", needs_submodules=True, pre_hooks=[_CHECKOUT_TEST_SUBMODULES], @@ -36,7 +36,7 @@ _TEST_AMD = Job.Config( name="Test AMD", - runs_on=[RunnerLabels.SMALL_AMD], + runs_on=[RunnerLabels.MEDIUM_AMD], command="python3 ./ci/jobs/test_job.py {PARAMETER}", needs_submodules=True, pre_hooks=[_CHECKOUT_TEST_SUBMODULES], From af1e0ee297c28c144c837202bd7f64d8032a956c Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Thu, 18 Jun 2026 15:10:47 +0200 Subject: [PATCH 7/8] large runners --- ci/infrastructure/projects.py | 9 +++++++++ ci/settings/settings.py | 1 + 2 files changed, 10 insertions(+) diff --git a/ci/infrastructure/projects.py b/ci/infrastructure/projects.py index f3cc225..695e05b 100644 --- a/ci/infrastructure/projects.py +++ b/ci/infrastructure/projects.py @@ -235,6 +235,15 @@ def _image_builders(): volume_size_gb=100, image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], ), + Components.RunnerPool( + name="arm-large", + instance_type="c7g.8xlarge", + scaling=Components.RunnerPool.Scaling.Auto, + size=0, + max_size=50, + volume_size_gb=100, + image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], + ), Components.RunnerPool( name="amd-medium", instance_type="c7a.4xlarge", diff --git a/ci/settings/settings.py b/ci/settings/settings.py index 3b03154..3895e57 100644 --- a/ci/settings/settings.py +++ b/ci/settings/settings.py @@ -3,6 +3,7 @@ class RunnerLabels: SMALL_AMD = "amd-small" MEDIUM_ARM = "arm-medium" MEDIUM_AMD = "amd-medium" + LARGE_ARM = "arm-large" PROJECT_NAME = "silk" From 063d4ba262ec88a3d7bcd8ae0e73d492c5443476 Mon Sep 17 00:00:00 2001 From: Max Kainov Date: Thu, 18 Jun 2026 15:48:22 +0200 Subject: [PATCH 8/8] add push workflow --- ci/infrastructure/projects.py | 9 +++++---- ci/workflows/main_ci.py | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ci/infrastructure/projects.py b/ci/infrastructure/projects.py index 695e05b..cd8c56b 100644 --- a/ci/infrastructure/projects.py +++ b/ci/infrastructure/projects.py @@ -4,7 +4,7 @@ # until published in pip -_PRAKTIKA_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika-0.1.2-py3-none-any.whl" +_PRAKTIKA_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika-0.1.3-py3-none-any.whl" _PRAKTIKA_CONTROLLER_WHL = "https://praktika-artifacts-eu-north-1.s3.amazonaws.com/packages/praktika_controller-0.1.1-py3-none-any.whl" @@ -142,11 +142,11 @@ def _silk_ci_image_components(): def _image_builders(): - image_recipe_version = "1.0.6" + image_recipe_version = "1.0.7" prebuilt_venvs = [ Components.create_praktika_venv_config( PRAKTIKA_BASE_VENV, - "0.1.2", + "0.1.3", ), ] return [ @@ -178,7 +178,7 @@ def _image_builders(): PROJECTS = [ CloudInfrastructure.Config( name=PROJECT_NAME, - min_praktika_version="0.1.2", + min_praktika_version="0.1.3", vpcs=[ VPC.Config( subnets=[ @@ -204,6 +204,7 @@ def _image_builders(): capacity_reserve=1, volume_size_gb=100, image_builder=_IMAGE_BUILDERS_BY_NAME["ci-arm64-image"], + ext={"allowed_push_branches": ["main", "add-praktika-ci-config"]} ), runner_pools=[ Components.RunnerPool( diff --git a/ci/workflows/main_ci.py b/ci/workflows/main_ci.py index 333ebb8..4e6d151 100644 --- a/ci/workflows/main_ci.py +++ b/ci/workflows/main_ci.py @@ -6,12 +6,12 @@ Workflow.Config( name="Main CI", event=Workflow.Event.PUSH, - branches=["main"], + branches=["main", "add-praktika-ci-config"], jobs=[ Job.Config( - name="Smoke Test", + name="Hello World Test", runs_on=[RunnerLabels.SMALL_ARM], - command='python3 -c \'print("hello from main ci")\'', + command='python3 -c \'print("hello world")\'', ), ], enable_report=True,