Skip to content

feat(opencode): complete DeepCode CLI lifecycle - #11

Merged
yuanchenglu merged 27 commits into
developfrom
cli-lifecycle
Jul 30, 2026
Merged

feat(opencode): complete DeepCode CLI lifecycle#11
yuanchenglu merged 27 commits into
developfrom
cli-lifecycle

Conversation

@yuanchenglu

Copy link
Copy Markdown
Owner

Scope

Complete S1-03: unify DeepCode CLI build, artifact naming, verified curl installation, upgrade rollback, and manifest-bounded uninstall behavior.

Problem

The package bin still targeted bin/opencode; compiled artifacts still contained an opencode binary and user-agent; npm postinstall and the legacy publisher retained OpenCode/upstream channels; the verified DeepCode release channel was a fail-closed placeholder; uninstall deleted user data by default instead of preserving it.

Implementation

  • Emit canonical deepcode-<os>-<arch>.<ext> archives containing only deepcode / deepcode.exe.
  • Generate deepcode-manifest.json and deepcode-checksums.txt and refuse publishing unless GH_REPO=yuanchenglu/deepcode.
  • Add a hardcoded DeepCode-owned curl installer with SHA-256 verification, smoke testing, atomic replacement, rollback, idempotent same-version installation, install manifest, and exact shell marker.
  • Add verified GitHub Release lookup/download and atomic upgrade logic; unsupported npm/brew/choco/scoop/AUR/container paths remain fail-closed.
  • Preserve configuration, sessions, cache, and state by default during uninstall; --purge requires a separate confirmation and only targets DeepCode global paths.
  • Remove the legacy OpenCode launcher and add the DeepCode launcher.

User impact

DeepCode can use one owned CLI identity and one verified release/curl lifecycle without contacting anomalyco/OpenCode or third-party package-manager release channels. Upgrade failures restore the previous binary. Normal uninstall preserves user data.

Tests

  • packages/opencode/test/installation/build-contract.test.ts
  • packages/opencode/test/installation/installation.test.ts
  • packages/opencode/test/installation/release.test.ts
  • existing packages/opencode/test/installation/uninstall.test.ts
  • required repository typecheck, Linux/Windows unit, lifecycle, E2E, generated client, and HttpApi workflows

Evidence

Failure baseline and final CI evidence will be recorded under docs/open-source-readiness/evidence/S1-03/ after Actions completes.

Risks

  • Windows curl upgrade remains explicitly disabled for Alpha; Windows build artifacts remain experimental.
  • Release workflow modernization, SBOM/license manifest, and Draft Release creation remain S1-06.
  • Website publication remains blocked on S1-01B/S1-07.

Technical debt

None accepted in this PR. CI failures will be classified before any rerun.

Next task

After S1-03 is merged and Plan/evidence are closed out, re-read the dependency graph and start the next earliest eligible Stage 1 task.

@github-actions

Copy link
Copy Markdown

The following comment was made by an LLM, it may be inaccurate:

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff9d712adb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment on lines +164 to +165
const execPath = path.resolve(options.execPath ?? process.execPath)
if (!isOwnedInstallPath(execPath, execPath)) throw new Error(`${execPath} is not a verified DeepCode curl installation`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require a detected curl install before upgrading

When a package-managed or development binary is invoked with upgrade --method curl, the CLI bypasses the detectedMethod === "unknown" guard, and this ownership check still always succeeds because it derives the allowed root from the same execPath being checked. The upgrade then renames and replaces process.execPath, potentially overwriting a binary under node_modules or even the Bun executable rather than refusing the unsupported installation; validate the .deepcode/bin/deepcode layout independently instead of treating every executable as owned.

Useful? React with 👍 / 👎.

temporary=$(mktemp -d "${TMPDIR:-/tmp}/deepcode-install.XXXXXX")
trap 'rm -rf "$temporary"' EXIT INT TERM

if [ -x "$binary" ] && "$binary" --version 2>/dev/null | grep -Fq "$version"; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compare the complete installed version before skipping

When the requested version is a prefix of the installed version, grep -Fq reports a false match—for example, requesting 1.17.1 while 1.17.13 is installed skips the downgrade and rewrites the manifest as 1.17.1. The same substring check is also used for candidate and post-install verification, so version validation should parse or compare the complete reported version rather than search for a substring.

Useful? React with 👍 / 👎.

Comment on lines +109 to +113
rollback() {
if [ "$replaced" = "1" ] && [ -f "$backup" ]; then
rm -f "$binary"
mv "$backup" "$binary"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove a failed fresh-install binary during rollback

On a first installation, replaced remains 0, so any failure after .deepcode.new is moved into place—such as installed-binary verification or manifest creation failing—runs this rollback without deleting the newly installed binary. The installer exits with an error but leaves a partial, potentially unverified installation at ~/.deepcode/bin/deepcode; the rollback needs to remove the binary when there was no previous installation to restore.

Useful? React with 👍 / 👎.

Comment on lines +57 to +58
{ os: "linux", arch: "arm64" },
{ os: "linux", arch: "x64", avx2: false },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject or provide artifacts for musl Linux hosts

On Alpine and other musl-based Linux systems, the installer accepts the host based only on uname, but the sole Linux artifacts are now compiled for glibc (bun-linux-* with FFF_LIBC and OPENTUI_LIBC set to glibc). Those users download a nominally supported asset that cannot execute and fail only at the smoke test; either retain musl-compatible artifacts or detect musl and report it as unsupported before downloading.

Useful? React with 👍 / 👎.

@yuanchenglu
yuanchenglu merged commit 08788ae into develop Jul 30, 2026
3 of 7 checks passed
@yuanchenglu
yuanchenglu deleted the cli-lifecycle branch July 30, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant