refactor: switch deployments to the canonical Remote Dev image - #60
Conversation
Summary by CodeRabbit
WalkthroughThe Compose files now use ChangesRemote-dev image compatibility
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@codex review Please review the current head |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/releases.md`:
- Around line 23-25: Align all image-precedence documentation with the Compose
empty-value behavior: in docs/releases.md lines 23-25 state that
REMOTE_DEV_IMAGE takes precedence only when set and non-empty, otherwise falling
back to CODEX_IMAGE; update docs/releases.md line 77 to say CODEX_IMAGE is used
when REMOTE_DEV_IMAGE is unset or empty; replace “unset” with “unset or empty”
in .env.example line 3; and update README.md line 160 and README.es.md line 113
to limit precedence to a set or non-empty REMOTE_DEV_IMAGE.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d958b850-9fa8-4a81-9a7e-834455e1bcfd
📒 Files selected for processing (11)
.env.example.github/workflows/build-amd64.ymlCHANGELOG.mdMakefilePROJECT_STATUS.mdREADME.es.mdREADME.mdcompose/docker-compose.ymlcompose/truenas.ymldocs/releases.mdscripts/test-compose-image-compat.sh
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: build
🧰 Additional context used
📓 Path-based instructions (4)
.github/workflows/**
⚙️ CodeRabbit configuration file
.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.
Files:
.github/workflows/build-amd64.yml
compose/**
⚙️ CodeRabbit configuration file
compose/**: Review Docker Compose files for TrueNAS and generic Docker compatibility.
Flag privileged mode, host networking, Docker socket mounts, overly broad host mounts,
missing authentication, unsafe public bindings and persistence paths that could lose credentials or workspaces.
Files:
compose/docker-compose.ymlcompose/truenas.yml
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.
Files:
docs/releases.mdCHANGELOG.mdPROJECT_STATUS.mdREADME.es.mdREADME.md
scripts/**/*.sh
⚙️ CodeRabbit configuration file
scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.
Files:
scripts/test-compose-image-compat.sh
🔇 Additional comments (9)
compose/docker-compose.yml (1)
3-3: LGTM!compose/truenas.yml (1)
3-3: LGTM!scripts/test-compose-image-compat.sh (1)
1-62: LGTM!CHANGELOG.md (1)
34-43: LGTM!Makefile (1)
15-15: LGTM!.github/workflows/build-amd64.yml (1)
52-52: LGTM!README.md (1)
28-28: LGTM!Also applies to: 53-53, 130-130, 151-159, 162-171
README.es.md (1)
25-25: LGTM!Also applies to: 50-50, 103-112, 114-126
PROJECT_STATUS.md (1)
19-21: LGTM!
| The canonical `remote-dev` package is public and is the deployment default. Generic and TrueNAS Compose use `REMOTE_DEV_IMAGE`, defaulting to `ghcr.io/experience83/remote-dev:edge-amd64`. | ||
|
|
||
| ### Canonical-package bootstrap | ||
|
|
||
| A newly created GHCR package starts with private visibility. After the first workflow run creates `remote-dev`, the maintainer must open that package's settings and change its visibility to **Public** before documentation or Compose defaults point anonymous users at it. Until that one-time action is confirmed, the checked-in Compose examples continue to use the public `codex-remote-dev` compatibility package. | ||
| The `codex-remote-dev` compatibility package and `CODEX_IMAGE` variable remain supported throughout `v0.1.x` and will not be removed before `v0.2.0`. `REMOTE_DEV_IMAGE` takes precedence when both variables are set. A deprecation notice must appear in release notes before removal. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files =="
git ls-files | rg '(^|/)(README(\.es)?\.md|\.env\.example|docs/releases\.md|.*compose.*|docker-compose\.ya?ml|compose\.ya?ml)$' || true
echo
echo "== relevant docs/env lines =="
for f in docs/releases.md README.md README.es.md .env.example; do
if [ -f "$f" ]; then
echo "--- $f ($(wc -l < "$f") lines) ---"
nl -ba "$f" | sed -n '1,120p'
fi
done
echo
echo "== compose/image variable occurrences =="
rg -n "REMOTE_DEV_IMAGE|CODEX_IMAGE|remote-dev|codex-remote-dev|image:" . -S --glob '!node_modules' --glob '!dist' --glob '!build' || true
echo
echo "== docker compose syntax references in repo =="
rg -n '(\$\{[^}]*:-|:-\$\{|-[^:}]+\$\{|\$\{[^}]*#|\$\{[^}]*:?\??[^}]*}\))' . --glob '*compose*.ya?ml' --glob '*.yaml' --glob '*.yml' -S || true
echo
echo "== if compose is present, show relevant image substitutions =="
python3 - <<'PY'
from pathlib import Path
matches=[]
for p in Path('.').rglob('*'):
if p.is_file() and p.name.endswith(('.yml','.yaml','.md','.txt','.lock')):
try:
s=p.read_text(errors='ignore')
except Exception:
continue
if 'REMOTE_DEV_IMAGE' in s or 'CODEX_IMAGE' in s:
matches.append(str(p))
for p in matches:
s=Path(p).read_text(errors='ignore')
if 'images/' in p or 'compose' in p.lower() or p.endswith('.env.example'):
print(f'--- {p} ---')
for i,line in enumerate(s.splitlines(),1):
if 'REMOTE_DEV_IMAGE'在s或'CODEX_IMAGE'在s:
print(f'{i}: {line}')
PYRepository: eXPerience83/remote-dev-containers
Length of output: 482
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== relevant env/readme/release text =="
for f in .env.example README.md README.es.md docs/releases.md; do
if [ -f "$f" ]; then
echo "--- $f ---"
awk '{printf "%-6d %s\n", NR, $0}' "$f"
fi
done
echo
echo "== compose files =="
for f in compose/docker-compose.yml compose/truenas.yml; do
if [ -f "$f" ]; then
echo "--- $f ---"
awk '{printf "%-6d %s\n", NR, $0}' "$f"
fi
done
echo
echo "== exact variable usages =="
grep -RIn -- 'REMOTE_DEV_IMAGE\|CODEX_IMAGE' . || true
echo
echo "== compose image substitution semantics check =="
python3 - <<'PY'
# Deterministic check based on compose variable expansion semantics:
# ${VAR-DEFAULT} substitutes ${VAR} when set and non-empty, else DEFAULT;
# ${VAR:-DEFAULT} substitutes DEFAULT when unset and non-empty.
from pathlib import Path
cases = {
"unset-default": ("REMOTE_DEV_IMAGE", "canonical", "$ ${REMOTE_DEV_IMAGE-canonical}"),
"empty-default": ("", "canonical", "$ ${REMOTE_DEV_IMAGE-canonical}"),
"blank-default": (" x ", "canonical", "$ ${REMOTE_DEV_IMAGE-canonical}"),
"unset-coalesce": ("REMOTE_DEV_IMAGE", "canonical", "$ ${REMOTE_DEV_IMAGE:-canonical}"),
"empty-coalesce": ("", "canonical", "$ ${REMOTE_DEV_IMAGE:-canonical}"),
"blank-coalesce": (" x ", "canonical", "$ ${REMOTE_DEV_IMAGE:-canonical}"),
}
def expand(v, default, use_default_on_blank=True):
if v is None:
return default
if use_default_on_blank and v == "":
return default
return v
for label, (var, default, line) in cases.items():
res = expand(var, default, use_default_on_blank=(label.endswith("-coalesce") or "coalesce" in label))
print(f"{label}: var={var!r}, default={default!r} => {res!r} (line {line})")
print("The ${VAR-default} form only falls back when REMOTE_DEV_IMAGE is unset. docker-compose does treat unset and empty as the same substitution result for this form.")
PYRepository: eXPerience83/remote-dev-containers
Length of output: 41067
Use one empty-value compatibility rule for the image precedence.
The Compose files use ${REMOTE_DEV_IMAGE:-${CODEX_IMAGE:-...}}, so Docker Compose only chooses the canonical image when REMOTE_DEV_IMAGE is set. Unset or empty REMOTE_DEV_IMAGE lets CODEX_IMAGE win before the canonical default. Update the matching compatibility statements.
docs/releases.md#L23-L25: sayREMOTE_DEV_IMAGEtakes precedence when set or non-empty and falls back toCODEX_IMAGEwhen unset or empty.docs/releases.md#L77: note that legacyCODEX_IMAGErolls back only whenREMOTE_DEV_IMAGEis unset or empty..env.example#L3: replace “unset” with “unset or empty”.README.md#L160andREADME.es.md#L113: state precedence only applies whenREMOTE_DEV_IMAGEis set or non-empty.
📍 Affects 4 files
docs/releases.md#L23-L25(this comment)docs/releases.md#L77-L77.env.example#L3-L3README.md#L160-L160README.es.md#L113-L113
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/releases.md` around lines 23 - 25, Align all image-precedence
documentation with the Compose empty-value behavior: in docs/releases.md lines
23-25 state that REMOTE_DEV_IMAGE takes precedence only when set and non-empty,
otherwise falling back to CODEX_IMAGE; update docs/releases.md line 77 to say
CODEX_IMAGE is used when REMOTE_DEV_IMAGE is unset or empty; replace “unset”
with “unset or empty” in .env.example line 3; and update README.md line 160 and
README.es.md line 113 to limit precedence to a set or non-empty
REMOTE_DEV_IMAGE.
Source: Path instructions
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
What changed
ghcr.io/experience83/remote-dev:edge-amd64;REMOTE_DEV_IMAGEinterpolation in both Compose files;CODEX_IMAGEas a lower-priority fallback throughoutv0.1.x;REMOTE_DEV_IMAGEprecedence when both variables are set;.env.example, English/Spanish usage, release guidance, project status and changelog;Compatibility
The exact Compose expression is:
${REMOTE_DEV_IMAGE:-${CODEX_IMAGE:-ghcr.io/experience83/remote-dev:edge-amd64}}Therefore existing
.envfiles containing onlyCODEX_IMAGEcontinue to work without edits. The canonical variable wins only when it is non-empty.CODEX_IMAGEand thecodex-remote-devpackage remain supported through allv0.1.xreleases and will not be removed beforev0.2.0.Scope
This PR changes only deployment image selection and related documentation/tests. It does not rename the
codexservice,container_name, data-root variables, volumes or persistent paths. It does not add the launcher/gateway, additional services or optional agents.Validation
docker compose config --imagesagainst an empty env file;Part of #25. This completes the canonical image/package and deployment-variable naming slice; service topology and persistence migration remain separate later PRs.