mercury-agent 0.4.22 → 0.4.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/bugs/registry-pull-no-local-fallback.md +168 -0
- package/package.json +1 -1
- package/src/agent/container-entry.ts +1021 -967
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Bug: mercury run fails when registry pull fails but local build exists
|
|
2
|
+
|
|
3
|
+
**Severity:** P1 — blocks users who build locally but have a registry image configured
|
|
4
|
+
**Introduced in:** 0.4.22 (commit 75e8e71)
|
|
5
|
+
**File:** `src/cli/mercury.ts`, `runAction()` (~line 187)
|
|
6
|
+
|
|
7
|
+
## Symptom
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
$ mercury build # succeeds → mercury-agent:latest exists locally
|
|
11
|
+
$ mercury run
|
|
12
|
+
Image 'ghcr.io/avishai-tsabari/mercury-agent:latest' not found locally, pulling...
|
|
13
|
+
Error response from daemon: unauthorized
|
|
14
|
+
|
|
15
|
+
Error: Failed to pull 'ghcr.io/avishai-tsabari/mercury-agent:latest'.
|
|
16
|
+
If this is a private registry, authenticate first:
|
|
17
|
+
docker login ghcr.io
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The user has a working local image (`mercury-agent:latest`) from `mercury build`,
|
|
21
|
+
but `mercury run` exits with an error because the configured registry image
|
|
22
|
+
can't be pulled (private registry, no auth, offline, etc.).
|
|
23
|
+
|
|
24
|
+
## Root cause
|
|
25
|
+
|
|
26
|
+
The 0.4.22 change replaced the local-fallback logic with auto-pull. The old
|
|
27
|
+
code tried `mercury-agent:latest` as a fallback when the configured image
|
|
28
|
+
wasn't found. The new code attempts `docker pull` and hard-exits on failure —
|
|
29
|
+
it never checks whether a locally built image exists.
|
|
30
|
+
|
|
31
|
+
### Before (0.4.21)
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
configured image not found?
|
|
35
|
+
→ try mercury-agent:latest locally
|
|
36
|
+
→ found? use it (with warning)
|
|
37
|
+
→ not found? error: pull or build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### After (0.4.22)
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
configured image not found?
|
|
44
|
+
→ is registry image? attempt pull
|
|
45
|
+
→ pull fails? hard exit ← BUG: should fall back to local
|
|
46
|
+
→ not registry? error: run mercury build
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Fix
|
|
50
|
+
|
|
51
|
+
After a failed pull of a registry image, check if `mercury-agent:latest`
|
|
52
|
+
exists locally before giving up. If it does, use it with a warning.
|
|
53
|
+
|
|
54
|
+
### Implementation (lines ~187–213 of `src/cli/mercury.ts`)
|
|
55
|
+
|
|
56
|
+
Replace the current block:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
if (imageCheck.status !== 0) {
|
|
60
|
+
const isRegistryImage = imageName.includes("/");
|
|
61
|
+
if (isRegistryImage) {
|
|
62
|
+
console.log(`Image '${imageName}' not found locally, pulling...`);
|
|
63
|
+
const pull = spawnSync("docker", ["pull", imageName], {
|
|
64
|
+
stdio: "inherit",
|
|
65
|
+
});
|
|
66
|
+
if (pull.signal) {
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (pull.status !== 0) {
|
|
70
|
+
const firstSegment = imageName.split("/")[0];
|
|
71
|
+
const registry = firstSegment.includes(".")
|
|
72
|
+
? firstSegment
|
|
73
|
+
: "docker.io";
|
|
74
|
+
console.error(`\nError: Failed to pull '${imageName}'.`);
|
|
75
|
+
console.error(
|
|
76
|
+
"If this is a private registry, authenticate first:\n" +
|
|
77
|
+
` docker login ${registry}`,
|
|
78
|
+
);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
console.error(`Error: Container image '${imageName}' not found.`);
|
|
83
|
+
console.error("Run 'mercury build' to build it.");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
With:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
if (imageCheck.status !== 0) {
|
|
93
|
+
const isRegistryImage = imageName.includes("/");
|
|
94
|
+
let resolved = false;
|
|
95
|
+
|
|
96
|
+
if (isRegistryImage) {
|
|
97
|
+
console.log(`Image '${imageName}' not found locally, pulling...`);
|
|
98
|
+
const pull = spawnSync("docker", ["pull", imageName], {
|
|
99
|
+
stdio: "inherit",
|
|
100
|
+
});
|
|
101
|
+
if (pull.signal) {
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
if (pull.status === 0) {
|
|
105
|
+
resolved = true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Fallback: if the configured image isn't available (pull failed, not a
|
|
110
|
+
// registry image, or never pulled), try the local build tag.
|
|
111
|
+
if (!resolved) {
|
|
112
|
+
const localTag = "mercury-agent:latest";
|
|
113
|
+
if (imageName !== localTag) {
|
|
114
|
+
const localCheck = spawnSync("docker", ["image", "inspect", localTag], {
|
|
115
|
+
stdio: "pipe",
|
|
116
|
+
});
|
|
117
|
+
if (localCheck.status === 0) {
|
|
118
|
+
console.log(
|
|
119
|
+
`\nℹ️ Using locally built ${localTag} (configured image unavailable)\n`,
|
|
120
|
+
);
|
|
121
|
+
process.env.MERCURY_AGENT_IMAGE = localTag;
|
|
122
|
+
resolved = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!resolved) {
|
|
128
|
+
if (isRegistryImage) {
|
|
129
|
+
const firstSegment = imageName.split("/")[0];
|
|
130
|
+
const registry = firstSegment.includes(".")
|
|
131
|
+
? firstSegment
|
|
132
|
+
: "docker.io";
|
|
133
|
+
console.error(`\nError: Failed to pull '${imageName}'.`);
|
|
134
|
+
console.error(
|
|
135
|
+
"If this is a private registry, authenticate first:\n" +
|
|
136
|
+
` docker login ${registry}\n` +
|
|
137
|
+
"Or build locally:\n" +
|
|
138
|
+
" mercury build",
|
|
139
|
+
);
|
|
140
|
+
} else {
|
|
141
|
+
console.error(`Error: Container image '${imageName}' not found.`);
|
|
142
|
+
console.error("Run 'mercury build' to build it.");
|
|
143
|
+
}
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Behavior after fix
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
configured image not found?
|
|
153
|
+
→ is registry image? attempt pull
|
|
154
|
+
→ pull succeeds? use it ✓
|
|
155
|
+
→ pull fails? continue to fallback
|
|
156
|
+
→ try mercury-agent:latest locally
|
|
157
|
+
→ found? use it (with info message) ✓
|
|
158
|
+
→ not found? error with both suggestions (login + build) ✓
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## How to verify
|
|
162
|
+
|
|
163
|
+
1. Build locally: `mercury build`
|
|
164
|
+
2. Ensure no GHCR auth: `docker logout ghcr.io`
|
|
165
|
+
3. Set `.env` to `MERCURY_AGENT_IMAGE=ghcr.io/avishai-tsabari/mercury-agent:latest`
|
|
166
|
+
4. Run `mercury run` — should fall back to local image with info message
|
|
167
|
+
5. Remove local image: `docker rmi mercury-agent:latest`
|
|
168
|
+
6. Run `mercury run` — should error with both `docker login` and `mercury build` suggestions
|