diff --git a/.github/actions/setup-dev-container/action.yml b/.github/actions/setup-dev-container/action.yml index 610ad770ff..481d955516 100644 --- a/.github/actions/setup-dev-container/action.yml +++ b/.github/actions/setup-dev-container/action.yml @@ -45,7 +45,7 @@ runs: - name: Install the Dev Container CLI shell: bash - run: npm install -g @devcontainers/cli@0.49.0 + run: npm install -g @devcontainers/cli@0.69.0 - name: Start the dev container shell: bash diff --git a/.github/workflows/build-devcontainer-image.yml b/.github/workflows/build-devcontainer-image.yml index bd703b3a3c..374925428d 100644 --- a/.github/workflows/build-devcontainer-image.yml +++ b/.github/workflows/build-devcontainer-image.yml @@ -66,7 +66,7 @@ jobs: export DEVCONTAINER_VERSION=${{ steps.prep.outputs.devcontainer_version }} # Build the image - npm install -g @devcontainers/cli + npm install -g @devcontainers/cli@0.69.0 devcontainer build \ --image-name "${IMAGE_NAME}:${IMAGE_TAG}" \ --workspace-folder "${WORKSPACE_FOLDER}" diff --git a/.github/workflows/schematic-api-ci.yml b/.github/workflows/schematic-api-ci.yml index 2c5e756e73..2129cb116e 100644 --- a/.github/workflows/schematic-api-ci.yml +++ b/.github/workflows/schematic-api-ci.yml @@ -69,7 +69,7 @@ jobs: ${{ runner.os }}-gradle- - name: Install the Dev Container CLI - run: npm install -g @devcontainers/cli@0.49.0 + run: npm install -g @devcontainers/cli@0.69.0 - name: Start the dev container run: | diff --git a/tools/devcontainers/build-image.sh b/tools/devcontainers/build-image.sh deleted file mode 100755 index beafacef5a..0000000000 --- a/tools/devcontainers/build-image.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -# This script must be run from the folder that includes it. - -devcontainer build \ - --image-name ghcr.io/sage-bionetworks/sage-devcontainer:testing \ - --workspace-folder sage diff --git a/tools/devcontainers/sage/.devcontainer/Dockerfile b/tools/devcontainers/sage/.devcontainer/Dockerfile index b3d23383ce..2b46429dda 100644 --- a/tools/devcontainers/sage/.devcontainer/Dockerfile +++ b/tools/devcontainers/sage/.devcontainer/Dockerfile @@ -1,42 +1,50 @@ -ARG imageVersion=jammy-20240227 +# Base image +ARG imageVersion=jammy-20240808 FROM ubuntu:$imageVersion -# Safer bash scripts with 'set -euxo pipefail' +# Set safer bash scripts SHELL ["/bin/bash", "-euxo", "pipefail", "-c"] -ARG devcontainerVersion="" -ENV DEVCONTAINER_VERSION=${devcontainerVersion} - +# List of build arguments # https://github.com/nektos/act -ARG actVersion="0.2.49" +ARG actVersion="0.2.65" # https://github.com/sharkdp/hyperfine -ARG hyperfineVersion="1.17.0" -# https://github.com/yarnpkg/berry -ARG yarnVersion="3.6.1" +ARG hyperfineVersion="1.18.0" # https://www.npmjs.com/package/@devcontainers/cli -ARG devcontainerCliVersion="0.50.2" +ARG devcontainerCliVersion="0.69.0" # https://pypi.org/project/poetry -ARG poetryVersion="1.8.2" +ARG poetryVersion="1.8.3" # https://docs.posit.co/resources/install-r/#specify-r-version ARG rVersion="4.2.3" # https://aquasecurity.github.io/trivy -ARG trivyVersion="0.44.1" +ARG trivyVersion="0.54.1" # https://github.com/rstudio/renv ARG renvVersion="1.0.0" -# https://www.npmjs.com/package/playwright -ARG playwrightVersion="1.40.1" +# https://nodejs.org/en/about/previous-releases +ARG nodeVersionMajor="20" +# https://pypi.org/project/pipenv/ +ARG pipenvVersion="2024.0.1" # https://github.com/pnpm/pnpm/releases -ARG pnpmVersion="8.7.0" +ARG pnpmVersion="9.9.0" +# List of Python versions separated by spaces +ARG pyenvPythonVersions="3.9.2 3.10.14 3.11.8" # https://github.com/SonarSource/sonar-scanner-cli/releases ARG sonarScannerVersion="5.0.1.3006" # https://github.com/hadolint/hadolint ARG hadolintVersion="2.12.0" +# The version of this dev container image +ARG devcontainerVersion="" +# The username of the non-root user +ARG user="vscode" + +# Set environment variables +ENV DEVCONTAINER_VERSION=${devcontainerVersion} \ + LANG=en_US.UTF-8 \ + LC_ALL=en_US.UTF-8 -# Create the docker group so that we can assign it to the user. -# This is to enable the non-root user to use the command `docker`. -# hadolint ignore=DL3008,DL3013 -RUN groupadd docker \ - && apt-get update -qq -y && export DEBIAN_FRONTEND=noninteractive \ +# Install system packages +# hadolint ignore=DL3008 +RUN apt-get update -qq -y && export DEBIAN_FRONTEND=noninteractive \ && apt-get install --no-install-recommends -qq -y \ ca-certificates curl git bash-completion gnupg2 lsb-release ssh sudo \ python3-pip python3-dev python-is-python3 openjdk-17-jdk \ @@ -53,16 +61,8 @@ RUN groupadd docker \ # Required by Hadolint shellcheck \ # Add Node.js repository - && mkdir -p /etc/apt/keyrings \ - && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ - | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ - && NODE_MAJOR=18 \ - && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \ - | tee /etc/apt/sources.list.d/nodesource.list \ - # Add Hadolint - && curl https://github.com/hadolint/hadolint/releases/download/v${hadolintVersion}/hadolint-Linux-x86_64 -o hadolint \ - && mv hadolint /usr/local/bin/. \ - && chmod +x /usr/local/bin/hadolint \ + && curl -fsSL https://deb.nodesource.com/setup_${nodeVersionMajor}.x -o nodesource_setup.sh \ + && bash nodesource_setup.sh \ # Add GitHub CLI repository && curl -sSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | \ gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg \ @@ -74,69 +74,68 @@ RUN groupadd docker \ # Add hashicorp repository && curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - \ && echo "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list \ - # Install extra packages + # Install additional packages && apt-get update -qq -y \ - && apt-get install --no-install-recommends -qq -y \ - nodejs gh ngrok \ - terraform \ - vault \ + && apt-get install --no-install-recommends -qq -y nodejs gh ngrok terraform vault \ + # Enable corepack + && corepack enable \ # Fix Vault CLI # See https://github.com/hashicorp/vault/issues/10924 && setcap -r /usr/bin/vault \ - # Install Yarn - && corepack enable yarn \ - && corepack prepare "yarn@${yarnVersion}" --activate \ - # Instal pnpm - # && curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=${pnpmVersion} bash - \ - && corepack enable pnpm \ - && corepack prepare "pnpm@${pnpmVersion}" --activate \ - # Install @devcontainers/cli - && npm install -g "@devcontainers/cli@${devcontainerCliVersion}" \ - # Install act - && curl "https://raw.githubusercontent.com/nektos/act/v${actVersion}/install.sh" | bash - \ - # Install hyperfine - && curl -sSL "https://github.com/sharkdp/hyperfine/releases/download/v${hyperfineVersion}/hyperfine_${hyperfineVersion}_amd64.deb" \ - -o /tmp/hyperfine.deb \ - && apt-get install --no-install-recommends -qq -y /tmp/hyperfine.deb \ - && rm -fr /tmp/hyperfine.deb \ - # Install AWS CLI - && curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip \ + # Set up UTF-8 locale + && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen \ + # Install R (must be done before clearing the apt cache) + && curl "https://cdn.rstudio.com/r/ubuntu-2204/pkgs/r-${rVersion}_1_amd64.deb" -o /tmp/r_amd64.deb \ + && gdebi --non-interactive /tmp/r_amd64.deb \ + && rm -fr /tmp/r_amd64.deb \ + && ln -s /opt/R/${rVersion}/bin/R /usr/local/bin/R \ + && ln -s /opt/R/${rVersion}/bin/Rscript /usr/local/bin/Rscript \ + && R -e "options(repos = c(POSIT = \"https://packagemanager.posit.co/all/__linux__/jammy/latest\", CRAN = \"https://mirror.las.iastate.edu/CRAN\")); install.packages(\"renv\", version = \"${renvVersion}\")" \ + # Cleanup + && apt-get -y autoclean \ + && apt-get -y autoremove \ + && rm -rf /var/lib/apt/lists/* + +# Install Poetry +RUN curl -sSL https://install.python-poetry.org | POETRY_HOME=/etc/poetry python3 - --version "${poetryVersion}" \ + && ln -s /etc/poetry/bin/poetry /usr/local/bin/. + +# Install Trivy +RUN curl -fsSL "https://github.com/aquasecurity/trivy/releases/download/v${trivyVersion}/trivy_${trivyVersion}_Linux-64bit.deb" -o /tmp/trivy.deb \ + && dpkg -i /tmp/trivy.deb \ + && rm -fr /tmp/trivy.deb + +# Install act +RUN curl "https://raw.githubusercontent.com/nektos/act/v${actVersion}/install.sh" | bash - + +# Install AWS CLI +RUN curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip \ && unzip awscliv2.zip \ && ./aws/install \ && rm -fr awscliv2.zip ./aws \ # Add AWS Session Manager plugin && curl -fsSL "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o /tmp/session-manager-plugin.deb \ && dpkg -i /tmp/session-manager-plugin.deb \ - && rm -fr /tmp/session-manager-plugin.deb \ - # Install Poetry - && curl -sSL https://install.python-poetry.org | POETRY_HOME=/etc/poetry python3 - --version "${poetryVersion}" \ - && ln -s /etc/poetry/bin/poetry /usr/local/bin/. \ - # Install R - && curl "https://cdn.rstudio.com/r/ubuntu-2204/pkgs/r-${rVersion}_1_amd64.deb" -o /tmp/r_amd64.deb \ - && gdebi --non-interactive /tmp/r_amd64.deb \ - && rm -fr /tmp/r_amd64.deb \ - && ln -s /opt/R/${rVersion}/bin/R /usr/local/bin/R \ - && ln -s /opt/R/${rVersion}/bin/Rscript /usr/local/bin/Rscript \ - && R -e "options(repos = c(POSIT = \"https://packagemanager.posit.co/all/__linux__/jammy/latest\", CRAN = \"https://mirror.las.iastate.edu/CRAN\")); install.packages(\"renv\", version = \"${renvVersion}\")" \ - # Install Trivy - && curl -fsSL "https://github.com/aquasecurity/trivy/releases/download/v${trivyVersion}/trivy_${trivyVersion}_Linux-64bit.deb" -o /tmp/trivy.deb \ - && dpkg -i /tmp/trivy.deb \ - && rm -fr /tmp/trivy.deb \ - # Cleanup - && apt-get -y autoclean \ - && apt-get -y autoremove \ - && rm -rf /var/lib/apt/lists/* \ - && pip install --no-cache-dir pipenv + && rm -fr /tmp/session-manager-plugin.deb -# Setting up a UTF-8 locale -RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen \ - && locale-gen -ENV LANG=en_US.UTF-8 \ - LC_ALL=en_US.UTF-8 +# Install the devcontainer CLI +RUN npm install -g "@devcontainers/cli@${devcontainerCliVersion}" + +# Install Hadolint +RUN curl https://github.com/hadolint/hadolint/releases/download/v${hadolintVersion}/hadolint-Linux-x86_64 -o hadolint \ + && mv hadolint /usr/local/bin/. \ + && chmod +x /usr/local/bin/hadolint + +# Install hyperfine +RUN curl -sSL "https://github.com/sharkdp/hyperfine/releases/download/v${hyperfineVersion}/hyperfine_${hyperfineVersion}_amd64.deb" \ + -o /tmp/hyperfine.deb \ + && apt-get install --no-install-recommends -qq -y /tmp/hyperfine.deb \ + && rm -fr /tmp/hyperfine.deb -ARG user=vscode +# Create non-root user RUN useradd -m $user \ && echo "$user:$user" | chpasswd \ + && groupadd docker \ && usermod -a --groups docker,sudo $user \ && usermod --shell /bin/bash $user \ && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \ @@ -152,9 +151,7 @@ RUN useradd -m $user \ " . ./dev-env.sh" \ " workspace-initialize-env" \ "fi" \ - "" | tee -a "/home/$user/.bashrc" \ - # Set the default version of Yarn - && corepack prepare "yarn@${yarnVersion}" --activate + "" | tee -a "/home/$user/.bashrc" # Install SonarScanner CLI ARG SONAR_SCANNER_HOME=/opt/sonar-scanner @@ -168,23 +165,17 @@ RUN curl https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-s && chown -R ${user}:${user} "${SONAR_SCANNER_HOME}" \ && chmod -R 777 "${SONAR_USER_HOME}" +# Switch to non-root user USER $user -# Install browsers used for e2e testing with Playwright -# Note: The version of Playwright should be the same as the one used by your project (package.json) -RUN npx playwright@${playwrightVersion} install --with-deps \ - chromium \ - firefox \ - webkit \ - # Install pyenv as the user - && curl https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash - +# Install the global version of pnpm +RUN corepack install --global "pnpm@${pnpmVersion}" -# Install Python environments +# Set up Python environments ENV PYENV_ROOT /home/${user}/.pyenv ENV PATH $PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH -RUN pyenv install \ - 3.9.2 \ - 3.10.14 \ - 3.11.8 +RUN pip install --no-cache-dir pipenv==${pipenvVersion} \ + && curl https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash - \ + && pyenv install ${pyenvPythonVersions} CMD ["bash"] \ No newline at end of file diff --git a/tools/devcontainers/sage/.devcontainer/README.md b/tools/devcontainers/sage/.devcontainer/README.md deleted file mode 100644 index e0e0e4b767..0000000000 --- a/tools/devcontainers/sage/.devcontainer/README.md +++ /dev/null @@ -1 +0,0 @@ -https://code.visualstudio.com/docs/remote/devcontainer-cli \ No newline at end of file diff --git a/tools/devcontainers/sage/.devcontainer/devcontainer.json b/tools/devcontainers/sage/.devcontainer/devcontainer.json index 209ea53e6a..99955be6b7 100644 --- a/tools/devcontainers/sage/.devcontainer/devcontainer.json +++ b/tools/devcontainers/sage/.devcontainer/devcontainer.json @@ -1,13 +1,16 @@ { - "name": "Sage Dev Container", - "build": { - "dockerfile": "Dockerfile", - "args": { - "imageVersion": "jammy-20230624", + "name": "Sage Dev Container (Test)", + "build": { + "dockerfile": "Dockerfile", + "args": { + "imageVersion": "jammy-20240808", "devcontainerVersion": "${localEnv:DEVCONTAINER_VERSION}" - } - }, - "remoteUser": "vscode", + } + }, + "remoteUser": "vscode", "shutdownAction": "stopContainer", - "runArgs": ["--name", "sage_devcontainer"] + "runArgs": [ + "--name", + "sage_devcontainer_test" + ] } \ No newline at end of file diff --git a/tools/devcontainers/sage/README.md b/tools/devcontainers/sage/README.md new file mode 100644 index 0000000000..6a934e4167 --- /dev/null +++ b/tools/devcontainers/sage/README.md @@ -0,0 +1,19 @@ +# Sage Dev Container + +Learn how to build and run dev containers with the devcontainer CLI: + +https://code.visualstudio.com/docs/remote/devcontainer-cli + +# Build the image with devcontainer + +```console +devcontainer build \ + --image-name ghcr.io/sage-bionetworks/sage-devcontainer:test \ + --workspace-folder ../sage +``` + +# Build the image with Docker + +```console +docker build -t ghcr.io/sage-bionetworks/sage-devcontainer:test .devcontainer/ +``` \ No newline at end of file