Skip to content

Commit 88d4c44

Browse files
authored
Auto-detect pipeline ID and commit SHA for local e2e test runs (#47575)
### What does this PR do? When running `dda inv new-e2e-tests.run` locally (not in CI), automatically look up the most recent GitLab pipeline for the current HEAD commit SHA and set `E2E_PIPELINE_ID` / `E2E_COMMIT_SHA` — so tests use the correct build artifacts without needing the user to set those env vars manually. Two changes in `tasks/new_e2e_tests.py`: **New helper `_find_pipeline_for_commit_sha`** - Queries the GitLab API for pipelines matching the current HEAD commit SHA - For each candidate pipeline, fetches all jobs and verifies that the `packaging` and `deploy_packages` stages are both present and have all jobs in `success` or `skipped` state - Returns the first pipeline that passes, or `None` with a diagnostic message to stderr **Updated `run` task (local path only)** - Inside the existing `if not running_in_ci():` block, if `E2E_PIPELINE_ID` is not already in the environment, calls the new helper and sets `E2E_PIPELINE_ID` + `E2E_COMMIT_SHA` in `env_vars` - If no qualifying pipeline is found, prints a yellow warning and continues — the task still runs, preserving previous behaviour for cases where no pipeline exists (e.g. a brand-new branch) ### Motivation Previously, developers had to manually find the right pipeline ID and set `E2E_PIPELINE_ID`/`E2E_COMMIT_SHA` before running e2e tests locally. This was error-prone and tedious. The auto-detection removes that friction while ensuring only pipelines with completed packaging artifacts are used. ### Describe how you validated your changes - Code review: verified the GitLab `pipelines.list(sha=...)` and `pipeline.jobs.list(get_all=True)` API usage matches the python-gitlab client interface already used elsewhere in the codebase (`_find_recent_successful_pipeline`) - The change is gated behind `not running_in_ci()` and `"E2E_PIPELINE_ID" not in os.environ`, so it is a no-op in CI and when users have already set the env var manually - Tried on this branch, with unready pipeline I had the following message, continued with default behavior ``` Pipeline 101237294 skipped: jobs not passed: packaging/agent_suse-arm64-a7-fips (running), packaging/agent_rpm-arm64-a7-fips (running), packaging/agent_suse-arm64-a7 (running), packaging/agent_rpm-arm64-a7 (running), packaging/agent_oci (created), packaging/agent_deb-arm64-a7-fips (running), packaging/agent_deb-arm64-a7 (running), deploy_packages/deploy_ddot_oci (manual), deploy_packages/deploy_installer_oci (manual), deploy_packages/deploy_agent_oci (created), deploy_packages/qa_installer_script_linux (manual) No pipeline with passing packaging and deploy_packages stages found for commit 1dfa6245, skipping pipeline auto-detection ``` Once the pipeline is ready, got ``` Pipeline ID: 101251448 ``` ### Additional Notes - Requires a `GITLAB_TOKEN` env var with `read_api` scope for the GitLab API calls; if absent, a warning is printed and the task continues without auto-detection - `skipped` jobs are counted as passing (rules may exclude certain platforms/architectures) Co-authored-by: paola.ducolin <[email protected]>
1 parent a09fc4d commit 88d4c44

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

tasks/new_e2e_tests.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,33 @@ def run(
331331
parsed_params["ddagent:imagePullRegistry"] += ",376334461865.dkr.ecr.us-east-1.amazonaws.com"
332332
parsed_params["ddagent:imagePullUsername"] += ",AWS"
333333

334+
# Auto-detect pipeline ID and commit SHA for local runs if not already set
335+
if "E2E_PIPELINE_ID" not in os.environ:
336+
print(
337+
color_message(
338+
"E2E_PIPELINE_ID is not set. The E2E job you are running may require build and packaging "
339+
"jobs to have completed in the pipeline (e.g. container images, deb/rpm packages, OCI deploys). "
340+
"Check the `needs:` of your target job in .gitlab/test/e2e/e2e.yml and ensure those jobs "
341+
"have run on your branch before triggering the E2E job.",
342+
"yellow",
343+
)
344+
)
345+
commit_sha = get_commit_sha(ctx)
346+
short_commit_sha = get_commit_sha(ctx, short=True)
347+
print(color_message(f"Auto-detecting pipeline for commit {short_commit_sha}...", "blue"))
348+
pipeline_id = _find_pipeline_for_commit_sha(ctx, commit_sha)
349+
if pipeline_id:
350+
print(color_message(f"Auto-detected pipeline {pipeline_id} for commit {short_commit_sha}", "blue"))
351+
env_vars["E2E_PIPELINE_ID"] = pipeline_id
352+
env_vars["E2E_COMMIT_SHA"] = short_commit_sha
353+
else:
354+
print(
355+
color_message(
356+
f"No pipeline with passing packaging and deploy_packages stages found for commit {short_commit_sha}, skipping pipeline auto-detection",
357+
"yellow",
358+
)
359+
)
360+
334361
for param in configparams:
335362
parts = param.split("=", 1)
336363
if len(parts) != 2:
@@ -1168,6 +1195,66 @@ def _find_recent_successful_pipeline(ctx: Context, branch: str | None = None) ->
11681195
return None
11691196

11701197

1198+
def _find_pipeline_for_commit_sha(ctx: Context, commit_sha: str) -> str | None:
1199+
"""
1200+
Find the most recent pipeline for a given commit SHA where stages
1201+
'packaging' and 'deploy_packages' have all jobs successfully completed (success or skipped).
1202+
Searches by branch ref and matches on SHA, as GitLab's sha filter is unreliable.
1203+
Returns pipeline_id or None if not found.
1204+
"""
1205+
required_stages = {"packaging", "deploy_packages"}
1206+
1207+
try:
1208+
token = os.environ.get('GITLAB_TOKEN')
1209+
repo = get_gitlab_repo(token=token)
1210+
1211+
branch = get_current_branch(ctx)
1212+
pipelines = repo.pipelines.list(ref=branch, per_page=20, order_by='updated_at', get_all=False)
1213+
for pipeline in pipelines:
1214+
if not pipeline.sha.startswith(commit_sha) and not commit_sha.startswith(pipeline.sha):
1215+
continue
1216+
jobs = pipeline.jobs.list(get_all=True)
1217+
1218+
stage_jobs: dict[str, list] = {}
1219+
for job in jobs:
1220+
if job.stage in required_stages:
1221+
stage_jobs.setdefault(job.stage, []).append(job)
1222+
1223+
# All required stages must be present
1224+
if not required_stages.issubset(stage_jobs.keys()):
1225+
missing = required_stages - stage_jobs.keys()
1226+
print(
1227+
f"Pipeline {pipeline.id} skipped: missing stages {missing}",
1228+
file=sys.stderr,
1229+
)
1230+
continue
1231+
1232+
# All jobs in required stages must have passed (success, skipped, or manual/not triggered)
1233+
failed_jobs = [
1234+
f"{job.stage}/{job.name} ({job.status})"
1235+
for stage in required_stages
1236+
for job in stage_jobs[stage]
1237+
if job.status not in ("success", "skipped", "manual")
1238+
]
1239+
if failed_jobs:
1240+
print(
1241+
f"Pipeline {pipeline.id} skipped: jobs not passed: {', '.join(failed_jobs)}",
1242+
file=sys.stderr,
1243+
)
1244+
continue
1245+
1246+
return str(pipeline.id)
1247+
1248+
return None
1249+
except Exception as e:
1250+
print(f"Warning: Could not query GitLab for pipelines for commit {commit_sha[:8]}: {e}")
1251+
if 'GITLAB_TOKEN' not in os.environ:
1252+
print(
1253+
"No GITLAB_TOKEN environment variable found, set it with a GitLab Personal Access Token (read_api scope)"
1254+
)
1255+
return None
1256+
1257+
11711258
def _find_local_msi_build(pkg: str | None = None) -> str | None:
11721259
"""
11731260
Find a local MSI build in the omnibus/pkg directory.

0 commit comments

Comments
 (0)