Skip to content

Codespace vigilant yodel qp7pgx6r5q93xp59 - #1

Open
khulnasoft-bot wants to merge 11 commits into
FortiShield:mainfrom
khulnasoft-bot:codespace-vigilant-yodel-qp7pgx6r5q93xp59
Open

Codespace vigilant yodel qp7pgx6r5q93xp59#1
khulnasoft-bot wants to merge 11 commits into
FortiShield:mainfrom
khulnasoft-bot:codespace-vigilant-yodel-qp7pgx6r5q93xp59

Conversation

@khulnasoft-bot

@khulnasoft-bot khulnasoft-bot commented Jul 25, 2026

Copy link
Copy Markdown

What kind of change does this PR introduce?

  • Bugfix
  • New Feature
  • Feature Improvement
  • Refactoring
  • Documentation
  • Other, please describe:

Description:

Checklist:

  • I have read the CONTRIBUTING document.
  • My changes don't require a change to the documentation, or if they do, I've added all required information.

Summary by Sourcery

Optimize Docker build performance and GPU image setup, introduce BuildKit/buildx support and Makefile helpers, and modernize CI workflows and editor tooling.

New Features:

  • Add Docker BuildKit/buildx support with optional registry cache configuration via new CLI flags.
  • Introduce a Makefile with standard build, test, release, and CI targets for all workspace flavors.

Enhancements:

  • Refactor main and GPU Dockerfiles to use multi-stage builds, NVIDIA CUDA base images, and extensive cache mounts for apt, pip, conda, and npm.
  • Split Python dependency requirements into stable base and dev-specific files for improved layer caching and faster incremental builds.
  • Improve clean-layer and fix-permissions behavior for safer, more robust cleanup and permission handling.
  • Update VS Code Server and desktop installation scripts to use newer versions and simpler, prebuilt package installs.
  • Add Python dependencies setup to the GitHub build-environment action image to support the build tooling.

CI:

  • Simplify build-pipeline workflow by inlining inputs, upgrading checkout actions, and wiring build arguments directly from inputs or secrets.
  • Update release-pipeline workflow to use the latest checkout action versions for reliability and performance.

Documentation:

  • Add DOCKER_BUILD_IMPROVEMENTS.md documenting the new build performance optimizations, cache usage, and recommended workflows.

Tests:

  • Make container-based test runs more robust by cleaning up any existing test containers and ensuring containers are always removed even on failure.

Summary by CodeRabbit

  • New Features

    • Added streamlined commands for building, testing, linting, publishing, and releasing workspace images across supported flavors.
    • Added optional BuildKit/Buildx support with configurable build caching for faster repeat builds.
    • Improved GPU image setup using an NVIDIA CUDA base image and runtime configuration.
  • Bug Fixes

    • Improved test-container cleanup to prevent conflicts and ensure cleanup after failures.
    • Updated VS Code and VS Code Server installation flows.
  • Documentation

    • Added guidance on Docker build optimizations, caching, usage examples, and verification.

gitworkflows and others added 11 commits August 17, 2024 22:03
Signed-off-by: gitworkflows <118260833+gitworkflows@users.noreply.github.com>
- Add Makefile with targets for build, test, push, release
- Support BUILDX, CACHE_FROM, CACHE_TO variables
- CI targets: ci-build, ci-test, ci-push
- Development shortcuts: dev-build-full, dev-build-gpu
- Add DOCKER_BUILD_IMPROVEMENTS.md documentation
- Update requirements-base.txt and requirements-dev.txt with unique packages
@sourcery-ai

sourcery-ai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors Docker build pipeline for ml-workspace to use BuildKit/caching, introduces a conda bootstrap stage and NVIDIA CUDA base image for GPU flavor, adds buildx-aware build tooling (Makefile, build.py) and CI workflow tweaks, and updates VS Code tooling and cleanup scripts for more robust, faster builds.

Sequence diagram for build.py using buildx and running tests

sequenceDiagram
    actor Developer
    participant build_py as build_py
    participant docker_cli as docker_cli
    participant docker_daemon as docker_daemon
    participant tests as pytest_container_tests

    Developer->>build_py: python3 build.py --make --buildx --flavor full
    build_py->>build_py: parse_arguments
    build_py->>build_py: _build_with_buildx
    build_py->>docker_cli: docker buildx build (with cache-from, cache-to)
    docker_cli->>docker_daemon: build image ml-workspace:VERSION
    docker_daemon-->>docker_cli: image built
    docker_cli-->>build_py: completed_process
    build_py->>docker_daemon: run container workspace-test-full
    build_py->>tests: build_utils.run pytest /resources/tests
    tests-->>build_py: completed_process
    build_py->>docker_daemon: remove container workspace-test-full
    build_py->>Developer: exit_process(0 or 1) based on tests
Loading

File-Level Changes

Change Details Files
Introduce a dedicated conda bootstrap stage and broad use of BuildKit cache mounts to speed up and stabilize the main Docker image build.
  • Add dockerfile syntax directive and new conda-bootstrap stage to pre-install Miniconda with mamba and pip
  • Replace in-place conda installation with COPY from the bootstrap stage
  • Add cache mounts for apt, pip, conda, npm, node-gyp, and temp dirs across RUN instructions
  • Refactor data-science installation to use mamba, adjust channel priority, and split pip requirements into base/dev/minimal/light/full files
  • Improve locale and basic package installation RUN steps to be cache-friendly
Dockerfile
resources/libraries/requirements-base.txt
resources/libraries/requirements-dev.txt
resources/libraries/requirements-minimal.txt
resources/libraries/requirements-light.txt
resources/libraries/requirements-full.txt
Replace the custom CUDA setup for the GPU flavor with an official NVIDIA CUDA base image and add caching/cleanup improvements.
  • Switch GPU Dockerfile base to nvidia/cuda:11.2.2-cudnn8-devel-ubuntu20.04 with BuildKit syntax header
  • Remove manual CUDA, cuDNN, and NCCL installation and apt-pin logic
  • Add cache mounts for apt, pip, and conda plus a small set of extra OS libs for GPU workloads
  • Wire cleanup scripts into the GPU image and simplify environment/labels setup
  • Adjust GPU-specific Python package installation, fixing jax installation command comments
gpu-flavor/Dockerfile
resources/scripts/clean-layer.sh
Enhance build tooling to support buildx/BuildKit with remote cache, add a Makefile, and make container-based tests more robust.
  • Add buildx, cache-from, and cache-to flags plus a _build_with_buildx helper in the main build script
  • Select the correct Dockerfile path for GPU flavor builds and conditionally call buildx vs classic docker build
  • Add helpers to remove any existing test container before running tests and ensure containers are always cleaned up in both builds
  • Apply the same container cleanup logic in the GPU build script
  • Introduce a Makefile with targets for building, testing, pushing, releasing, CI shortcuts, and linting
