fix(ci): auto-resolve the ECS base image for the runner rebuild

The automated rebuild failed with 'Missing required configuration:
--base-image-id' because the ALIYUN_ECS_BASE_IMAGE_ID repo variable
does not exist yet (it was flagged as a one-time setup item).

Remove the setup dependency instead: build-ecs-image.py now defaults
--base-image-id to the latest public Ubuntu 24.04 x86_64 system image
in the region (DescribeImages with image_owner_alias=system), so no
manual variable is required. The runner Dockerfile pins every tool
version itself, so base-image drift is low-risk; --base-image-id or
the ALIYUN_ECS_BASE_IMAGE_ID variable still pin a specific base image
deterministically, and the workflow only passes the flag when the
variable is set.

Part of #9289.

Signed-off-by: Ning Sun <sunning@greptime.com>
This commit is contained in:
Ning Sun
2026-09-28 11:28:59 +08:00
parent a6a823295f
commit 5a9fd2c769
3 changed files with 61 additions and 7 deletions
@@ -101,9 +101,15 @@ The manual fallback (also what the workflow runs):
ALIBABA_CLOUD_ACCESS_KEY_ID=... ALIBABA_CLOUD_ACCESS_KEY_SECRET=... \ ALIBABA_CLOUD_ACCESS_KEY_ID=... ALIBABA_CLOUD_ACCESS_KEY_SECRET=... \
uv run .github/runner-scale-sets/query-regression/ecs-image/build-ecs-image.py \ uv run .github/runner-scale-sets/query-regression/ecs-image/build-ecs-image.py \
--region-id <region> --vswitch-id <vsw-...> --security-group-id <sg-...> \ --region-id <region> --vswitch-id <vsw-...> --security-group-id <sg-...> \
--base-image-id <ubuntu-24.04-image-id> [--base-image-id <ubuntu-24.04-image-id>]
``` ```
`--base-image-id` is optional: the script defaults to the latest public
Ubuntu 24.04 image in the region (the Dockerfile pins every tool version
itself, so base drift is low-risk); pass it — or set the
`ALIYUN_ECS_BASE_IMAGE_ID` repo variable consumed by the automated job —
to pin a specific base image.
The script boots a temporary builder instance, `docker build`s the runner The script boots a temporary builder instance, `docker build`s the runner
image, materializes `/opt/rustup`, `/opt/cargo`, `/usr/local/bin` tools, and image, materializes `/opt/rustup`, `/opt/cargo`, `/usr/local/bin` tools, and
`/home/runner` (actions-runner) onto the host, installs the ephemeral-runner `/home/runner` (actions-runner) onto the host, installs the ephemeral-runner
@@ -235,6 +235,48 @@ def call_api_with_retry(fn, description: str, attempts: int = 5):
raise RuntimeError("unreachable: retry loop exited without returning") raise RuntimeError("unreachable: retry loop exited without returning")
def resolve_base_image_id(client, region_id: str) -> str:
"""Resolve the latest public Ubuntu 24.04 x86_64 system image.
Used as the default for --base-image-id: the runner Dockerfile pins
every tool version itself, so a current stock Ubuntu 24.04 base is all
the builder needs. Pass --base-image-id (or ALIYUN_ECS_BASE_IMAGE_ID)
to pin a specific base image deterministically.
"""
from alibabacloud_ecs20140526 import models as ecs_models
response = call_api_with_retry(
lambda: client.describe_images(
ecs_models.DescribeImagesRequest(
region_id=region_id,
image_owner_alias="system",
os_type="linux",
)
),
"DescribeImages(system base)",
)
candidates = [
image
for image in (response.body.images.image or [])
if (image.architecture or "") == "x86_64"
and "Ubuntu" in (image.os_name or "")
and "24.04" in (image.os_name or "")
]
if not candidates:
raise SystemExit(
"No public Ubuntu 24.04 x86_64 system image found in region "
f"{region_id}; pass --base-image-id explicitly"
)
candidates.sort(key=lambda image: image.creation_time or "", reverse=True)
picked = candidates[0]
print(
f"Resolved base image: {picked.image_id} ({picked.os_name}, "
f"created {picked.creation_time}) from {len(candidates)} candidates",
flush=True,
)
return picked.image_id
def read_console_output(client, region_id: str, instance_id: str) -> str: def read_console_output(client, region_id: str, instance_id: str) -> str:
"""Fetch the instance's serial console output; no in-guest agent needed.""" """Fetch the instance's serial console output; no in-guest agent needed."""
from alibabacloud_ecs20140526 import models as ecs_models from alibabacloud_ecs20140526 import models as ecs_models
@@ -259,13 +301,19 @@ def main() -> int:
parser.add_argument("--image-name", default=None, help="Defaults to a timestamped name.") parser.add_argument("--image-name", default=None, help="Defaults to a timestamped name.")
args = parser.parse_args() args = parser.parse_args()
for name in ("region_id", "vswitch_id", "security_group_id", "base_image_id"): for name in ("region_id", "vswitch_id", "security_group_id"):
if not getattr(args, name): if not getattr(args, name):
raise SystemExit(f"Missing required configuration: --{name.replace('_', '-')}") raise SystemExit(f"Missing required configuration: --{name.replace('_', '-')}")
from alibabacloud_ecs20140526 import models as ecs_models from alibabacloud_ecs20140526 import models as ecs_models
client = make_ecs_client(args.region_id) client = make_ecs_client(args.region_id)
# --base-image-id is optional: default to the latest public Ubuntu 24.04
# image in the region (the Dockerfile pins every tool version itself, so
# base drift is low-risk; pass --base-image-id or set
# ALIYUN_ECS_BASE_IMAGE_ID to pin deterministically).
if not args.base_image_id:
args.base_image_id = resolve_base_image_id(client, args.region_id)
image_name = args.image_name or time.strftime( image_name = args.image_name or time.strftime(
"greptimedb-query-regression-runner-%Y%m%d%H%M%S", time.gmtime() "greptimedb-query-regression-runner-%Y%m%d%H%M%S", time.gmtime()
) )
@@ -344,11 +344,11 @@ jobs:
# #
# Required repository configuration (same names the provisioning job # Required repository configuration (same names the provisioning job
# uses): vars ALIYUN_ECS_REGION_ID, ALIYUN_ECS_VSWITCH_ID, # uses): vars ALIYUN_ECS_REGION_ID, ALIYUN_ECS_VSWITCH_ID,
# ALIYUN_ECS_SECURITY_GROUP_ID, ALIYUN_ECS_BASE_IMAGE_ID (Ubuntu 24.04 # ALIYUN_ECS_SECURITY_GROUP_ID, optionally ALIYUN_ECS_RESOURCE_GROUP_ID
# public image id in the region; specific to this rebuild), optionally # and ALIYUN_ECS_BASE_IMAGE_ID (deterministic base-image pin; otherwise
# ALIYUN_ECS_RESOURCE_GROUP_ID; secrets ALICLOUD_ECS_ACCESS_KEY_ID, # the rebuild auto-resolves the latest public Ubuntu 24.04 image).
# ALICLOUD_ECS_ACCESS_KEY_SECRET, GH_PERSONAL_ACCESS_TOKEN (repo push + # Secrets: ALICLOUD_ECS_ACCESS_KEY_ID, ALICLOUD_ECS_ACCESS_KEY_SECRET,
# actions-variable write). # GH_PERSONAL_ACCESS_TOKEN (repo push + actions-variable write).
name: Rebuild query-regression runner image name: Rebuild query-regression runner image
needs: [changes] needs: [changes]
if: ${{ github.repository == 'GreptimeTeam/greptimedb' && ((github.event_name == 'push' && needs.changes.outputs.query-regression-runner == 'true') || inputs.release_query_regression_runner_image) }} if: ${{ github.repository == 'GreptimeTeam/greptimedb' && ((github.event_name == 'push' && needs.changes.outputs.query-regression-runner == 'true') || inputs.release_query_regression_runner_image) }}