diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 7baa7d1..b190cb2 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -37,15 +37,31 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Build and push - id: docker_build + - name: Build and push (amd64) uses: docker/build-push-action@v6 with: - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 push: ${{ github.event_name == 'push' }} tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max,compression=zstd,oci-mediatypes=true + provenance: false + sbom: false + secrets: | + GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} + + - name: Build and push (arm64) + uses: docker/build-push-action@v6 + with: + platforms: linux/arm64 + push: ${{ github.event_name == 'push' }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max,compression=zstd,oci-mediatypes=true + provenance: false + sbom: false + secrets: | + GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} - name: Generate artifact attestation uses: actions/attest-build-provenance@v2 diff --git a/Dockerfile b/Dockerfile index cd79b19..fa5bb0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,75 +2,106 @@ FROM ubuntu:24.04 ENV LANG="C.UTF-8" ENV HOME=/root +ENV DEBIAN_FRONTEND=noninteractive ### BASE ### RUN apt-get update \ - && apt-get upgrade -y \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - binutils \ - sudo \ - build-essential \ - bzr \ - curl \ - default-libmysqlclient-dev \ - dnsutils \ - gettext \ - git \ - git-lfs \ - gnupg2 \ - inotify-tools \ - iputils-ping \ - jq \ - libbz2-dev \ - libc6 \ - libc6-dev \ - libcurl4-openssl-dev \ - libdb-dev \ - libedit2 \ - libffi-dev \ - libgcc-13-dev \ - libgcc1 \ - libgdbm-compat-dev \ - libgdbm-dev \ - libgdiplus \ - libgssapi-krb5-2 \ - liblzma-dev \ - libncurses-dev \ - libncursesw5-dev \ - libnss3-dev \ - libpq-dev \ - libpsl-dev \ - libpython3-dev \ - libreadline-dev \ - libsqlite3-dev \ - libssl-dev \ - libstdc++-13-dev \ - libunwind8 \ - libuuid1 \ - libxml2-dev \ - libz3-dev \ - make \ - moreutils \ - netcat-openbsd \ - openssh-client \ - pkg-config \ - protobuf-compiler \ - python3-pip \ - ripgrep \ - rsync \ - software-properties-common \ - sqlite3 \ - swig3.0 \ - tk-dev \ - tzdata \ - unixodbc-dev \ - unzip \ - uuid-dev \ - xz-utils \ - zip \ - zlib1g \ - zlib1g-dev \ + && apt-get install -y --no-install-recommends \ + binutils=2.42-* \ + sudo=1.9.* \ + build-essential=12.10* \ + bzr=2.7.* \ + curl=8.5.* \ + default-libmysqlclient-dev=1.1.* \ + dnsutils=1:9.18.* \ + gettext=0.21-* \ + git=1:2.43.* \ + git-lfs=3.4.* \ + gnupg=2.4.* \ + inotify-tools=3.22.* \ + iputils-ping=3:20240117-* \ + jq=1.7.* \ + libbz2-dev=1.0.* \ + libc6=2.39-* \ + libc6-dev=2.39-* \ + libcurl4-openssl-dev=8.5.* \ + libdb-dev=1:5.3.* \ + libedit2=3.1-* \ + libffi-dev=3.4.* \ + libgcc-13-dev=13.3.* \ + libgdbm-compat-dev=1.23-* \ + libgdbm-dev=1.23-* \ + libgdiplus=6.1+dfsg-* \ + libgssapi-krb5-2=1.20.* \ + liblzma-dev=5.6.* \ + libncurses-dev=6.4+20240113-* \ + libnss3-dev=2:3.98-* \ + libpq-dev=16.9-* \ + libpsl-dev=0.21.* \ + libpython3-dev=3.12.* \ + libreadline-dev=8.2-* \ + libsqlite3-dev=3.45.* \ + libssl-dev=3.0.* \ + libstdc++-13-dev=13.3.* \ + libunwind8=1.6.* \ + libuuid1=2.39.* \ + libxml2-dev=2.9.* \ + libz3-dev=4.8.* \ + make=4.3-* \ + moreutils=0.69-* \ + netcat-openbsd=1.226-* \ + openssh-client=1:9.6p1-* \ + pkg-config=1.8.* \ + protobuf-compiler=3.21.* \ + python3=3.12.* \ + python3-pip=24.* \ + ripgrep=14.1.* \ + rsync=3.2.* \ + software-properties-common=0.99.* \ + sqlite3=3.45.* \ + swig3.0=3.0.* \ + tk-dev=8.6.* \ + tzdata=2025b-* \ + unixodbc-dev=2.3.* \ + unzip=6.0-* \ + uuid-dev=2.39.* \ + wget=1.21.* \ + xz-utils=5.6.* \ + zip=3.0-* \ + zlib1g=1:1.3.* \ + zlib1g-dev=1:1.3.* \ + && rm -rf /var/lib/apt/lists/* + +### MISE ### + +RUN install -dm 0755 /etc/apt/keyrings \ + && curl -fsSL https://mise.jdx.dev/gpg-key.pub \ + | gpg --batch --yes --dearmor -o /etc/apt/keyrings/mise-archive-keyring.gpg \ + && chmod 0644 /etc/apt/keyrings/mise-archive-keyring.gpg \ + && echo "deb [signed-by=/etc/apt/keyrings/mise-archive-keyring.gpg] https://mise.jdx.dev/deb stable main" \ + > /etc/apt/sources.list.d/mise.list \ + && apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mise/stable \ + && rm -rf /var/lib/apt/lists/* \ + && echo 'eval "$(mise activate bash)"' >> /etc/profile \ + && mise settings set experimental true \ + && mise settings set override_tool_versions_filenames none \ + && mise settings add idiomatic_version_file_enable_tools "[]" + +ENV PATH=$HOME/.local/share/mise/shims:$PATH + +### LLVM ### + +RUN install -dm 0755 /etc/apt/keyrings \ + && curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \ + | gpg --batch --yes --dearmor -o /etc/apt/keyrings/llvm.gpg \ + && chmod 0644 /etc/apt/keyrings/llvm.gpg \ + && . /etc/os-release \ + && echo "deb [signed-by=/etc/apt/keyrings/llvm.gpg] https://apt.llvm.org/${VERSION_CODENAME}/ llvm-toolchain-${VERSION_CODENAME}-20 main" \ + > /etc/apt/sources.list.d/llvm.list \ + && apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends clang-20 lld-20 lldb-20 llvm-20 \ && rm -rf /var/lib/apt/lists/* ### PYTHON ### @@ -81,23 +112,26 @@ ARG PYTHON_VERSION=3.11.12 # Install pyenv ENV PYENV_ROOT=/root/.pyenv ENV PATH=$PYENV_ROOT/bin:$PATH -RUN git -c advice.detachedHead=0 clone --branch ${PYENV_VERSION} --depth 1 https://github.com/pyenv/pyenv.git "${PYENV_ROOT}" \ +ENV PYTHON_VERSIONS="3.10 3.11.12 3.12 3.13" +RUN git -c advice.detachedHead=0 clone --branch "$PYENV_VERSION" --depth 1 https://github.com/pyenv/pyenv.git "$PYENV_ROOT" \ && echo 'export PYENV_ROOT="$HOME/.pyenv"' >> /etc/profile \ && echo 'export PATH="$$PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH"' >> /etc/profile \ && echo 'eval "$(pyenv init - bash)"' >> /etc/profile \ - && cd ${PYENV_ROOT} && src/configure && make -C src \ - && pyenv install 3.10 3.11.12 3.12 3.13 \ - && pyenv global ${PYTHON_VERSION} -# Install pipx for common global package managers (e.g. poetry) + && cd "$PYENV_ROOT" && src/configure && make -C src \ + && pyenv install $PYTHON_VERSIONS \ + && pyenv global "$PYTHON_VERSION" + + # Install pipx for common global package managers (e.g. poetry) ENV PIPX_BIN_DIR=/root/.local/bin ENV PATH=$PIPX_BIN_DIR:$PATH -RUN apt-get update && apt-get install -y pipx \ +RUN apt-get update && apt-get install -y --no-install-recommends pipx=1.4.* \ && rm -rf /var/lib/apt/lists/* \ - && pipx install poetry uv \ + && pipx install poetry==2.1.* uv==0.7.* \ # Preinstall common packages for each version - && for pyv in $(ls ${PYENV_ROOT}/versions/); do \ - ${PYENV_ROOT}/versions/$pyv/bin/pip install --upgrade pip ruff black mypy pyright isort; \ + && for pyv in "${PYENV_ROOT}/versions/"*; do \ + "${pyv}/bin/pip" install --upgrade pip ruff black mypy pyright isort pytest; \ done + # Reduce the verbosity of uv - impacts performance of stdout buffering ENV UV_NO_PROGRESS=1 @@ -113,120 +147,123 @@ ENV COREPACK_DEFAULT_TO_LATEST=0 ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 ENV COREPACK_ENABLE_AUTO_PIN=0 ENV COREPACK_ENABLE_STRICT=0 -RUN git -c advice.detachedHead=0 clone --branch ${NVM_VERSION} --depth 1 https://github.com/nvm-sh/nvm.git "${NVM_DIR}" \ + +RUN git -c advice.detachedHead=0 clone --branch "$NVM_VERSION" --depth 1 https://github.com/nvm-sh/nvm.git "$NVM_DIR" \ && echo 'source $NVM_DIR/nvm.sh' >> /etc/profile \ && echo "prettier\neslint\ntypescript" > $NVM_DIR/default-packages \ && . $NVM_DIR/nvm.sh \ - && nvm install 18 \ - && nvm install 20 \ - && nvm install 22 \ - && nvm alias default $NODE_VERSION \ - && corepack enable \ - && corepack install -g yarn pnpm npm + # The latest versions of npm aren't supported on node 18, so we install each set differently + && nvm install 18 && nvm use 18 && npm install -g npm@10.9 pnpm@10.12 && corepack enable && corepack install -g yarn \ + && nvm install 20 && nvm use 20 && npm install -g npm@11.4 pnpm@10.12 && corepack enable && corepack install -g yarn \ + && nvm install 22 && nvm use 22 && npm install -g npm@11.4 pnpm@10.12 && corepack enable && corepack install -g yarn \ + && nvm alias default "$NODE_VERSION" ### BUN ### ARG BUN_VERSION=1.2.14 - -ENV BUN_INSTALL=/root/.bun -ENV PATH="$BUN_INSTALL/bin:$PATH" - -RUN mkdir -p "$BUN_INSTALL/bin" \ - && curl -L --fail "https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/bun-linux-x64-baseline.zip" \ - -o /tmp/bun.zip \ - && unzip -q /tmp/bun.zip -d "$BUN_INSTALL/bin" \ - && mv "$BUN_INSTALL/bin/bun-linux-x64-baseline/bun" "$BUN_INSTALL/bin/bun" \ - && chmod +x "$BUN_INSTALL/bin/bun" \ - && rm -rf "$BUN_INSTALL/bin/bun-linux-x64-baseline" /tmp/bun.zip \ - && echo 'export BUN_INSTALL=/root/.bun' >> /etc/profile \ - && echo 'export PATH="$BUN_INSTALL/bin:$PATH"' >> /etc/profile +RUN mise use --global "bun@${BUN_VERSION}" ### JAVA ### -ARG JAVA_VERSION=21 +ARG JAVA_VERSIONS="21 17 11" ARG GRADLE_VERSION=8.14 -ARG GRADLE_DOWNLOAD_SHA256=61ad310d3c7d3e5da131b76bbf22b5a4c0786e9d892dae8c1658d4b484de3caa - -ENV GRADLE_HOME=/opt/gradle -RUN apt-get update && apt-get install -y --no-install-recommends \ - openjdk-${JAVA_VERSION}-jdk \ - && rm -rf /var/lib/apt/lists/* \ - && curl -LO "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" \ - && echo "${GRADLE_DOWNLOAD_SHA256} *gradle-${GRADLE_VERSION}-bin.zip" | sha256sum --check - \ - && unzip gradle-${GRADLE_VERSION}-bin.zip \ - && rm gradle-${GRADLE_VERSION}-bin.zip \ - && mv "gradle-${GRADLE_VERSION}" "${GRADLE_HOME}/" \ - && ln -s "${GRADLE_HOME}/bin/gradle" /usr/bin/gradle +ARG MAVEN_VERSION=3.9.10 +RUN for v in $JAVA_VERSIONS; do mise install "java@${v}"; done \ + && mise use --global "java@${JAVA_VERSIONS%% *}" \ + && mise use --global "gradle@${GRADLE_VERSION}" \ + && mise use --global "maven@${MAVEN_VERSION}" ### SWIFT ### -ARG SWIFT_VERSION=6.1 +ARG SWIFT_VERSIONS="6.1 5.10.1" +RUN for v in $SWIFT_VERSIONS; do mise install "swift@${v}"; done \ + && mise use --global "swift@${SWIFT_VERSIONS%% *}" + +### RUST ### + +ARG RUST_VERSIONS="1.89.0 1.88.0 1.87.0 1.86.0 1.85.1 1.84.1 1.83.0" +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && . "$HOME/.cargo/env" \ + && echo 'source $HOME/.cargo/env' >> /etc/profile \ + && rustup install $RUST_VERSIONS \ + && rustup default ${RUST_VERSIONS%% *} -# Install swift. -RUN mkdir /tmp/swiftly \ - && cd /tmp/swiftly \ - && curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz \ - && tar zxf swiftly-$(uname -m).tar.gz \ - && ./swiftly init --quiet-shell-followup -y \ - && echo '. ~/.local/share/swiftly/env.sh' >> /etc/profile \ - && bash -lc "swiftly install --use ${SWIFT_VERSION}" \ - && rm -rf /tmp/swiftly ### RUBY ### +ARG RUBY_VERSIONS="3.2.3 3.3.8 3.4.4" RUN apt-get update && apt-get install -y --no-install-recommends \ - ruby-full \ - && rm -rf /var/lib/apt/lists/* + libyaml-dev=0.2.* \ + libgmp-dev=2:6.3.* \ + && rm -rf /var/lib/apt/lists/* \ + && for v in $RUBY_VERSIONS; do mise install "ruby@${v}"; done \ + && mise use --global "ruby@${RUBY_VERSIONS%% *}" -### RUST ### +### C++ ### +# gcc is already installed via apt-get above, so these are just additional linters, etc. +RUN pipx install cpplint==2.0.* clang-tidy==20.1.* clang-format==20.1.* cmakelang==0.6.* -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ - sh -s -- -y --profile minimal \ - && . "$HOME/.cargo/env" \ - && rustup show +### BAZEL ### + +ARG TARGETOS +ARG TARGETARCH +ARG BAZELISK_VERSION=v1.26.0 + +RUN curl -L --fail https://github.com/bazelbuild/bazelisk/releases/download/${BAZELISK_VERSION}/bazelisk-${TARGETOS}-${TARGETARCH} -o /usr/local/bin/bazelisk \ + && chmod +x /usr/local/bin/bazelisk \ + && ln -s /usr/local/bin/bazelisk /usr/local/bin/bazel ### GO ### -ARG GO_VERSION=1.23.8 -ARG GO_DOWNLOAD_SHA256=45b87381172a58d62c977f27c4683c8681ef36580abecd14fd124d24ca306d3f +ARG GO_VERSIONS="1.24.3 1.23.8 1.22.12" +ARG GOLANG_CI_LINT_VERSION=2.1.6 # Go defaults GOROOT to /usr/local/go - we just need to update PATH ENV PATH=/usr/local/go/bin:$HOME/go/bin:$PATH -RUN mkdir /tmp/go \ - && cd /tmp/go \ - && curl -O https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz \ - && echo "${GO_DOWNLOAD_SHA256} *go${GO_VERSION}.linux-amd64.tar.gz" | sha256sum --check - \ - && tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz \ - && rm -rf /tmp/go +RUN for v in $GO_VERSIONS; do mise install "go@${v}"; done \ + && mise use --global "go@${GO_VERSIONS%% *}" \ + && mise use --global "golangci-lint@${GOLANG_CI_LINT_VERSION}" -### BAZEL ### +### PHP ### -RUN curl -L --fail https://github.com/bazelbuild/bazelisk/releases/download/v1.26.0/bazelisk-linux-amd64 -o /usr/local/bin/bazelisk \ - && chmod +x /usr/local/bin/bazelisk \ - && ln -s /usr/local/bin/bazelisk /usr/local/bin/bazel - -### LLVM ### +ARG PHP_VERSIONS="8.4 8.3 8.2" +ARG COMPOSER_ALLOW_SUPERUSER=1 RUN apt-get update && apt-get install -y --no-install-recommends \ - git \ - cmake \ - ccache \ - python3 \ - ninja-build \ - nasm \ - yasm \ - gawk \ - lsb-release \ - wget \ - software-properties-common \ - gnupg \ + autoconf=2.71-* \ + bison=2:3.8.* \ + libgd-dev=2.3.* \ + libedit-dev=3.1-* \ + libicu-dev=74.2-* \ + libjpeg-dev=8c-* \ + libonig-dev=6.9.* \ + libpng-dev=1.6.* \ + libpq-dev=16.9-* \ + libzip-dev=1.7.* \ + openssl=3.0.* \ + re2c=3.1-* \ && rm -rf /var/lib/apt/lists/* \ - && bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" + && for v in $PHP_VERSIONS; do mise install "php@${v}"; done \ + && mise use --global "php@${PHP_VERSIONS%% *}" + +### ELIXIR ### + +ARG ERLANG_VERSION=27.1.2 +ARG ELIXIR_VERSION=1.18.3 +RUN mise install "erlang@${ERLANG_VERSION}" "elixir@${ELIXIR_VERSION}-otp-27" \ + && mise use --global "erlang@${ERLANG_VERSION}" "elixir@${ELIXIR_VERSION}-otp-27" ### SETUP SCRIPTS ### COPY setup_universal.sh /opt/codex/setup_universal.sh RUN chmod +x /opt/codex/setup_universal.sh +### VERIFICATION SCRIPT ### + +COPY verify.sh /opt/verify.sh +RUN chmod +x /opt/verify.sh && bash -lc /opt/verify.sh + +### ENTRYPOINT ### + COPY entrypoint.sh /opt/entrypoint.sh RUN chmod +x /opt/entrypoint.sh diff --git a/README.md b/README.md index 2aaf132..8ed871f 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ The Docker image is available at: docker pull ghcr.io/openai/codex-universal:latest ``` +This repository builds the image for both linux/amd64 and linux/arm64. However we only run the linux/amd64 version. +Your installed Docker may support linux/amd64 emulation by passing the `--platform linux/amd64` flag. + The below script shows how can you approximate the `setup` environment in Codex: ```sh @@ -25,6 +28,8 @@ docker run --rm -it \ -e CODEX_ENV_RUST_VERSION=1.87.0 \ -e CODEX_ENV_GO_VERSION=1.23.8 \ -e CODEX_ENV_SWIFT_VERSION=6.1 \ + -e CODEX_ENV_RUBY_VERSION=3.4.4 \ + -e CODEX_ENV_PHP_VERSION=8.4 \ -v $(pwd):/workspace/$(basename $(pwd)) -w /workspace/$(basename $(pwd)) \ ghcr.io/openai/codex-universal:latest ``` @@ -42,14 +47,19 @@ The following environment variables can be set to configure runtime installation | `CODEX_ENV_RUST_VERSION` | Rust version to install | `1.83.0`, `1.84.1`, `1.85.1`, `1.86.0`, `1.87.0` | | | `CODEX_ENV_GO_VERSION` | Go version to install | `1.22.12`, `1.23.8`, `1.24.3` | | | `CODEX_ENV_SWIFT_VERSION` | Swift version to install | `5.10`, `6.1` | | +| `CODEX_ENV_RUBY_VERSION` | Ruby version to install | `3.2.3`, `3.3.8`, `3.4.4` | | +| `CODEX_ENV_PHP_VERSION` | PHP version to install | `8.4`, `8.3`, `8.2` | | + + ## What's included In addition to the packages specified in the table above, the following packages are also installed: -- `ruby`: 3.2.3 - `bun`: 1.2.10 - `java`: 21 - `bazelisk` / `bazel` +- `erlang`: 27.1.2 +- `elixir`: 1.18.3 See [Dockerfile](Dockerfile) for the full details of installed packages. diff --git a/setup_universal.sh b/setup_universal.sh index d35a880..570e28f 100644 --- a/setup_universal.sh +++ b/setup_universal.sh @@ -4,9 +4,11 @@ set -euo pipefail CODEX_ENV_PYTHON_VERSION=${CODEX_ENV_PYTHON_VERSION:-} CODEX_ENV_NODE_VERSION=${CODEX_ENV_NODE_VERSION:-} +CODEX_ENV_RUBY_VERSION=${CODEX_ENV_RUBY_VERSION:-} CODEX_ENV_RUST_VERSION=${CODEX_ENV_RUST_VERSION:-} CODEX_ENV_GO_VERSION=${CODEX_ENV_GO_VERSION:-} CODEX_ENV_SWIFT_VERSION=${CODEX_ENV_SWIFT_VERSION:-} +CODEX_ENV_PHP_VERSION=${CODEX_ENV_PHP_VERSION:-} echo "Configuring language runtimes..." @@ -22,21 +24,28 @@ if [ -n "${CODEX_ENV_PYTHON_VERSION}" ]; then fi if [ -n "${CODEX_ENV_NODE_VERSION}" ]; then - echo "# Node.js: ${CODEX_ENV_NODE_VERSION}" - nvm alias default "${CODEX_ENV_NODE_VERSION}" - nvm use "${CODEX_ENV_NODE_VERSION}" - corepack enable - corepack install -g yarn pnpm npm + current=$(node -v | cut -d. -f1) # ==> v20 + echo "# Node.js: v${CODEX_ENV_NODE_VERSION} (default: ${current})" + if [ "${current}" != "v${CODEX_ENV_NODE_VERSION}" ]; then + nvm alias default "${CODEX_ENV_NODE_VERSION}" + nvm use "${CODEX_ENV_NODE_VERSION}" + corepack enable + fi +fi + +if [ -n "${CODEX_ENV_RUBY_VERSION}" ]; then + current=$(ruby -v | cut -d' ' -f2 | cut -d'p' -f1) # ==> 3.2.3 + echo "# Ruby: ${CODEX_ENV_RUBY_VERSION} (default: ${current})" + if [ "${current}" != "${CODEX_ENV_RUBY_VERSION}" ]; then + mise use --global "ruby@${CODEX_ENV_RUBY_VERSION}" + fi fi if [ -n "${CODEX_ENV_RUST_VERSION}" ]; then current=$(rustc --version | awk '{print $2}') # ==> 1.86.0 echo "# Rust: ${CODEX_ENV_RUST_VERSION} (default: ${current})" if [ "${current}" != "${CODEX_ENV_RUST_VERSION}" ]; then - rustup toolchain install --no-self-update "${CODEX_ENV_RUST_VERSION}" - rustup default "${CODEX_ENV_RUST_VERSION}" - # Pre-install common linters/formatters - # clippy is already installed + rustup default "${CODEX_ENV_RUST_VERSION}" fi fi @@ -44,19 +53,23 @@ if [ -n "${CODEX_ENV_GO_VERSION}" ]; then current=$(go version | awk '{print $3}') # ==> go1.23.8 echo "# Go: go${CODEX_ENV_GO_VERSION} (default: ${current})" if [ "${current}" != "go${CODEX_ENV_GO_VERSION}" ]; then - go install "golang.org/dl/go${CODEX_ENV_GO_VERSION}@latest" - "go${CODEX_ENV_GO_VERSION}" download - # Place new go first in PATH - echo "export PATH=$("go${CODEX_ENV_GO_VERSION}" env GOROOT)/bin:\$PATH" >> /etc/profile - # Pre-install common linters/formatters - golangci-lint --version # Already installed in base image, save us some bootup time + mise use --global "go@${CODEX_ENV_GO_VERSION}" fi fi if [ -n "${CODEX_ENV_SWIFT_VERSION}" ]; then - current=$(swift --version | awk -F'version ' '{print $2}' | awk '{print $1}') # ==> 6.1 + current=$(swift --version | sed -n 's/^Swift version \([0-9]\+\.[0-9]\+\).*/\1/p') # ==> 6.1 echo "# Swift: ${CODEX_ENV_SWIFT_VERSION} (default: ${current})" if [ "${current}" != "${CODEX_ENV_SWIFT_VERSION}" ]; then - swiftly install --use "${CODEX_ENV_SWIFT_VERSION}" + mise use --global "swift@${CODEX_ENV_SWIFT_VERSION}" fi fi + + +if [ -n "${CODEX_ENV_PHP_VERSION}" ]; then + current=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;') + echo "# PHP: ${CODEX_ENV_PHP_VERSION} (default: ${current})" + if [ "${current}" != "${CODEX_ENV_PHP_VERSION}" ]; then + mise use --global "php@${CODEX_ENV_PHP_VERSION}" + fi +fi \ No newline at end of file diff --git a/verify.sh b/verify.sh new file mode 100644 index 0000000..38cabc8 --- /dev/null +++ b/verify.sh @@ -0,0 +1,52 @@ +#!/bin/bash --login + +set -euo pipefail + +echo "Verifying language runtimes ..." + +echo "- Python:" +python3 --version +pyenv versions | sed 's/^/ /' + +echo "- Node.js:" +for version in "18" "20" "22"; do + nvm use --global "${version}" + node --version + npm --version + pnpm --version + yarn --version + npm ls -g +done + +echo "- Bun:" +bun --version + +echo "- Java / Gradle:" +java -version +javac -version +gradle --version | head -n 3 +mvn --version | head -n 1 + +echo "- Swift:" +swift --version + +echo "- Ruby:" +ruby --version + +echo "- Rust:" +rustc --version +cargo --version + +echo "- Go:" +go version + +echo "- PHP:" +php --version +composer --version + +echo "- Elixir:" +elixir --version +erl -version +erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell + +echo "All language runtimes detected successfully."