build.py
gpu-flavor/build.py
Makefile
Update GitHub Actions build and release workflows to use newer checkout actions and simplified inputs, and prepare build-environment image for running the Python build tooling.
  • Simplify build-pipeline workflow env handling by using inputs/secrets directly and upgrade to actions/checkout@v4
  • Set host IP using safer quoting and pass GITHUB_TOKEN explicitly to the composite build-environment action
  • Upgrade release-pipeline workflow to actions/checkout@v4 across jobs
  • Extend the build-environment Dockerfile to install python3-pip and Python build dependencies from a requirements file
.github/workflows/build-pipeline.yml
.github/workflows/release-pipeline.yml
.github/actions/build-environment/Dockerfile
.github/actions/build-environment/build_requirements.txt
build_requirements.txt
Modernize VS Code server/desktop tooling installation scripts for better reliability.
  • Change VS Code Server installation to use a pre-built .deb for a newer code-server version and remove yarn-based global install
  • Switch VS Code desktop install to use the generic Microsoft download URL and safely remove the vscode apt source list only if present
resources/tools/vs-code-server.sh
resources/tools/vs-code-desktop.sh
Document Docker build performance improvements and new build practices.
  • Add a summary document explaining BuildKit/buildx usage, caching strategy, requirements split, and expected performance gains
  • List modified files and usage examples for local and CI builds
DOCKER_BUILD_IMPROVEMENTS.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds Buildx and Makefile orchestration, restructures CPU and GPU Docker images with cache-aware dependency installation, updates container test cleanup, revises CI workflows, and changes VS Code installation scripts.

Changes

Docker build overhaul

