Skip to main content

debug-ci

Gophercloud CI: Debug acceptance test failures in GitHub Actions. Download artifacts, analyze Go test output, trace through OpenStack devstack service logs to find root cause.

跳到安装

来源信息

仓库
gophercloud/gophercloud
最近来源活动
2026年9月18日 09:48
检测到的 SKILL.md 语言
英语
星标
1,013
分支
612

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
debug-ci
description
Gophercloud CI: Debug acceptance test failures in GitHub Actions. Download artifacts, analyze Go test output, trace through OpenStack devstack service logs to find root cause.
# Gophercloud CI Failure Debugging Debug failures in the Gophercloud acceptance test suite run via GitHub Actions. ## Prerequisites - `gh` CLI authenticated with access to `gophercloud/gophercloud` - Working directory: the gophercloud repository root ## Overview Gophercloud acceptance tests run Go tests (via `gotestsum --format testname`) against real OpenStack environments deployed with [devstack](https://github.com/gophercloud/devstack-action) in GitHub Actions. Each functional workflow runs against a matrix of OpenStack versions defined in the workflow files under `.github/workflows/functional-*.yaml`. Check the `matrix.include` entries in the relevant workflow to see the current set of versions. When a test fails, the CI uploads devstack logs as artifacts (only on failure). ## Step 1: Identify the Failure Given a CI run URL, PR number, or run ID, identify which job(s) failed and which test(s) failed: ```bash # List jobs and their status gh run view <RUN_ID> --repo gophercloud/gophercloud \ --json jobs --jq '.jobs[] | select(.conclusion == "failure") | {name: .name, conclusion: .conclusion, id: .databaseId}' # Get logs for a specific failed job and find the failing test(s) gh run view <RUN_ID> --repo gophercloud/gophercloud \ --log --job <JOB_ID> 2>&1 | grep -E "FAIL\b" # Get the full test output around a failure (error message follows the FAIL line) gh run view <RUN_ID> --repo gophercloud/gophercloud \ --log --job <JOB_ID> 2>&1 | grep -A5 "FAIL.*Test" # If the run URL is from a PR, find runs for that PR gh run list --repo gophercloud/gophercloud --branch <BRANCH> --limit 5 \ --json databaseId,status,conclusion,name ``` ### Reading gotestsum output Gophercloud uses `gotestsum --format testname`. In a local terminal, failed tests are marked with `✖`, but in `gh run view --log` output the markers are replaced by ANSI-escaped `FAIL` wrapped in GitHub Actions `##[group]` annotations. Key patterns in the CI log output: - `##[group] FAIL internal/acceptance/openstack/db/v1.TestFooBar (0.07s)` — test failed (start of group) - ` foo_test.go:43: <error message>` — the actual error, printed on the line(s) **after** the FAIL line (inside the group block) - `##[endgroup]` — end of the failed test's output block - `FAIL Package internal/acceptance/openstack/...` — package-level failure summary ### Finding the test source Acceptance tests live under `internal/acceptance/openstack/<service>/`. Given a failing test name like `TestServersCreateDestroy`, locate it: ```bash grep -r "func TestServersCreateDestroy" internal/acceptance/ ``` Read the test to understand what OpenStack operations it performs and what assertions it makes. ## Step 2: Download Artifacts Artifacts are uploaded only when tests fail. The naming pattern is: ``` functional-<service>-<openstack_name>-<run_id> ``` For example: `functional-compute-epoxy-12345678901` ```bash # List available artifacts gh api repos/gophercloud/gophercloud/actions/runs/<RUN_ID>/artifacts \ --jq '.artifacts[] | {name: .name, size_in_bytes: .size_in_bytes}' # Download artifacts for a specific job gh run download <RUN_ID> --repo gophercloud/gophercloud \ --name functional-<service>-<openstack_name>-<RUN_ID> --dir /tmp/ci-artifacts ``` ### Artifact Contents The `script/collectlogs` script collects the following on failure: | File | Description | |---|---| | `journal.log` | Full system journal (`journalctl`) from the runner | | `devstack-services.txt` | Status of all `devstack@*` systemd services | | `<service>.log` | Individual devstack service log (one per running service, see mapping below) | | `free.txt` | Memory usage at time of log collection | | `dpkg-l.txt` | Installed Debian packages | | `pip-freeze.txt` | Python package versions (useful for identifying OpenStack service versions) | | `local.conf` | Devstack configuration used for deployment | ## Step 3: Analyze the Failure ### 3a. Read the Go Test Output 1. Find the failing test function name from the `FAIL` line 2. Read the error message — Gophercloud tests typically print the HTTP response body on failure, which includes the OpenStack error message and request ID 3. Locate the test source under `internal/acceptance/openstack/<service>/` 4. Read the test to understand what it does and what went wrong ### 3b. Trace OpenStack API Errors Gophercloud's test errors usually include: - The HTTP status code (e.g., `404 Not Found`, `409 Conflict`) - The response body with the OpenStack error message - The OpenStack request ID (in the `X-Openstack-Request-Id` header or response body) To trace server-side: ```bash # Find the OpenStack-side processing for a specific request grep "req-<REQUEST_ID>" /tmp/ci-artifacts/<service>.log # Find all errors in a service log grep -i "error\|traceback\|exception" /tmp/ci-artifacts/<service>.log # Find HTTP requests by status code grep "HTTP/1.1" /tmp/ci-artifacts/<service>.log | grep " 4[0-9][0-9]\| 5[0-9][0-9]" ``` ### 3c. Check for Devstack Infrastructure Issues ```bash # Check if any devstack services crashed grep -i "failed\|inactive\|dead" /tmp/ci-artifacts/devstack-services.txt # Check for OOM conditions cat /tmp/ci-artifacts/free.txt # Check for system-level errors (OOM killer, disk full) grep -i "oom\|out of memory\|no space left" /tmp/ci-artifacts/journal.log # Check the devstack configuration cat /tmp/ci-artifacts/local.conf ``` ### 3d. Determine Test Timing Go test output includes timestamps. To correlate with OpenStack logs: 1. Find the test start/end time from the Go test output 2. Search OpenStack service logs within that time window ```bash # Find log entries in a time window (OpenStack logs use HH:MM:SS format) grep "14:38\|14:39\|14:40" /tmp/ci-artifacts/<service>.log | grep -i "error" ``` ## Devstack Service Log Mapping ### Core services (always present in default devstack) | OpenStack Service | Log File | Description | |---|---|---| | Keystone | `keystone.log` | Identity / authentication | | Nova API | `n-api.log` | Compute API | | Nova Compute | `n-cpu.log` | Compute hypervisor | | Nova Scheduler | `n-sch.log` | Compute scheduling | | Nova Conductor | `n-cond.log` | Compute conductor | | Glance API | `g-api.log` | Image service | | Cinder API | `c-api.log` | Block storage API | | Cinder Volume | `c-vol.log` | Block storage volume manager | | Cinder Scheduler | `c-sch.log` | Block storage scheduling | | Cinder Backup | `c-bak.log` | Block storage backup | | Neutron | `q-svc.log` | Network API (present in all networking configurations) | | Placement | `placement-api.log` | Placement API | > **Note:** The `functional-networking` workflow uses OVN (the devstack default) and does **not** run Neutron agents (`q-l3`, `q-dhcp`, `q-meta`, `q-agt`). These agents are only present in workflows that explicitly set `Q_AGENT=openvswitch` (currently `functional-baremetal` and `functional-fwaas_v2`). Per-workflow log files are listed in the table below. ## Workflow Reference | Workflow | Test Path | Key Logs | |---|---|---| | functional-basic | `internal/acceptance/openstack` | `keystone.log`, `g-api.log`, `s-proxy.log` | | functional-baremetal | `internal/acceptance/openstack/baremetal/...` | `ir-api.log`, `ir-cond.log`, `n-api.log` | | functional-blockstorage | `internal/acceptance/openstack/blockstorage/...` | `c-api.log`, `c-vol.log`, `c-sch.log` | | functional-compute | `internal/acceptance/openstack/compute/...` | `n-api.log`, `n-cpu.log`, `n-sch.log` | | functional-container | `internal/acceptance/openstack/container/...` | `zun-api.log`, `zun-compute.log` | | functional-containerinfra | `internal/acceptance/openstack/containerinfra/...` | `magnum-*.log`, `h-api.log` (epoxy only), `h-eng.log` (epoxy only) | | functional-db | `internal/acceptance/openstack/db/...` | `tr-api.log`, `tr-cond.log`, `tr-tmgr.log` | | functional-dns | `internal/acceptance/openstack/dns/...` | `designate-api.log`, `designate-central.log` | | functional-fwaas_v2 | `internal/acceptance/openstack/networking/v2/extensions/fwaas_v2/...` | `q-svc.log`, `q-l3.log`, `q-agt.log` | | functional-identity | `internal/acceptance/openstack/identity/...` | `keystone.log` | | functional-image | `internal/acceptance/openstack/image/...` | `g-api.log` | | functional-keymanager | `internal/acceptance/openstack/keymanager/...` | `barbican-svc.log` | | functional-loadbalancer | `internal/acceptance/openstack/loadbalancer/...` | `o-api.log`, `o-cw.log`, `o-hm.log` | | functional-messaging | `internal/acceptance/openstack/messaging/...` | `zaqar-*.log` | | functional-metric | `internal/acceptance/openstack/metric/...` | `aetos.log`, `ceilometer-*.log` | | functional-networking | `internal/acceptance/openstack/networking/...` | `q-svc.log` | | functional-objectstorage | `internal/acceptance/openstack/objectstorage/...` | `s-proxy.log`, `s-account.log` | | functional-orchestration | `internal/acceptance/openstack/orchestration/...` | `h-api.log`, `h-eng.log` | | functional-placement | `internal/acceptance/openstack/placement/...` | `placement-api.log` | | functional-sharedfilesystems | `internal/acceptance/openstack/sharedfilesystems/...` | `manila-*.log` | | functional-workflow | `internal/acceptance/openstack/workflow/...` | `mistral-api.log`, `mistral-engine.log` | ## Step 4: Common Failure Patterns | Category | Symptoms | Likely Cause | |---|---|---| | Devstack deploy failure | No test output, "Deploy devstack" step failed | OpenStack upstream / devstack bug; check `journal.log` | | Service crash | Tests fail mid-run with `503` or connection refused | Devstack service crashed; check `devstack-services.txt` and `journal.log` | | Timeout | `context deadline exceeded` or 60m test timeout | Resource contention, slow service, or leaked resources from prior test | | 404 Not Found | Resource created then immediately not found | Race condition, wrong endpoint, or version-specific API change | | 409 Conflict | Resource already exists or state conflict | Test cleanup issue or concurrent test interference | | 401 Unauthorized | Authentication or token error | Token expiration (long-running tests), service misconfiguration | | 400 Bad Request | Invalid request body | Gophercloud sending wrong fields, or microversion mismatch | | Microversion not supported | `Version X.Y is not supported by the API` | Test requires a microversion not available on that OpenStack release | | Version-specific failure | Fails only on one OpenStack version (e.g., master but not epoxy) | API behavior change between releases | | OOM | Tests killed, truncated output | Check `free.txt` and `journal.log` for OOM killer | | Disk full | Various I/O errors | Check `journal.log` for "No space left on device" | ## Step 5: Classify the Failure | Category | Description | Action | |---|---|---| | **OpenStack bug** | Devstack service returned unexpected or incorrect behavior | Document; may need upstream report to OpenStack | | **Gophercloud bug** | SDK sends wrong request, mishandles response, or incorrect URL construction | File or fix in gophercloud | | **Test bug** | Wrong assertions, missing setup/cleanup, incorrect environment assumptions | Fix the test | | **Infrastructure flake** | Timeout, OOM, network issue, devstack instability | Document; consider retry or resource tuning | ### Classification Guardrails Before classifying a failure as **Infrastructure flake**, verify: 1. You have **positive evidence** of an infrastructure problem (OOM in `free.txt`, service crash in `devstack-services.txt`, network timeout in `journal.log`) — not just "I can't find another explanation." 2. You have explicitly ruled out **Gophercloud bug** (reviewed the SDK code path), **Test bug** (verified assertions and test setup are correct), and **OpenStack bug** (checked service logs for API-level errors) with specific reasoning for why each doesn't apply. 3. State the specific evidence for your classification — if you cannot point to a concrete log line or metric, reconsider your conclusion. "Unknown" is a valid classification. Do not default to "Infrastructure flake" when uncertain. ## Caveats ### Multiple Failures May Be Independent When multiple tests fail in the same run, they may not be related — each acceptance test is designed to be self-contained. Analyze each failure independently before assuming a common cause. ### File-Filter May Skip Tests Each workflow uses `.github/actions/file-filter` to skip tests when only unrelated files changed. If a workflow shows "No relevant files changed - skipping tests", this is not a failure — the job exits successfully. The filter patterns are defined per-workflow in the `patterns` field. ### Artifacts Only on Failure Log artifacts are uploaded only when the test step fails (`if: failure()`). Successful runs have no artifacts. If you need logs from a successful run, they are only available in the job's stdout via `gh run view --log`. ### Scheduled Runs Functional workflows also run on a schedule (`cron: '0 0 */3 * *'` — every 3 days). Scheduled run failures that don't reproduce on PRs often indicate flaky tests or transient devstack issues. Check the run's `event` field: ```bash gh run view <RUN_ID> --repo gophercloud/gophercloud --json event --jq '.event' ``` ### Falling Back to journal.log for Missing Service Logs If a service's individual log file is unexpectedly absent from the artifacts, its output can still be found in `journal.log`: ```bash grep "devstack@<service>" /tmp/ci-artifacts/journal.log ``` ### OpenStack Version Differences Failures on only one OpenStack version (e.g., `master` but not `epoxy`) may indicate: - A new API behavior or deprecation in that release - A devstack configuration difference - A version-specific bug Check `pip-freeze.txt` in the artifacts to identify exact service versions.
在 GitHub 查看