elastic / elastic/ai-github-actions
[autonomy-atomicity] Makefile compiler bootstrap writes shared binaries non-atomically
- Dominant language
- Python
- Stars
- 11
- Forks
- 16
- Avg merge
- 22h 9m
- Merged PRs (30d)
- 31
Description
## Autonomy / Atomicity Findings
### 1. Shared gh-aw compiler binaries are updated in place during `make compile`
**Category:** Global state / Config hotspot
**File(s):** `Makefile`
**Problem:**
`make compile` depends on `setup-gh-aw` and `setup-gh-aw-compat`, then immediately executes the shared binaries from the repository-local `.bin/` directory. The release install path downloads directly into `.bin/gh-aw` and `.bin/gh-aw-compat`, and the non-release path writes/moves into the same shared paths before updating the corresponding version files.
Evidence:
- `Makefile:29-60` defines `download-file` and `install-gh-aw-from-release`; the release helper writes directly to the output path passed by the caller.
- `Makefile:140-147` creates `.bin`, checks `.bin/gh-aw` plus `.bin/.gh-aw-version`, then calls `install-gh-aw-from-release` with `.bin/gh-aw` as the final output path and writes `.bin/.gh-aw-version` afterward.
- `Makefile:155-160` installs non-release builds with `GOBIN="$(CURDIR)/.bin" go install ./cmd/gh-aw`, then writes `.bin/.gh-aw-version` afterward.
- `Makefile:166-187` repeats the same shared-path pattern for `.bin/gh-aw-compat` and `.bin/.gh-aw-compat-version`.
- `Makefile:193-199` then runs `.bin/gh-aw compile` and `.bin/gh-aw-compat compile` from those same shared paths.
When two agents or developers run `make compile` in the same checkout during a version bump or a cold bootstrap, both invocations can write the same compiler path concurrently, or one invocation can execute a binary while another invocation is replacing it. That creates a subtle, workspace-local race that is hard to diagnose and can make otherwise independent workflow changes fail or produce inconsistent generated output.
**Suggested fix:**
Make compiler bootstrap atomic and isolated. Install each compiler into a versioned temporary path under `.bin/` (for example `.bin/gh-aw-v0.80.9.tmp.`), verify it, then atomically `mv` it into a versioned final path or update a symlink under a `flock`-protected lock. Run `make compile` against the versioned executable path selected for that invocation, and update `.bin/.gh-aw-version` only after the executable is fully installed.
Duplicate check: this is distinct from the existing autonomy findings for the runtime setup fragment (#897), Makefile actionlint whitelist (#1319), fixed quick-setup branch name (#806), dogfood registries (#683), and duplicated workflow registries (#777). The other candidates from this run were not filed because the CI path-filter issue is already tracked by #1221 and the docs catalog/nav registry overlaps a prior finding (#560).
## Suggested Actions
- [ ] Install `gh-aw` and `gh-aw-compat` through versioned temporary files instead of writing directly to `.bin/gh-aw*`.
- [ ] Protect compiler installation/version-file updates with a lock or atomic symlink swap.
- [ ] Have `make compile` execute the resolved versioned compiler path for the current invocation instead of a mutable shared path.
---
[What is this?](https://ela.st/github-ai-tools) | [From workflow: Trigger Autonomy Atomicity Analyzer](https://github.com/elastic/ai-github-actions/actions/runs/28672904288)
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
Contributor guide
Assessment
This issue has not been assessed yet.