Layer / File(s) Summary
Build orchestration and caching
Makefile, build.py, build_requirements.txt, DOCKER_BUILD_IMPROVEMENTS.md
Adds Buildx flags, cache configuration, flavor-aware build/test/release targets, container cleanup, and documentation for the new build flow.
CPU image bootstrap and dependency layers
Dockerfile, resources/libraries/*, resources/scripts/clean-layer.sh
Adds a conda bootstrap stage, BuildKit cache mounts, split requirements files, mamba-based installs, and more tolerant cache cleanup.
GPU image and test lifecycle
gpu-flavor/Dockerfile, gpu-flavor/build.py
Switches to an NVIDIA CUDA base image, configures GPU runtime metadata and caches, and ensures test containers are removed before and after execution.
CI build environment and workflow wiring
.github/actions/build-environment/*, .github/workflows/*
Installs pinned Python build dependencies, upgrades checkout actions, and passes workflow inputs directly to the local build action.
Editor installation updates
resources/tools/vs-code-desktop.sh, resources/tools/vs-code-server.sh
Updates VS Code download and cleanup behavior and replaces the VS Code Server installation path with a fixed deb package.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Makefile
  participant build.py
  participant DockerBuildx
  Makefile->>build.py: Invoke flavor and cache arguments
  build.py->>DockerBuildx: Run docker buildx build
  DockerBuildx-->>build.py: Return build result
Loading

Suggested reviewers: jankalkan

Poem

A rabbit hops through layers bright,
Caches bloom in moonlit light.
Conda rests, the builds take flight,
GPU stars begin to glow,
Clean test burrows close just so.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is generic and does not describe the build, Docker, or workflow changes in the PR. Replace it with a short, specific summary of the main change, such as "Improve Docker build caching and build scripts".
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai 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.

Hey - I've found 1 security issue, 2 other issues, and left some high level feedback:

Security issues:

  • Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'. (link)

General comments:

  • The new gpu-flavor/Dockerfile no longer builds FROM the main workspace image and assumes conda and workspace tooling already exist; this will break all subsequent conda/pip operations unless you reintroduce a base workspace stage or explicitly install the workspace stack in the GPU image.
  • In gpu-flavor/Dockerfile the jax installation line appears corrupt (pip install --# install jax: ... followed by another pip install), which will cause the RUN step to fail; clean this up to a single valid pip command.
  • The updated clean-layer.sh now hardcodes /root/.cache and drops $HOME usage; if this script is ever reused outside root-only build stages it may miss user caches, so consider retaining $HOME-based cleanup or documenting that it is strictly for root builds.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new gpu-flavor/Dockerfile no longer builds FROM the main workspace image and assumes conda and workspace tooling already exist; this will break all subsequent conda/pip operations unless you reintroduce a base workspace stage or explicitly install the workspace stack in the GPU image.
- In gpu-flavor/Dockerfile the jax installation line appears corrupt (`pip install --# install jax: ...` followed by another `pip install`), which will cause the RUN step to fail; clean this up to a single valid pip command.
- The updated clean-layer.sh now hardcodes `/root/.cache` and drops `$HOME` usage; if this script is ever reused outside root-only build stages it may miss user caches, so consider retaining `$HOME`-based cleanup or documenting that it is strictly for root builds.

## Individual Comments

### Comment 1
<location path="gpu-flavor/Dockerfile" line_range="81-82" />
<code_context>
     # cuda111 -> >= 11.1
     pip install --no-cache-dir mxnet-cu112 && \
     # install jax: https://github.com/google/jax#pip-installation
+    pip install --# install jax: https://github.com/google/jax#pip-installation \
     pip install --upgrade jax[cuda111] -f https://storage.googleapis.com/jax-releases/jax_releases.html && \
     # Install pygpu - Required for theano: http://deeplearning.net/software/libgpuarray/
     conda install -y pygpu && \
</code_context>
<issue_to_address>
**issue (bug_risk):** The JAX installation lines contain a malformed `pip install` command that will cause the Docker build to fail.

`pip install --# install jax: ...` is invalid syntax (`--#` is not a valid pip option) and will cause this layer to fail before the real JAX install runs. Remove this stray command or convert it to a shell comment (`# install jax: ...`) so only the actual `pip install --upgrade jax[cuda111] ...` executes.
</issue_to_address>

### Comment 2
<location path="Makefile" line_range="65-66" />
<code_context>
+build:
+	python3 build.py --make $(BUILD_ARGS)
+
+build-minimal:
+	python3 build.py --flavor minimal --make $(BUILD_ARGS)
+
+build-light:
</code_context>
<issue_to_address>
**issue (bug_risk):** Targets like `build-minimal` pass conflicting `--flavor` arguments due to `BUILD_ARGS` also containing `--flavor`.

For `build-minimal`, this expands to `python3 build.py --flavor minimal --make ... --flavor $(FLAVOR)`. With the default `FLAVOR=full`, the last `--flavor` wins and `build-minimal` (and similarly `build-light`, `build-full`, `build-gpu`) actually builds the full flavor. Fix either by removing `--flavor $(FLAVOR)` from `BUILD_ARGS` and setting `--flavor` only in each target, or by keeping `BUILD_ARGS` as-is and overriding `FLAVOR` per target instead of passing an explicit `--flavor` there.
</issue_to_address>

### Comment 3
<location path="build.py" line_range="139" />
<code_context>
    completed_process = subprocess.run(buildx_args, env=env)
</code_context>
<issue_to_address>
**security (python.lang.security.audit.dangerous-subprocess-use-audit):** Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread gpu-flavor/Dockerfile
Comment on lines +81 to 82
pip install --# install jax: https://github.com/google/jax#pip-installation \
pip install --upgrade jax[cuda111] -f https://storage.googleapis.com/jax-releases/jax_releases.html && \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): The JAX installation lines contain a malformed pip install command that will cause the Docker build to fail.

pip install --# install jax: ... is invalid syntax (--# is not a valid pip option) and will cause this layer to fail before the real JAX install runs. Remove this stray command or convert it to a shell comment (# install jax: ...) so only the actual pip install --upgrade jax[cuda111] ... executes.

Comment thread Makefile
Comment on lines +65 to +66
build-minimal:
python3 build.py --flavor minimal --make $(BUILD_ARGS)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Targets like build-minimal pass conflicting --flavor arguments due to BUILD_ARGS also containing --flavor.

For build-minimal, this expands to python3 build.py --flavor minimal --make ... --flavor $(FLAVOR). With the default FLAVOR=full, the last --flavor wins and build-minimal (and similarly build-light, build-full, build-gpu) actually builds the full flavor. Fix either by removing --flavor $(FLAVOR) from BUILD_ARGS and setting --flavor only in each target, or by keeping BUILD_ARGS as-is and overriding FLAVOR per target instead of passing an explicit --flavor there.

Comment thread build.py
env = os.environ.copy()
env["DOCKER_BUILDKIT"] = "1"

completed_process = subprocess.run(buildx_args, env=env)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security (python.lang.security.audit.dangerous-subprocess-use-audit): Detected subprocess function 'run' without a static string. If this data can be controlled by a malicious actor, it may be an instance of command injection. Audit the use of this call to ensure it is not controllable by an external resource. You may consider using 'shlex.escape()'.

Source: opengrep

@coderabbitai coderabbitai 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.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/release-pipeline.yml (1)

121-127: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pin the checked-out release-drafter revision.

This workflow fetches khulnasoft/release-drafter without ref, then executes it guarded by GITHUB_TOKEN. Pin the checkout to a reviewed immutable commit SHA so changes to the repository’s default branch cannot alter release behavior.

Proposed fix
         with:
           repository: khulnasoft/release-drafter
+          ref: <reviewed-immutable-commit-sha>
           path: ./.git/cloned-actions/release-drafter
🤖 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 @.github/workflows/release-pipeline.yml around lines 121 - 127, Pin the
actions/checkout step for khulnasoft/release-drafter to a reviewed immutable
commit SHA by adding the appropriate ref under its with configuration. Keep the
existing repository, checkout path, create-release-draft condition, and local
action usage unchanged.
🧹 Nitpick comments (6)
.github/actions/build-environment/build_requirements.txt (1)

5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Pin the Docker SDK for reproducible builds.

.github/actions/build-environment/build_requirements.txt allows any Docker SDK 6.x release, so resolves can pick different versions between environments. Use the tested exact version, e.g. docker==6.1.3, or lock the build requirements.

🤖 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 @.github/actions/build-environment/build_requirements.txt at line 5, Pin the
Docker SDK dependency in build_requirements.txt to the tested exact version,
such as docker==6.1.3, replacing the current 6.x version range while leaving
other build requirements unchanged.
Makefile (1)

14-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

build-all re-implements the BUILDX/cache-arg logic instead of reusing BUILD_ARGS.

Lines 14-24 already compute buildx/cache flags via ifeq; build-all re-derives the same flags inline with $(if ...), a second implementation of the same logic that can silently drift from BUILD_ARGS over time.

Also applies to: 77-78

🤖 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 `@Makefile` around lines 14 - 24, Update the build-all target to reuse the
existing BUILD_ARGS variable for buildx and cache flags instead of
reconstructing them with inline conditional expressions. Keep the conditional
logic centralized in the BUILD_ARGS definition and remove the duplicated flag
assembly from build-all.
Dockerfile (2)

328-343: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Git clone timeout is fully disabled, not bounded.

http.lowSpeedLimit 0 combined with http.lowSpeedTime 999999 effectively removes git's stall-detection for the pyenv clones. If the network stalls mid-clone, this RUN step (and the build/CI job) can hang indefinitely instead of failing fast, wasting CI minutes with no automatic recovery.

🤖 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 `@Dockerfile` around lines 328 - 343, Bound Git’s network stall detection in
the pyenv installation RUN step by removing the unlimited
http.lowSpeedLimit/http.lowSpeedTime settings and using finite, appropriate
timeout values. Keep the existing pyenv and plugin clone sequence unchanged
while ensuring stalled clones fail rather than hanging indefinitely.

329-330: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Inconsistent sharing=locked on cache mounts.

Only the very first apt cache mounts (lines 14-15, 85-86, 102-103) declare sharing=locked; every later --mount=type=cache in this file (pyenv, pipx, node, supervisor, gui-tools, vnc, data-science) omits it. Without sharing=locked, concurrent builds sharing the same BuildKit cache backend (e.g. CI matrix-building multiple flavors, or make -j) can write to the same apt/conda cache simultaneously, risking a corrupted package index/cache — apt in particular is documented as not safe for concurrent cache writers.

Also applies to: 350-350, 359-362, 405-407, 425-426, 489-490, 583-587

🤖 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 `@Dockerfile` around lines 329 - 330, Update every later cache mount identified
in the Dockerfile, including the mounts near the shown apt commands and the
additional locations noted in the review, to use sharing=locked consistently.
Preserve each mount’s existing cache target and build behavior while ensuring
concurrent writers cannot modify shared package or tool caches simultaneously.
gpu-flavor/Dockerfile (1)

5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Base image string duplicated between FROM and LABEL.

workspace.baseimage hardcodes nvidia/cuda:11.2.2-cudnn8-devel-ubuntu20.04 again at line 121, duplicating the literal from the FROM line. If the base image is bumped later, it's easy to update one and forget the other, leaving the label metadata stale.

♻️ Proposed refactor
+ARG BASE_IMAGE="nvidia/cuda:11.2.2-cudnn8-devel-ubuntu20.04"
-FROM nvidia/cuda:11.2.2-cudnn8-devel-ubuntu20.04 AS gpu-base
+FROM $BASE_IMAGE AS gpu-base
+ARG BASE_IMAGE
 LABEL \
     "workspace.version"=$WORKSPACE_VERSION \
     "workspace.flavor"=$WORKSPACE_FLAVOR \
-    "workspace.baseimage"="nvidia/cuda:11.2.2-cudnn8-devel-ubuntu20.04" \
+    "workspace.baseimage"=$BASE_IMAGE \

Also applies to: 118-127

🤖 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 `@gpu-flavor/Dockerfile` at line 5, Remove the duplicated CUDA base-image
literal from the workspace.baseimage LABEL metadata and derive or reuse the
image reference declared by the FROM instruction, so updating the base image
keeps the label synchronized.
gpu-flavor/build.py (1)

27-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate _remove_existing_container helper — extract to shared module.

This function is byte-for-byte identical to _remove_existing_container already added in build.py (per the graph context). Maintaining the same try/except-NotFound logic in two places risks drift if one copy is updated later without the other.

Consider moving it into build_utils.py (already imported by both scripts) and importing it from there instead of duplicating.

🤖 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 `@gpu-flavor/build.py` around lines 27 - 35, Move the duplicate
_remove_existing_container helper into the shared build_utils.py module, then
remove the local definition and import it in both build.py scripts. Preserve the
existing client.containers.get, force removal, and docker.errors.NotFound
handling exactly through the shared helper.
🤖 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 @.github/actions/build-environment/build_requirements.txt:
- Line 3: Update the urllib3 dependency pin in build_requirements.txt from
1.26.13 to a patched release, using urllib3==1.26.20 or newer as appropriate.

In @.github/workflows/build-pipeline.yml:
- Line 19: Update the actions/checkout@v4 step in the build job to set
persist-credentials to false. Preserve the existing explicit GITHUB_TOKEN
handling for the local action, and configure any other authenticated Git access
explicitly if required.
- Around line 16-30: Update the build job containing actions/checkout@v4 and
run-build-scripts to add a job-level permissions block granting only the minimum
required capability for checkout, such as contents read access. Remove
GITHUB_TOKEN from the run-build-scripts env unless build.py or the local build
action explicitly requires GitHub API access; do not grant broader permissions.

In `@build.py`:
- Line 133: Update _build_with_buildx() so build_args is tokenized using
shell-style parsing rather than plain whitespace splitting, preserving quoted
values containing spaces as single arguments before passing them to
subprocess.run.

In `@gpu-flavor/Dockerfile`:
- Around line 78-82: Fix the corrupted JAX installation command in the
Dockerfile by removing the merged `--# install jax...` artifact and preserving a
valid standalone `pip install --upgrade jax[cuda111]` command with its
continuation. Also clean up the stray Arrayfire TODO/install artifact near the
later installation block without changing the intended package setup.

In `@Makefile`:
- Around line 42-44: Update the Makefile release target so it performs the
promised release workflow: bump versions, create a tag, and push the release,
rather than duplicating push-all. Keep push-all limited to pushing all flavors
and ensure the release help text accurately reflects the implemented behavior.
- Around line 62-76: Remove the duplicate flavor argument from the per-flavor
targets build-minimal, build-light, build-full, and build-gpu, or otherwise
ensure each target’s explicit flavor is the final effective value after
BUILD_ARGS. Preserve the existing build command behavior while making each
target reliably select its named flavor.

In `@resources/tools/vs-code-desktop.sh`:
- Around line 19-21: Update the VS Code installation flow in the script to
download a fixed, versioned Microsoft .deb URL instead of the latest redirect,
define the expected SHA-256 for that artifact, and verify the downloaded
vscode.deb checksum before running apt-get install. Keep installation blocked
when checksum validation fails.

In `@resources/tools/vs-code-server.sh`:
- Line 26: Update the symlink creation command in the installation script to be
idempotent, replacing the plain ln -s behavior so retries succeed when
/usr/local/bin/code-server already exists as the expected symlink. Preserve
creation of the link when it is absent and ensure the command remains compatible
with set -e.

---

Outside diff comments:
In @.github/workflows/release-pipeline.yml:
- Around line 121-127: Pin the actions/checkout step for
khulnasoft/release-drafter to a reviewed immutable commit SHA by adding the
appropriate ref under its with configuration. Keep the existing repository,
checkout path, create-release-draft condition, and local action usage unchanged.

---

Nitpick comments:
In @.github/actions/build-environment/build_requirements.txt:
- Line 5: Pin the Docker SDK dependency in build_requirements.txt to the tested
exact version, such as docker==6.1.3, replacing the current 6.x version range
while leaving other build requirements unchanged.

In `@Dockerfile`:
- Around line 328-343: Bound Git’s network stall detection in the pyenv
installation RUN step by removing the unlimited
http.lowSpeedLimit/http.lowSpeedTime settings and using finite, appropriate
timeout values. Keep the existing pyenv and plugin clone sequence unchanged
while ensuring stalled clones fail rather than hanging indefinitely.
- Around line 329-330: Update every later cache mount identified in the
Dockerfile, including the mounts near the shown apt commands and the additional
locations noted in the review, to use sharing=locked consistently. Preserve each
mount’s existing cache target and build behavior while ensuring concurrent
writers cannot modify shared package or tool caches simultaneously.

In `@gpu-flavor/build.py`:
- Around line 27-35: Move the duplicate _remove_existing_container helper into
the shared build_utils.py module, then remove the local definition and import it
in both build.py scripts. Preserve the existing client.containers.get, force
removal, and docker.errors.NotFound handling exactly through the shared helper.

In `@gpu-flavor/Dockerfile`:
- Line 5: Remove the duplicated CUDA base-image literal from the
workspace.baseimage LABEL metadata and derive or reuse the image reference
declared by the FROM instruction, so updating the base image keeps the label
synchronized.

In `@Makefile`:
- Around line 14-24: Update the build-all target to reuse the existing
BUILD_ARGS variable for buildx and cache flags instead of reconstructing them
with inline conditional expressions. Keep the conditional logic centralized in
the BUILD_ARGS definition and remove the duplicated flag assembly from
build-all.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 72f2de80-ab32-402e-8344-55f587f0cca6

📥 Commits

Reviewing files that changed from the base of the PR and between c1f1089 and 5766231.

📒 Files selected for processing (16)
  • .github/actions/build-environment/Dockerfile
  • .github/actions/build-environment/build_requirements.txt
  • .github/workflows/build-pipeline.yml
  • .github/workflows/release-pipeline.yml
  • DOCKER_BUILD_IMPROVEMENTS.md
  • Dockerfile
  • Makefile
  • build.py
  • build_requirements.txt
  • gpu-flavor/Dockerfile
  • gpu-flavor/build.py
  • resources/libraries/requirements-base.txt
  • resources/libraries/requirements-dev.txt
  • resources/scripts/clean-layer.sh
  • resources/tools/vs-code-desktop.sh
  • resources/tools/vs-code-server.sh

@@ -0,0 +1,5 @@
pipenv==2022.11.25
ml_buildkit==0.6.18
urllib3==1.26.13

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

python -m pip install --disable-pip-version-check pip-audit
pip-audit -r .github/actions/build-environment/build_requirements.txt

Repository: FortiShield/ml-workspace

Length of output: 4715


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== requirements =="
cat -n .github/actions/build-environment/build_requirements.txt

echo
echo "== pip-audit installed to == "
python3 -m pip show pip-audit | sed -n '1,16p' || true
if [ -f /home/jailuser/.local/bin/pip-audit ]; then
  /home/jailuser/.local/bin/pip-audit -r .github/actions/build-environment/build_requirements.txt || true
else
  echo "pip-audit executable not on PATH"
fi

Repository: FortiShield/ml-workspace

Length of output: 1180


🌐 Web query:

Python urllib3 CVE-2023-45803 fixed in version advisory

💡 Result:

The vulnerability CVE-2023-45803 in the Python urllib3 library, which involved a failure to strip the HTTP request body when performing certain redirects, has been fixed in the following versions: - urllib3 version 1.26.18 [1][2][3] - urllib3 version 2.0.7 [1][2][3] Users running any version of urllib3 prior to these releases are advised to upgrade to the patched versions [2][3]. If an immediate upgrade is not possible, the vulnerability can be mitigated by disabling automatic redirects for services where they are not expected, or by handling them manually to ensure the request body is stripped when required [1][3].

Citations:


🌐 Web query:

pip-audit --no-deps --only-fixed urllib3

💡 Result:

The command pip-audit --no-deps --only-fixed urllib3 is invalid because --only-fixed is not a recognized flag for the pip-audit tool [1][2][3][4]. According to the official pip-audit documentation, the available flags and options include [1][5][4]: --no-deps: This flag instructs pip-audit to skip dependency resolution [1][6][5]. It requires that all requirements be pinned to exact versions [1][2][6]. It is primarily designed for use with requirements files [7]. There is no --only-fixed flag in the current pip-audit CLI [1][2][4]. If you are attempting to filter for vulnerabilities that have a known fix, note that pip-audit does not currently provide a native flag for this specific purpose [8]. The tool is generally designed to report all discovered vulnerabilities, and you can manage specific entries using options like --ignore-vuln [1][8][4]. Additionally, the command structure you provided implies auditing a single package (urllib3) as a positional argument. Please be aware that pip-audit is typically used to audit local environments, projects, or requirement files, rather than individual packages passed directly as arguments [3][4]. If you wish to audit a specific version of a package, you can create a temporary requirements file containing that package and version, then point pip-audit to it using the -r flag [7][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
export PATH="/home/jailuser/.local/bin:$PATH"
python3 -m pip_audit.cli -r .github/actions/build-environment/build_requirements.txt || true

Repository: FortiShield/ml-workspace

Length of output: 210


🏁 Script executed:

#!/bin/bash
set -euo pipefail
export PATH="/home/jailuser/.local/bin:$PATH"
python3 -m pip audit -r .github/actions/build-environment/build_requirements.txt || true

echo
echo "== direct pip-audit with PATH =="
pip-audit -r .github/actions/build-environment/build_requirements.txt || true

Repository: FortiShield/ml-workspace

Length of output: 621


Upgrade the vulnerable urllib3 pin.

urllib3==1.26.13 is below the patched 1.26.18 release for CVE-2023-45803. Since this build environment receives CI credentials, use a patched pin such as urllib3==1.26.20.

🤖 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 @.github/actions/build-environment/build_requirements.txt at line 3, Update
the urllib3 dependency pin in build_requirements.txt from 1.26.13 to a patched
release, using urllib3==1.26.20 or newer as appropriate.

Comment on lines 16 to +30
build:
runs-on: ubuntu-latest
steps:
- name: set-input-build-args
if: ${{ github.event.inputs != null && github.event.inputs.build_args != null}}
run: echo "BUILD_ARGS=${{ github.event.inputs.build_args }}" >> $GITHUB_ENV
# new syntax: run: echo "BUILD_ARGS=${{ github.event.inputs.build_args }}" >> "$GITHUB_ENV"
- name: set-input-working-directory
if: ${{ github.event.inputs != null && github.event.inputs.working_directory != null}}
run: echo "WORKING_DIRECTORY=${{ github.event.inputs.working_directory }}" >> $GITHUB_ENV
# new syntax: run: echo "WORKING_DIRECTORY=${{ github.event.inputs.working_directory }}" >> "$GITHUB_ENV"
# Set host ip to env variable to be uside within container actions
- uses: actions/checkout@v4

- name: set-host-ip
run: echo "_HOST_IP=$(hostname -I | cut -d ' ' -f 1)" >> $GITHUB_ENV
- uses: actions/checkout@v2
run: echo "_HOST_IP=$(hostname -I | cut -d ' ' -f 1)" >> "$GITHUB_ENV"

- name: run-build-scripts
uses: ./.github/actions/build-environment
with:
build_args: ${{ env.BUILD_ARGS }}
working_directory: ${{ env.WORKING_DIRECTORY }}
build_args: ${{ github.event.inputs.build_args || secrets.BUILD_ARGS }}
working_directory: ${{ github.event.inputs.working_directory || secrets.WORKING_DIRECTORY }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow =="
cat -n .github/workflows/build-pipeline.yml | sed -n '1,120p'

echo
echo "== local action manifest and dockerfiles =="
fd -a 'action.yml|Dockerfile|.*\.ya?ml|.*\.sh|.*\.ps1' .github/actions/build-environment || true

echo
echo "== files under local action =="
git ls-files .github/actions/build-environment | sed -n '1,200p'

echo
echo "== search GITHUB_TOKEN and permissions in workflow/action =="
rg -n "permissions:|GITHUB_TOKEN|secrets\.GITHUB_TOKEN|actions/checkout|gh |npm|yarn|pip|go build|cargo|build" .github/workflows/build-pipeline.yml .github/actions/build-environment || true

echo
echo "== changed files/stat =="
git diff --stat HEAD~1..HEAD 2>/dev/null || git diff --stat || true

Repository: FortiShield/ml-workspace

Length of output: 5991


Set a least-privilege GitHub token scope.

This workflow runs actions/checkout@v4, and the local build action forwards secrets.GITHUB_TOKEN into the build container for git config and build.py. Add a job-level permissions: block with only the required token capabilities, and omit GITHUB_TOKEN from the action unless the build actually needs GitHub API access.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 19-19: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[warning] 16-30: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)

🤖 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 @.github/workflows/build-pipeline.yml around lines 16 - 30, Update the build
job containing actions/checkout@v4 and run-build-scripts to add a job-level
permissions block granting only the minimum required capability for checkout,
such as contents read access. Remove GITHUB_TOKEN from the run-build-scripts env
unless build.py or the local build action explicitly requires GitHub API access;
do not grant broader permissions.

Source: Linters/SAST tools

run: echo "WORKING_DIRECTORY=${{ github.event.inputs.working_directory }}" >> $GITHUB_ENV
# new syntax: run: echo "WORKING_DIRECTORY=${{ github.event.inputs.working_directory }}" >> "$GITHUB_ENV"
# Set host ip to env variable to be uside within container actions
- uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Disable persisted checkout credentials for the build job.

zizmor flags this checkout because credentials remain available to subsequent build tooling. Since GITHUB_TOKEN is already passed explicitly to the local action, add persist-credentials: false and configure any required authenticated Git access explicitly.

Proposed fix
       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 19-19: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 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 @.github/workflows/build-pipeline.yml at line 19, Update the
actions/checkout@v4 step in the build job to set persist-credentials to false.
Preserve the existing explicit GITHUB_TOKEN handling for the local action, and
configure any other authenticated Git access explicitly if required.

Source: Linters/SAST tools

Comment thread build.py
if flavor in ["minimal", "light"]:
buildx_args.extend(["--build-arg", f"ARG_WORKSPACE_FLAVOR={flavor}"])

buildx_args.extend(build_args.split())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect how version_build_arg / build_date_build_arg / vcs_ref_build_arg are constructed
grep -n "build_arg" build.py

Repository: FortiShield/ml-workspace

Length of output: 925


🏁 Script executed:

#!/bin/bash
set -euo pipefail
wc -l build.py
sed -n '1,220p' build.py

Repository: FortiShield/ml-workspace

Length of output: 6347


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '120,165p' build.py | cat -n
python3 - <<'PY'
examples = [
    ' --build-arg ARG_BUILD_DATE=2026-01-02',
    ' --build-arg ARG_BUILD_DATE="2026-01 02"',
    ' --build-arg ARG_BUILD_DATE=2026-01-02 --build-arg ARG_WORKSPACE_FLAVOR=full',
]
for arg in examples:
    print(repr(arg), "=>", arg.split(), "count", len(arg.split()))
PY

Repository: FortiShield/ml-workspace

Length of output: 2216


Parse the build args as tokens, not naive whitespace.

build_args is a shell-style argument string, but _build_with_buildx() splits it with plain whitespace before calling subprocess.run. A build arg containing a quoted value with a space will be split into multiple arguments, so --build-arg can get the wrong value or be followed by a dangling fragment. Tokenize the string with a shell parser, or build the argument list directly.

🤖 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 `@build.py` at line 133, Update _build_with_buildx() so build_args is tokenized
using shell-style parsing rather than plain whitespace splitting, preserving
quoted values containing spaces as single arguments before passing them to
subprocess.run.

Comment thread gpu-flavor/Dockerfile
Comment on lines 78 to 82
# cuda111 -> >= 11.1
pip install --no-cache-dir mxnet-cu112 && \
# install jax: https://github.com/google/jax#pip-installation
pip install --# install jax: https://github.com/google/jax#pip-installation \
pip install --upgrade jax[cuda111] -f https://storage.googleapis.com/jax-releases/jax_releases.html && \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Build-breaking merge artifact in the jax install line.

Line 81 (pip install --# install jax: https://github.com/google/jax#pip-installation \) looks like a corrupted merge of the comment on line 80 with the real install line on line 82. Since --# is a single token (not # at the start of a word), bash won't treat it as a comment — it passes --# as a literal (invalid) pip argument. Combined with line 82 via the backslash continuation, this produces one garbled pip install invocation that will fail, breaking the entire RUN and the GPU image build.

The same kind of leftover artifact also shows up at line 99 (# TODO: Install Arrayfire: ... pip install --no-cache-dir arrayfire && \) — harmless there since the whole line is a comment, but worth cleaning up while fixing this hunk.

🐛 Proposed fix
-    # install jax: https://github.com/google/jax#pip-installation
-    pip install --# install jax: https://github.com/google/jax#pip-installation \
+    # install jax: https://github.com/google/jax#pip-installation
     pip install --upgrade jax[cuda111] -f https://storage.googleapis.com/jax-releases/jax_releases.html && \
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# cuda111 -> >= 11.1
pip install --no-cache-dir mxnet-cu112 && \
# install jax: https://github.com/google/jax#pip-installation
pip install --# install jax: https://github.com/google/jax#pip-installation \
pip install --upgrade jax[cuda111] -f https://storage.googleapis.com/jax-releases/jax_releases.html && \
# cuda111 -> >= 11.1
pip install --no-cache-dir mxnet-cu112 && \
# install jax: https://github.com/google/jax#pip-installation
pip install --upgrade jax[cuda111] -f https://storage.googleapis.com/jax-releases/jax_releases.html && \
🤖 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 `@gpu-flavor/Dockerfile` around lines 78 - 82, Fix the corrupted JAX
installation command in the Dockerfile by removing the merged `--# install
jax...` artifact and preserving a valid standalone `pip install --upgrade
jax[cuda111]` command with its continuation. Also clean up the stray Arrayfire
TODO/install artifact near the later installation block without changing the
intended package setup.

Comment thread Makefile
Comment on lines +42 to +44
@echo " make push - Push single flavor"
@echo " make push-all - Push all flavors"
@echo " make release - Create release (bump versions, tag, push)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

release doesn't do what the help text promises.

Help text says make release should "bump versions, tag, push", but release (92-93) is byte-identical to push-all (89-90) — no version bump or tagging logic exists anywhere in this file.

Also applies to: 86-93

🤖 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 `@Makefile` around lines 42 - 44, Update the Makefile release target so it
performs the promised release workflow: bump versions, create a tag, and push
the release, rather than duplicating push-all. Keep push-all limited to pushing
all flavors and ensure the release help text accurately reflects the implemented
behavior.

Comment thread Makefile
Comment on lines +62 to +76
build:
python3 build.py --make $(BUILD_ARGS)

build-minimal:
python3 build.py --flavor minimal --make $(BUILD_ARGS)

build-light:
python3 build.py --flavor light --make $(BUILD_ARGS)

build-full:
python3 build.py --flavor full --make $(BUILD_ARGS)

build-gpu:
python3 build.py --flavor gpu --make $(BUILD_ARGS)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

--flavor is passed twice, so per-flavor targets silently build the wrong flavor.

BUILD_ARGS (line 15) already appends --flavor $(FLAVOR) (default full). build-minimal/build-light/build-full/build-gpu additionally pass an explicit --flavor <x> before $(BUILD_ARGS). Since argparse takes the last occurrence of a repeated flag, the trailing --flavor full (from BUILD_ARGS, unless the caller also sets FLAVOR=...) wins — e.g. make build-minimal actually builds the full flavor.

🐛 Proposed fix
-build-minimal:
-	python3 build.py --flavor minimal --make $(BUILD_ARGS)
-
-build-light:
-	python3 build.py --flavor light --make $(BUILD_ARGS)
-
-build-full:
-	python3 build.py --flavor full --make $(BUILD_ARGS)
-
-build-gpu:
-	python3 build.py --flavor gpu --make $(BUILD_ARGS)
+build-minimal:
+	$(MAKE) build FLAVOR=minimal
+
+build-light:
+	$(MAKE) build FLAVOR=light
+
+build-full:
+	$(MAKE) build FLAVOR=full
+
+build-gpu:
+	$(MAKE) build FLAVOR=gpu
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
build:
python3 build.py --make $(BUILD_ARGS)
build-minimal:
python3 build.py --flavor minimal --make $(BUILD_ARGS)
build-light:
python3 build.py --flavor light --make $(BUILD_ARGS)
build-full:
python3 build.py --flavor full --make $(BUILD_ARGS)
build-gpu:
python3 build.py --flavor gpu --make $(BUILD_ARGS)
build:
python3 build.py --make $(BUILD_ARGS)
build-minimal:
$(MAKE) build FLAVOR=minimal
build-light:
$(MAKE) build FLAVOR=light
build-full:
$(MAKE) build FLAVOR=full
build-gpu:
$(MAKE) build FLAVOR=gpu
🤖 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 `@Makefile` around lines 62 - 76, Remove the duplicate flavor argument from the
per-flavor targets build-minimal, build-light, build-full, and build-gpu, or
otherwise ensure each target’s explicit flavor is the final effective value
after BUILD_ARGS. Preserve the existing build command behavior while making each
target reliably select its named flavor.

Comment on lines +19 to 21
wget -q https://go.microsoft.com/fwlink/?LinkID=760868 -O ./vscode.deb
apt-get update
apt-get install -y ./vscode.deb

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repo files matching vscode:\n'
fd -i 'vs-code-desktop|vscode|Dockerfile' . | sed 's#^\./##' | head -100

printf '\nresources/tools/vs-code-desktop.sh if present:\n'
if [ -f resources/tools/vs-code-desktop.sh ]; then
  cat -n resources/tools/vs-code-desktop.sh
else
  echo 'not found'
fi

printf '\nDockerfile references around 545-554 if present:\n'
if [ -f Dockerfile ]; then
  sed -n '530,565p' Dockerfile | cat -n -v
else
  echo 'Dockerfile not found at root'
  fd -i '^Dockerfile$' . | while read -r f; do
    echo "--- $f"
    wc -l "$f"
    sed -n '1,80p' "$f"
  done
fi

printf '\nSearch for LinkID=760868 and vs-code-desktop usage:\n'
rg -n "LinkID=760868|vs-code-desktop|vscode.deb|go\.microsoft\.com/fwlink' --silent

Repository: FortiShield/ml-workspace

Length of output: 3059


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Search for LinkID=760868 and vs-code-desktop usage:\n'
rg -n 'LinkID=760868|vs-code-desktop|vscode\.deb|go\.microsoft\.com/fwlink' .

printf '\nDockerfile line numbers around VS Code install section:\n'
grep -nE 'Install Visual Studio Code|vs-code-desktop|WORKSPACE_FLAVOR' Dockerfile || true

Repository: FortiShield/ml-workspace

Length of output: 3298


🌐 Web query:

Visual Studio Code Linux installer go.microsoft.com/fwlink LinkID=760868

💡 Result:

The URL go.microsoft.com/fwlink/?LinkID=760868 is an official Microsoft forwarding link that redirects to the latest stable.deb (Debian-based) installer for Visual Studio Code on Linux [1][2][3]. Because this is a redirect link, it is often used in scripts and automated installation processes to ensure the most recent version of the software is downloaded [4][5]. If you are using this link in a command-line tool like curl, you must use the -L (or --location) flag to follow the HTTP redirect to the final file location [4]: curl -L -o code.deb https://go.microsoft.com/fwlink/?LinkID=760868 Once downloaded, the package can be installed using standard package managers, such as: sudo apt install./code.deb Alternatively, for older distributions, one might use: sudo dpkg -i code.deb sudo apt-get install -f # To resolve and install dependencies Official documentation recommends visiting the main Visual Studio Code download page for a comprehensive list of distribution options, including.rpm and Snap packages [6][3][7].

Citations:


Pin the VS Code artifact for reproducible image builds.

resources/tools/vs-code-desktop.sh:19 installs VS Code from Microsoft’s latest .deb redirect during Dockerfile image construction (Dockerfile:545-552), so non-minimal images can receive a different VS Code version after cache misses. Use a fixed, versioned .deb and verify its SHA-256 before apt-get install.

🤖 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 `@resources/tools/vs-code-desktop.sh` around lines 19 - 21, Update the VS Code
installation flow in the script to download a fixed, versioned Microsoft .deb
URL instead of the latest redirect, define the expected SHA-256 for that
artifact, and verify the downloaded vscode.deb checksum before running apt-get
install. Keep installation blocked when checksum validation fails.

apt-get update
apt-get install -y ./code-server.deb
rm ./code-server.deb
ln -s /usr/bin/code-server /usr/local/bin/code-server

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repository files around target:"
git ls-files | rg '(^|/)vs-code-server\.sh$|usr/local/bin|code-server' || true

echo
echo "Target file excerpt:"
if [ -f resources/tools/vs-code-server.sh ]; then
  cat -n resources/tools/vs-code-server.sh | sed -n '1,80p'
fi

echo
echo "Search symlink command and shell behavior clues:"
rg -n 'ln -s .*code-server|code-server|set -e|bash|sh' resources || true

Repository: FortiShield/ml-workspace

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Exact target excerpt:"
cat -n resources/tools/vs-code-server.sh | sed -n '1,80p'

echo
echo "Relevant shell tests in /tmp:"
test -d /tmp/code-server-link-test && rm -rf /tmp/code-server-link-test
mkdir -p /tmp/code-server-link-test
target_dir="$(mktemp -d /tmp/code-server-link-test-usr-local.XXXXXX)"
tmp_dir="$(mktemp -d /tmp/code-server-link-test-usr-bin.XXXXXX)"
export target_dir tmp_dir
python3 - <<'PY'
import os, subprocess, tempfile
from pathlib import Path

target_dir = os.environ["target_dir"].encode() if isinstance(os.environ["target_dir"], str) else os.environ["target_dir"]
tmp_dir = os.environ["tmp_dir"].encode() if isinstance(os.environ["tmp_dir"], str) else os.environ["tmp_dir"]

target_dir = Path(target_dir.decode())
tmp_dir = Path(tmp_dir.decode())
target_dir.symlink_to(tmp_dir)
bin_path = Path(target_dir / "dir")
bin_path.parent.mkdir()
bin_path.symlink_to("/usr/bin/code-server")

out = subprocess.run(
    ["bash", "-c", "set -e ; ln -s /usr/bin/code-server /usr/local/bin/code-server"],
    executable="/bin/bash",
    text=True,
)
print("plain_ln_rc=", out.returncode)

out2 = subprocess.run(
    ["bash", "-c", "set -e ; ln -sfn /usr/bin/code-server /usr/local/bin/code-server"],
    executable="/bin/bash",
    text=True,
)
print("force_ln_rc=", out2.returncode)
PY

echo
echo "Search for exact symlink command in repository:"
rg -n --glob '!resources/licenses/**' --glob '!docs/**' --glob '!node_modules/**' '\bln -s /usr/bin/code-server /usr/local/bin/code-server\b' . || true

Repository: FortiShield/ml-workspace

Length of output: 2392


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import os, subprocess, tempfile, stat
from pathlib import Path

with tempfile.TemporaryDirectory() as tmpdir:
    bin_dir = Path(tmpdir) / "usr" / "bin"
    local_dir = Path(tmpdir) / "usr" / "local" / "bin"
    bin_dir.mkdir(parents=True)
    local_dir.mkdir(parents=True)
    target_file = bin_dir / "code-server"
    target_file.write_text("echo target")
    target_file.chmod(target_file.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
    local_link = local_dir / "code-server"
    local_link.symlink_to(target_file)

    print("before_plain_is_ok=", local_link.exists(), os.path.lexists(str(local_link)))

    out = subprocess.run(
        ["bash", "-c", "set -e ; ln -s /usr/bin/code-server /usr/local/bin/code-server"],
        executable="/bin/bash",
        cwd=tmpdir,
        text=True,
        capture_output=True,
    )
    print("plain_ln_returncode=", out.returncode)
    print("plain_ln_stderr=", out.stderr.strip().replace(tmpdir, "<tmpdir>"))
    print("after_plain_is_ok=", local_link.exists(), os.path.lexists(str(local_link)))

    print("before_force_is_ok=", local_link.exists(), os.path.lexists(str(local_link)))

    out2 = subprocess.run(
        ["bash", "-c", "set -e ; ln -sfn /usr/bin/code-server /usr/local/bin/code-server"],
        executable="/bin/bash",
        cwd=tmpdir,
        text=True,
        capture_output=True,
    )
    print("force_ln_returncode=", out2.returncode)
    print("force_ln_stderr=", out2.stderr.strip().replace(tmpdir, "<tmpdir>"))
    print("after_force_is_ok=", local_link.exists(), os.path.lexists(str(local_link)))
PY

Repository: FortiShield/ml-workspace

Length of output: 526


🌐 Web query:

GNU coreutils ln command line options -sf overwrite existing destination documentation

💡 Result:

By default, the GNU coreutils ln command does not replace or overwrite existing files [1][2]. If you attempt to create a link with a name that already exists, the command will fail [3][4]. To manage existing destination files, you can use the following command-line options: --force (-f): This option removes any existing destination files unconditionally to allow the link to be created [1][3]. --interactive (-i): This option prompts you for confirmation before removing an existing destination file [1][2]. The operation proceeds only if you provide an affirmative response [2]. --backup (-b): This option creates a backup of each existing destination file before it is removed or replaced [1][5]. You can customize the backup method using the --backup[=CONTROL] option or the VERSION_CONTROL environment variable [6][3]. When using --backup, there is no brief moment where the destination file does not exist, which distinguishes GNU ln from standard POSIX behavior [1][2].

Citations:


🌐 Web query:

POSIX ln command behavior existing destination file without -f

💡 Result:

According to the POSIX standard, the behavior of the ln command when a destination file already exists is as follows: If the -f (force) option is not specified and the destination path already exists, the ln utility is not permitted to remove or replace the existing destination file [1][2]. In this scenario, the utility will typically write a diagnostic message to standard error and skip the creation of the link for that specific source file [3][4]. The -f option is explicitly provided to change this behavior: when -f is specified, ln is authorized to remove the existing destination path to allow the new link to be created [1][2]. It is important to note that the standard explicitly leaves the exact behavior unspecified if the destination path was created by a previous step in the same execution (e.g., when linking multiple files at once) [1]. Additionally, while historical implementations might have prompted for confirmation before unlinking an existing file, the current POSIX specification does not require or define such interactive behavior [1].

Citations:


🌐 Web query:

APT DEB package /usr/bin/code-server conffile usr/local/bin/code-server conffile configuration file lintian

💡 Result:

In Debian packaging, marking files under /usr as conffiles triggers a Lintian error because of the Debian Policy Manual requirements [1][2][3]. According to the Debian Policy Manual, all configuration files must reside in /etc [4]. Files located under /usr (such as /usr/bin/code-server or /usr/local/bin/code-server) are not permitted to be marked as conffiles because /usr may be mounted as a read-only filesystem, preventing the local system administrator from modifying the configuration [1][2][3]. If you are encountering this issue while packaging software like code-server, you must adhere to the following Debian packaging standards: 1. Compliance with Location Policy: Move configuration files to /etc [4]. If your application requires a configuration file, create a subdirectory in /etc (e.g., /etc/code-server/) to hold it [4]. 2. Avoid Marking Binaries as Conffiles: Executables installed in /usr/bin or /usr/local/bin should never be marked as conffiles [1][4]. The conffiles mechanism is exclusively intended for files that a user is expected to customize, such as service configurations or application settings [5][4]. 3. Packaging Tooling: If you are using automated tools to build your.deb packages (such as nfpm, which is often used in code-server builds), ensure your configuration file mapping explicitly points to /etc [6][7]. If a file is incorrectly flagged by Lintian, you may have an error in your package's debian/conffiles file or your build system's configuration that is erroneously designating a binary path as a configuration file [8][9]. If you must manage application configuration that defaults to a path outside of /etc, you can use symlinks within /etc pointing to the actual configuration location, or use maintainer scripts (postinst) to manage the configuration file creation, provided they follow Debian policy on idempotency and user interaction [10][5][4].

Citations:


🌐 Web query:

GitHub cdr code-server Debian package usr/bin/code-server usr/local/bin/code-server

💡 Result:

When you install the code-server.deb package on Debian or Ubuntu, the executable is installed to /usr/bin/code-server. This path is standard for system-level package installations on Debian-based distributions. In contrast, the /usr/local/bin/ directory is typically reserved for software compiled or installed manually by the user, or by scripts that do not follow standard packaging conventions. If you use the code-server automated installation script with the --prefix=/usr/local option, or if you perform a manual standalone installation, the binary may be placed in or symlinked to /usr/local/bin/code-server, but this is distinct from the standard Debian package installation behavior.

Citations:


Make symlink creation idempotent.

If a retry follows a partial install, apt-get may restore the existing /usr/local/bin/code-server symlink so the subsequent plain ln -s fails under set -e.

Suggested fix
-    ln -s /usr/bin/code-server /usr/local/bin/code-server
+    ln -sfn /usr/bin/code-server /usr/local/bin/code-server
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ln -s /usr/bin/code-server /usr/local/bin/code-server
ln -sfn /usr/bin/code-server /usr/local/bin/code-server
🤖 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 `@resources/tools/vs-code-server.sh` at line 26, Update the symlink creation
command in the installation script to be idempotent, replacing the plain ln -s
behavior so retries succeed when /usr/local/bin/code-server already exists as
the expected symlink. Preserve creation of the link when it is absent and ensure
the command remains compatible with set -e.

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