Fix: Install the whole Codex package so codex-code-mode-host sits beside bin/codex
Codex 0.165.0 ships as a package tree and runs bin/codex-code-mode-host, codex-path/ and codex-resources/ relative to itself. The installer verified the full archive but kept only bin/codex, so code mode failed. Keep the whole verified tree, link ~/.local/bin/codex to its bin/codex, and replace the receipted flat install earlier runs left behind once the new tree verifies.
This commit is contained in:
1 parent
86f6e391b7
commit
6c8db4e845
3 files changed
+57
-16
No files matched your search
@@ -77,7 +77,10 @@ matched the `digest` GitHub publishes for that release asset. The installer
|
|||||||
accepts a Codex archive only when `tar -tzf` prints exactly the entries in
|
accepts a Codex archive only when `tar -tzf` prints exactly the entries in
|
||||||
`codex-package.listing`. Both architectures share that listing. 0.165.0 dropped
|
`codex-package.listing`. Both architectures share that listing. 0.165.0 dropped
|
||||||
the bundled `codex-resources/zsh/` and added `codex-resources/voice/`, and the
|
the bundled `codex-resources/zsh/` and added `codex-resources/voice/`, and the
|
||||||
archives grew past 128 MiB, so `CODEX_*_MAX_BYTES` is 256 MiB. To bump Codex,
|
archives grew past 128 MiB, so `CODEX_*_MAX_BYTES` is 256 MiB. The installer keeps the
|
||||||
|
whole verified tree as the version directory and links `~/.local/bin/codex` to
|
||||||
|
its `bin/codex`, because Codex runs `bin/codex-code-mode-host` and reads
|
||||||
|
`codex-path/` and `codex-resources/` relative to itself. To bump Codex,
|
||||||
update `installers.conf`, regenerate the listing with `tar -tzf ARTIFACT`, and
|
update `installers.conf`, regenerate the listing with `tar -tzf ARTIFACT`, and
|
||||||
run `tests/setup/package-provenance-contract`.
|
run `tests/setup/package-provenance-contract`.
|
||||||
|
|
||||||
|
|||||||
@@ -417,20 +417,33 @@ _codex_version_matches() {
|
|||||||
[[ "$output" =~ (^|[^0-9])${version_pattern}([^0-9]|$) ]]
|
[[ "$output" =~ (^|[^0-9])${version_pattern}([^0-9]|$) ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Codex ships as a package tree: bin/codex finds bin/codex-code-mode-host,
|
||||||
|
# codex-path/ and codex-resources/ beside itself, so the version directory keeps
|
||||||
|
# the whole verified tree and the active link points at its bin/codex.
|
||||||
_install_codex() (
|
_install_codex() (
|
||||||
local artifact_arch version_dir target bin_link parent expected_listing member
|
local artifact_arch version_dir target bin_link parent expected_listing member
|
||||||
local stage archive listing staged_binary artifact_digest binary_digest
|
local stage archive listing staged_binary artifact_digest binary_digest
|
||||||
|
local retire_flat=0
|
||||||
stage=""
|
stage=""
|
||||||
trap '[[ -z "$stage" ]] || rm -rf -- "$stage"' EXIT
|
# A retired flat install goes back if activation never happened.
|
||||||
|
trap '[[ -z "$stage" ]] || { [[ -d "$stage/retired" && ! -e "$version_dir" ]] \
|
||||||
|
&& mv -Tn -- "$stage/retired" "$version_dir"; rm -rf -- "$stage"; }' EXIT
|
||||||
trap 'exit 130' INT
|
trap 'exit 130' INT
|
||||||
trap 'exit 143' TERM
|
trap 'exit 143' TERM
|
||||||
_set_artifact_arch || return 1
|
_set_artifact_arch || return 1
|
||||||
version_dir="$HOME/.local/lib/panama/codex/${INSTALLER_PROVENANCE[CODEX_VERSION]}"
|
version_dir="$HOME/.local/lib/panama/codex/${INSTALLER_PROVENANCE[CODEX_VERSION]}"
|
||||||
target="$version_dir/codex"
|
target="$version_dir/bin/codex"
|
||||||
bin_link="$HOME/.local/bin/codex"
|
bin_link="$HOME/.local/bin/codex"
|
||||||
artifact_digest="${INSTALLER_PROVENANCE[CODEX_${artifact_arch}_SHA256]}"
|
artifact_digest="${INSTALLER_PROVENANCE[CODEX_${artifact_arch}_SHA256]}"
|
||||||
binary_digest="${INSTALLER_PROVENANCE[CODEX_${artifact_arch}_BINARY_SHA256]}"
|
binary_digest="${INSTALLER_PROVENANCE[CODEX_${artifact_arch}_BINARY_SHA256]}"
|
||||||
if [[ -e "$version_dir" || -L "$version_dir" ]]; then
|
# Earlier installs of this same reviewed artifact kept only the codex binary
|
||||||
|
# at the top of the version directory, without the helpers it needs. That
|
||||||
|
# directory carries our receipt, so it is replaced once the full tree verifies.
|
||||||
|
if [[ ! -e "$version_dir/bin" && ! -L "$version_dir/bin" ]] \
|
||||||
|
&& _runtime_receipt_matches "$version_dir" "$version_dir/codex" \
|
||||||
|
"$artifact_digest" "$binary_digest"; then
|
||||||
|
retire_flat=1
|
||||||
|
elif [[ -e "$version_dir" || -L "$version_dir" ]]; then
|
||||||
_runtime_receipt_matches "$version_dir" "$target" \
|
_runtime_receipt_matches "$version_dir" "$target" \
|
||||||
"$artifact_digest" "$binary_digest" || return 1
|
"$artifact_digest" "$binary_digest" || return 1
|
||||||
[[ -x "$target" ]] || return 1
|
[[ -x "$target" ]] || return 1
|
||||||
@@ -459,24 +472,24 @@ _install_codex() (
|
|||||||
while IFS= read -r member; do
|
while IFS= read -r member; do
|
||||||
_archive_path_is_safe "$member" || { rm -rf -- "$stage"; return 1; }
|
_archive_path_is_safe "$member" || { rm -rf -- "$stage"; return 1; }
|
||||||
done <<<"$listing"
|
done <<<"$listing"
|
||||||
mkdir -m 0700 "$stage/extract" "$stage/version" \
|
mkdir -m 0700 "$stage/version" \
|
||||||
|| { rm -rf -- "$stage"; return 1; }
|
|| { rm -rf -- "$stage"; return 1; }
|
||||||
tar -xzf "$archive" --no-same-owner --no-same-permissions -C "$stage/extract" \
|
tar -xzf "$archive" --no-same-owner --no-same-permissions -C "$stage/version" \
|
||||||
|| { rm -rf -- "$stage"; return 1; }
|
|| { rm -rf -- "$stage"; return 1; }
|
||||||
_tree_links_stay_inside "$stage/extract" || { rm -rf -- "$stage"; return 1; }
|
_tree_links_stay_inside "$stage/version" || { rm -rf -- "$stage"; return 1; }
|
||||||
_tree_hardlinks_stay_inside "$stage/extract" || { rm -rf -- "$stage"; return 1; }
|
_tree_hardlinks_stay_inside "$stage/version" || { rm -rf -- "$stage"; return 1; }
|
||||||
staged_binary="$stage/extract/bin/codex"
|
staged_binary="$stage/version/bin/codex"
|
||||||
[[ -f "$staged_binary" && ! -L "$staged_binary" && -x "$staged_binary"
|
[[ -f "$staged_binary" && ! -L "$staged_binary" && -x "$staged_binary"
|
||||||
&& "$(sha256sum "$staged_binary" | awk '{ print $1 }')" == "$binary_digest" ]] \
|
&& "$(sha256sum "$staged_binary" | awk '{ print $1 }')" == "$binary_digest" ]] \
|
||||||
|| { rm -rf -- "$stage"; return 1; }
|
|| { rm -rf -- "$stage"; return 1; }
|
||||||
_codex_version_matches "$staged_binary" \
|
_codex_version_matches "$staged_binary" \
|
||||||
|| { rm -rf -- "$stage"; return 1; }
|
|| { rm -rf -- "$stage"; return 1; }
|
||||||
mv -- "$staged_binary" "$stage/version/codex" \
|
|
||||||
|| { rm -rf -- "$stage"; return 1; }
|
|
||||||
_write_runtime_receipt "$stage/version" "$artifact_digest" "$binary_digest" \
|
_write_runtime_receipt "$stage/version" "$artifact_digest" "$binary_digest" \
|
||||||
|| { rm -rf -- "$stage"; return 1; }
|
|| { rm -rf -- "$stage"; return 1; }
|
||||||
_activate_directory_no_replace "$stage/version" "$version_dir" \
|
if (( retire_flat )); then
|
||||||
|| { rm -rf -- "$stage"; return 1; }
|
mv -Tn -- "$version_dir" "$stage/retired" || return 1
|
||||||
|
fi
|
||||||
|
_activate_directory_no_replace "$stage/version" "$version_dir" || return 1
|
||||||
_runtime_receipt_matches "$version_dir" "$target" \
|
_runtime_receipt_matches "$version_dir" "$target" \
|
||||||
"$artifact_digest" "$binary_digest" || { rm -rf -- "$stage"; return 1; }
|
"$artifact_digest" "$binary_digest" || { rm -rf -- "$stage"; return 1; }
|
||||||
_codex_version_matches "$target" || { rm -rf -- "$stage"; return 1; }
|
_codex_version_matches "$target" || { rm -rf -- "$stage"; return 1; }
|
||||||
|
|||||||
@@ -1375,8 +1375,11 @@ grep -qFx 'nvm:alias default 24.20.0' "$test_tmp/cases/node-x86_64/commands.log"
|
|||||||
[[ "$($test_tmp/cases/codex-x86_64/home/.local/bin/codex --version)" == \
|
[[ "$($test_tmp/cases/codex-x86_64/home/.local/bin/codex --version)" == \
|
||||||
'codex-cli 0.165.0' ]] || fail 'x86_64 Codex activation has the wrong version'
|
'codex-cli 0.165.0' ]] || fail 'x86_64 Codex activation has the wrong version'
|
||||||
[[ "$(readlink "$test_tmp/cases/codex-x86_64/home/.local/bin/codex")" == \
|
[[ "$(readlink "$test_tmp/cases/codex-x86_64/home/.local/bin/codex")" == \
|
||||||
"$test_tmp/cases/codex-x86_64/home/.local/lib/panama/codex/0.165.0/codex" ]] \
|
"$test_tmp/cases/codex-x86_64/home/.local/lib/panama/codex/0.165.0/bin/codex" ]] \
|
||||||
|| fail 'Codex did not atomically activate the reviewed version path'
|
|| fail 'Codex did not atomically activate the reviewed version path'
|
||||||
|
[[ -x "$test_tmp/cases/codex-x86_64/home/.local/lib/panama/codex/0.165.0/bin/codex-code-mode-host" \
|
||||||
|
&& -f "$test_tmp/cases/codex-x86_64/home/.local/lib/panama/codex/0.165.0/codex-package.json" ]] \
|
||||||
|
|| fail 'Codex dropped the helpers its package ships beside bin/codex'
|
||||||
|
|
||||||
# Unsupported CPUs stop before curl. RustDesk's reviewed RPM is x86_64-only,
|
# Unsupported CPUs stop before curl. RustDesk's reviewed RPM is x86_64-only,
|
||||||
# so aarch64 is also an intentional, recorded soft failure without a download.
|
# so aarch64 is also an intentional, recorded soft failure without a download.
|
||||||
@@ -1511,7 +1514,7 @@ done
|
|||||||
# Successful updates keep the old version directory and switch only the active
|
# Successful updates keep the old version directory and switch only the active
|
||||||
# symlink after the replacement binary has passed its version check.
|
# symlink after the replacement binary has passed its version check.
|
||||||
for component_spec in 'Bun install_bun .bun/bin/bun .bun/versions/1.4.0/bin/bun' \
|
for component_spec in 'Bun install_bun .bun/bin/bun .bun/versions/1.4.0/bin/bun' \
|
||||||
'Codex install_codex .local/bin/codex .local/lib/panama/codex/0.165.0/codex'; do
|
'Codex install_codex .local/bin/codex .local/lib/panama/codex/0.165.0/bin/codex'; do
|
||||||
read -r component function_name active_relative target_relative <<<"$component_spec"
|
read -r component function_name active_relative target_relative <<<"$component_spec"
|
||||||
name="${component,,}-atomic-update"
|
name="${component,,}-atomic-update"
|
||||||
reset_installer_fixture
|
reset_installer_fixture
|
||||||
@@ -1528,12 +1531,34 @@ for component_spec in 'Bun install_bun .bun/bin/bun .bun/versions/1.4.0/bin/bun'
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Installs before the package-layout fix kept only a receipted flat
|
||||||
|
# 0.165.0/codex. That directory is ours, so the full tree replaces it.
|
||||||
|
name=codex-flat-repair
|
||||||
|
reset_installer_fixture
|
||||||
|
STUB_SEED_OLD=Codex expect_success run_installer_function "$name" install_codex
|
||||||
|
home="$test_tmp/cases/$name/home"
|
||||||
|
flat="$home/.local/lib/panama/codex/0.165.0"
|
||||||
|
rm -rf -- "$flat"
|
||||||
|
mkdir -p -- "$flat"
|
||||||
|
cp "$artifact_root/codex-x86_64.bin" "$flat/codex"
|
||||||
|
chmod +x "$flat/codex"
|
||||||
|
printf 'schema=1\nartifact_sha256=%s\nbinary_sha256=%s\n' \
|
||||||
|
e97c4463d7f146692a955d7b0e1c8cf48f97cd4d616cd45c5dcab2e8d9743316 \
|
||||||
|
c06a67fd8ac76508dc78bd99ce20c9f317b8d568beda59485f3f4134df9962d5 > "$flat/.panama-provenance"
|
||||||
|
ln -sfn "$flat/codex" "$home/.local/bin/codex"
|
||||||
|
STUB_REUSE_CASE=1 expect_success run_installer_function "$name" install_codex
|
||||||
|
[[ "$(readlink "$home/.local/bin/codex")" == "$flat/bin/codex" \
|
||||||
|
&& -x "$flat/bin/codex-code-mode-host" && ! -e "$flat/codex" ]] \
|
||||||
|
|| fail "$name did not replace the flat install with the package tree"
|
||||||
|
[[ ! -s "$test_tmp/cases/$name/softly-failed" ]] || fail "$name recorded a soft failure"
|
||||||
|
assert_no_runtime_staging "$name"
|
||||||
|
|
||||||
# Receipt or executable tampering preserves the directory and leaves an older
|
# Receipt or executable tampering preserves the directory and leaves an older
|
||||||
# active link unchanged. A matching version string is not an attestation.
|
# active link unchanged. A matching version string is not an attestation.
|
||||||
for tamper_spec in \
|
for tamper_spec in \
|
||||||
'Node install_node .nvm/versions/node/v24.20.0 bin/node v24.20.0' \
|
'Node install_node .nvm/versions/node/v24.20.0 bin/node v24.20.0' \
|
||||||
'Bun install_bun .bun/versions/1.4.0 bin/bun 1.4.0' \
|
'Bun install_bun .bun/versions/1.4.0 bin/bun 1.4.0' \
|
||||||
'Codex install_codex .local/lib/panama/codex/0.165.0 codex codex-cli_0.165.0'; do
|
'Codex install_codex .local/lib/panama/codex/0.165.0 bin/codex codex-cli_0.165.0'; do
|
||||||
read -r component function_name target_relative binary_relative version_text <<<"$tamper_spec"
|
read -r component function_name target_relative binary_relative version_text <<<"$tamper_spec"
|
||||||
for tamper_kind in receipt binary; do
|
for tamper_kind in receipt binary; do
|
||||||
name="${component,,}-$tamper_kind-tamper"
|
name="${component,,}-$tamper_kind-tamper"
|
||||||
|
|||||||
Reference in new issue
Block a user