Skip to content

Add Docker image and GitHub Action for qtmesh CLI - #184

Merged
fernandotonon merged 7 commits into
masterfrom
feature/docker-image-github-action
Mar 9, 2026
Merged

Add Docker image and GitHub Action for qtmesh CLI#184
fernandotonon merged 7 commits into
masterfrom
feature/docker-image-github-action

Conversation

@fernandotonon

@fernandotonon fernandotonon commented Mar 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a Docker image (Ubuntu 22.04 + .deb) for running qtmesh CLI commands without local installation
  • Includes docker-entrypoint.sh that auto-starts Xvfb for headless Ogre GL rendering and routes commands to the correct binary
  • Adds docker-publish.yml workflow that builds and pushes the image to ghcr.io (always) and Docker Hub (on release) when a release is published
  • Adds a reusable composite GitHub Action at .github/actions/qtmesh/ for easy integration into CI pipelines

Usage

# Info
docker run --rm -v $(pwd):/workspace ghcr.io/fernandotonon/qtmesheditor info model.fbx --json

# Convert
docker run --rm -v $(pwd):/workspace ghcr.io/fernandotonon/qtmesheditor convert model.fbx -o model.gltf2

# Fix
docker run --rm -v $(pwd):/workspace ghcr.io/fernandotonon/qtmesheditor fix model.fbx -o fixed.fbx --all

# MCP server
docker run --rm -p 8080:8080 -v $(pwd):/workspace ghcr.io/fernandotonon/qtmesheditor --mcp --http-port 8080

GitHub Action:

- uses: fernandotonon/QtMeshEditor/.github/actions/qtmesh@master
  with:
    command: info
    input-file: assets/player.fbx
    options: --json

Required secrets for Docker Hub

  • DOCKERHUB_USERNAME — Docker Hub username
  • DOCKERHUB_TOKEN — Docker Hub access token

ghcr.io uses the built-in GITHUB_TOKEN (no setup needed).

Test plan

  • Download a release .deb, place in repo root, build image locally: docker build -t qtmesheditor:test .
  • Test CLI commands: --help, --version, info, convert, fix, anim --list
  • Trigger workflow via workflow_dispatch to verify image builds and pushes to ghcr.io
  • After setting Docker Hub secrets, verify push to Docker Hub on a release

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Docker container support, an entrypoint that routes CLI commands and enables GUI in headless environments, and an automated workflow to build, tag, and publish the container image.
    • Added a reusable CI action to run the tool inside the container and capture results.
  • Chores

    • Updated ignore rules to exclude build/local artifacts from container context and packaging.
    • Bumped project version to 2.11.1.

fernandotonon and others added 5 commits March 5, 2026 21:29
The curl installer places sentry-cli in /usr/local/bin which is not in
Git Bash's PATH on Windows runners. Use the full path instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enables running qtmesh CLI commands via Docker without local installation.
The image installs the release .deb in Ubuntu 22.04 with Xvfb for headless
Ogre GL rendering.

- Dockerfile: single-stage Ubuntu 22.04, COPY .deb approach
- docker-entrypoint.sh: auto-starts Xvfb, routes CLI/MCP commands
- docker-publish.yml: builds and pushes on release (ghcr.io + Docker Hub)
- .github/actions/qtmesh: reusable composite action for CI pipelines
- .dockerignore: excludes build artifacts and dev files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bae8dd440b

ℹ️ About Codex in GitHub

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

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

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Dockerfile Outdated

# Create qtmesh symlink for CLI mode detection
# (binary name must start with "qtmesh" but NOT contain "editor")
RUN ln -sf /usr/share/qtmesheditor/qtmesheditor /usr/local/bin/qtmesh

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route CLI through packaged launcher script

qtmesh is symlinked directly to /usr/share/qtmesheditor/qtmesheditor, but the Debian package is built to launch via /usr/bin/qtmesheditor (which exports runtime env like LD_LIBRARY_PATH before exec). Because the entrypoint sends info|fix|convert|anim|--help|--version through qtmesh, the container can fail at runtime with missing Qt/Ogre shared libraries even though the package installed successfully.

Useful? React with 👍 / 👎.

Comment thread .github/workflows/docker-publish.yml Outdated
run: |
VERSION="${{ steps.version.outputs.version }}"
TAGS="${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }}:${VERSION}"
TAGS="${TAGS},${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }}:latest"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Skip publishing :latest for version-pinned dispatch builds

This step always appends the GHCR :latest tag, including workflow_dispatch runs where inputs.version is explicitly set to an older release. Rebuilding or backfilling an old tag would therefore overwrite ghcr.io/...:latest with stale binaries, regressing consumers that pull latest.

Useful? React with 👍 / 👎.

Comment thread .github/workflows/docker-publish.yml Outdated
- name: Extract version from CMakeLists.txt
id: version
run: |
VERSION=$(grep 'project(QtMeshEditor VERSION' CMakeLists.txt | sed 's/.*VERSION \([0-9.]*\).*/\1/')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive image version from the selected release artifact

The workflow downloads the .deb for the requested release tag, but then computes VERSION from the checked-out branch’s CMakeLists.txt. On workflow_dispatch for non-current tags, this can publish labels/tags that claim one version while containing another release’s binary, making image provenance unreliable.

Useful? React with 👍 / 👎.

@coderabbitai

coderabbitai Bot commented Mar 9, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d84ce4f3-3d3a-4791-bd87-26f7678c39ff

📥 Commits

Reviewing files that changed from the base of the PR and between 5c033e4 and c893f78.

📒 Files selected for processing (1)
  • CMakeLists.txt

📝 Walkthrough

Walkthrough

Adds Docker packaging and entrypoint for QtMeshEditor, a reusable GitHub Actions composite action for running qtmesh, CI workflows to build/tag/publish container images, updates .dockerignore, and bumps project version to 2.11.1; also creates a packaging symlink for the qtmesh CLI.

Changes

Cohort / File(s) Summary
Docker config & entrypoint
\.dockerignore, Dockerfile, docker-entrypoint.sh
Adds .dockerignore exclusions; new Dockerfile that installs a qtmesheditor .deb, sets OCI labels, creates /usr/local/bin/qtmesh symlink and docker-entrypoint.sh; entrypoint enables Xvfb when DISPLAY is absent and routes commands between qtmesh and qtmesheditor.
CI workflows
.github/workflows/docker-publish.yml, .github/workflows/deploy.yml
Adds docker-publish.yml to build, tag, and push Docker images (ghcr.io and Docker Hub on release), extract version and release assets, and verify the image; deploy.yml packaging step now creates a qtmesh symlink in packaged usr/bin.
Reusable GH Action
.github/actions/qtmesh/action.yml
New composite action qtmesh with inputs (command, input-file, output-file, options, image-tag) and output result; runs the qtmesheditor image via Docker, mounts workspace, and captures stdout as action output.
Build metadata
CMakeLists.txt
Project version increment from 2.11.0 to 2.11.1.

Sequence Diagram(s)

sequenceDiagram
    participant Release as Release/Event
    participant GH_Actions as GitHub Actions
    participant GH_CLI as gh CLI
    participant Buildx as Docker Buildx
    participant Registry as Registry (ghcr.io / Docker Hub)

    Release->>GH_Actions: trigger (release or workflow_dispatch)
    GH_Actions->>GH_CLI: download .deb release assets
    GH_Actions->>Buildx: build image with tags & OCI labels
    Buildx->>Registry: push image tags
    GH_Actions->>Registry: run container --help to verify
Loading
sequenceDiagram
    participant Workflow as Workflow Job
    participant Composite as .github/actions/qtmesh
    participant Docker as Docker (runner)
    participant Container as qtmesheditor image

    Workflow->>Composite: invoke (command, input-file, options, image-tag)
    Composite->>Docker: run container with workspace mount
    Docker->>Container: execute qtmesh / qtmesheditor
    Container-->>Composite: stdout captured
    Composite-->>Workflow: output `result`
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped into a Docker nest,
Packed qtmesh snug for CI's quest,
Actions spin and images soar,
Symlinks hum and screens restore —
A rabbit cheers for builds abreast 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main changes: adding Docker image and GitHub Action support for qtmesh CLI, which aligns with the primary objectives of the changeset.
Description check ✅ Passed The description includes a comprehensive summary, technical details organized by features, usage examples, required secrets, and a test plan—covering all template sections with substantial content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/docker-image-github-action

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

@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: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/actions/qtmesh/action.yml:
- Around line 30-44: The current run step interpolates inputs directly into a
shell string (OUTPUT, OUTPUT_FLAG, ${{ inputs.command }}, ${{ inputs.options }})
which allows word-splitting and injection and also runs the container as root;
change it to build safe arrays and quoted expansions and add a non-root user:
construct a bash array for the docker command and a separate array for the
container command (e.g., DOCKER_ARGS=(--rm -v "${{ github.workspace
}}:/workspace" --user "$(id -u):$(id -g)"
"ghcr.io/fernandotonon/qtmesheditor:${{ inputs.image-tag }}" ) and CMD_ARGS=(
"${{ inputs.command }}" "/workspace/${{ inputs.input-file }}" ), use read -r -a
OPTS <<< "${{ inputs.options }}" to split options into an array if present and
append them to CMD_ARGS, handle OUTPUT_FLAG by appending "-o" and
"/workspace/${{ inputs.output-file }}" to CMD_ARGS only when inputs.output-file
is non-empty, then execute docker with: OUTPUT=$(docker run "${DOCKER_ARGS[@]}"
"${CMD_ARGS[@]}") so all inputs are passed as separate, quoted argv elements and
files created inside the workspace are owned by the calling user instead of
root.

In @.github/workflows/docker-publish.yml:
- Around line 39-50: The workflow currently downloads all matching .deb assets
which can produce multiple files and break Docker's COPY *.deb; modify the
"Download .deb from release" step to select a single asset and rename it to a
deterministic filename (e.g., qtmesheditor.deb) after download (use the TAG
variable and gh release download options or filter/rename the single matched
file), and then update the Dockerfile to COPY that deterministic filename (COPY
qtmesheditor.deb /tmp/qtmesheditor.deb) instead of using a glob; ensure the
workflow echoes/ls only the renamed file to verify.
- Around line 52-86: The workflow currently extracts VERSION in the "Extract
version from CMakeLists.txt" step (id: version) and later computes tags in the
"Compute Docker tags" step (id: tags), which causes tags to reflect the
checked-out branch instead of the selected release artifact; change the logic so
VERSION is derived from the selected release artifact or release tag (use the
downloaded asset filename or github.event.release.tag_name when a release is
targeted) and only set the additional :latest tag when the release being built
is the latest/current release; update the version extraction step (id: version)
to prefer the release/tag source and adjust the tag computation step (id: tags)
accordingly so published images are named from the release artifact, not from
the checked-out branch.

In `@docker-entrypoint.sh`:
- Around line 7-12: The startup loop that probes Xvfb using "for i in $(seq 1
10); do xdpyinfo -display :99 &>/dev/null && break; sleep 0.2; done" should fail
fast if the probe never succeeds: after that loop check the probe result (e.g.
run xdpyinfo -display :99 once more or test whether the loop broke) and if it
still fails, emit a clear error message and exit with a non‑zero status (use
exit 1) so the container stops immediately instead of continuing to later
Qt/Ogre steps; update the block around the Xvfb start and probe to perform this
check and exit on timeout.

In `@Dockerfile`:
- Around line 1-30: The Dockerfile currently leaves the container running as
root; add a non-root runtime user and switch to it before ENTRYPOINT to reduce
blast radius. Create a dedicated user/group (e.g., qtmesh user) and set
ownership of /workspace and any runtime-required files (and the installed app
path) to that user, then add USER <username> before ENTRYPOINT; ensure
docker-entrypoint.sh remains executable and does not require root-only
operations (or performs privileged setup and then drops privileges). Update any
references in docker-entrypoint.sh that assume root to work under the new user
or perform the privilege-drop there if needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f81218c-b048-4d42-9d3e-d338bd798a83

📥 Commits

Reviewing files that changed from the base of the PR and between 80753b6 and bae8dd4.

📒 Files selected for processing (5)
  • .dockerignore
  • .github/actions/qtmesh/action.yml
  • .github/workflows/docker-publish.yml
  • Dockerfile
  • docker-entrypoint.sh

Comment thread .github/actions/qtmesh/action.yml Outdated
Comment thread .github/workflows/docker-publish.yml Outdated
Comment thread .github/workflows/docker-publish.yml Outdated
Comment thread docker-entrypoint.sh
Comment thread Dockerfile
fernandotonon and others added 2 commits March 9, 2026 14:50
- Dockerfile: add non-root user (qtmesh, uid 10001), use deterministic
  COPY filename, symlink qtmesh through launcher script (sets LD_LIBRARY_PATH)
- docker-entrypoint.sh: fail fast with clear error if Xvfb never starts,
  use absolute paths through /usr/bin/qtmesh launcher
- docker-publish.yml: rename downloaded .deb to deterministic filename,
  extract version from .deb metadata (not CMakeLists.txt), only tag
  :latest for release events or unversioned dispatch
- action.yml: prevent shell injection by using env vars and bash arrays,
  run container with --user to match host UID
- deploy.yml: add /usr/bin/qtmesh symlink to .deb package so the qtmesh
  CLI command works after apt install

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/actions/qtmesh/action.yml:
- Around line 54-56: The heredoc uses the generic delimiter "EOF" which can
collide with OUTPUT content; update the three lines that write to GITHUB_OUTPUT
(the lines echoing "result<<EOF", echo "$OUTPUT", and echo "EOF") to use a
unique delimiter instead (e.g., "QTMESH_RESULT_<unique>" or a generated
timestamp/UUID) so the opening and closing heredoc markers match and cannot
appear in $OUTPUT; ensure the modified opening marker ("result<<DELIM") and the
final marker ("DELIM") are identical and unlikely to appear in command output.
- Around line 30-52: The docker image tag is injected unsafely via `${{
inputs.image-tag }}` in the docker run call; instead pass the image tag through
the action env (e.g., add INPUT_IMAGE_TAG: ${{ inputs.image-tag }} alongside the
other INPUT_* env entries) and reference it inside the run script as
"$INPUT_IMAGE_TAG" when invoking docker (replace the literal "ghcr.io/...:${{
inputs.image-tag }}" with a construct using the env var), so the value is
handled by the shell-safe variable expansion like the other inputs and not
pre-interpolated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d6f77565-6f35-4941-bb10-d9f60711487a

📥 Commits

Reviewing files that changed from the base of the PR and between bae8dd4 and 5c033e4.

📒 Files selected for processing (5)
  • .github/actions/qtmesh/action.yml
  • .github/workflows/deploy.yml
  • .github/workflows/docker-publish.yml
  • Dockerfile
  • docker-entrypoint.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/docker-publish.yml
  • docker-entrypoint.sh

Comment on lines +30 to +52
- id: run
shell: bash
env:
INPUT_COMMAND: ${{ inputs.command }}
INPUT_FILE: ${{ inputs.input-file }}
INPUT_OUTPUT_FILE: ${{ inputs.output-file }}
INPUT_OPTIONS: ${{ inputs.options }}
run: |
# Build command args safely via arrays to prevent injection
cmd=("$INPUT_COMMAND" "/workspace/$INPUT_FILE")
if [ -n "$INPUT_OUTPUT_FILE" ]; then
cmd+=("-o" "/workspace/$INPUT_OUTPUT_FILE")
fi
if [ -n "$INPUT_OPTIONS" ]; then
read -r -a opts <<< "$INPUT_OPTIONS"
cmd+=("${opts[@]}")
fi

OUTPUT=$(docker run --rm \
--user "$(id -u):$(id -g)" \
-v "${{ github.workspace }}:/workspace" \
"ghcr.io/fernandotonon/qtmesheditor:${{ inputs.image-tag }}" \
"${cmd[@]}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Shell injection mitigations are well-implemented, but image-tag input bypasses the safe pattern.

The env-var + array approach for command, input-file, output-file, and options correctly prevents shell injection. However, inputs.image-tag at line 51 is still directly interpolated via ${{ }}, which expands before bash runs and could allow metacharacter injection if a workflow passes an untrusted value.

🛡️ Suggested fix: Pass image-tag through env as well
       env:
         INPUT_COMMAND: ${{ inputs.command }}
         INPUT_FILE: ${{ inputs.input-file }}
         INPUT_OUTPUT_FILE: ${{ inputs.output-file }}
         INPUT_OPTIONS: ${{ inputs.options }}
+        INPUT_IMAGE_TAG: ${{ inputs.image-tag }}
       run: |
         # Build command args safely via arrays to prevent injection
         cmd=("$INPUT_COMMAND" "/workspace/$INPUT_FILE")
         if [ -n "$INPUT_OUTPUT_FILE" ]; then
           cmd+=("-o" "/workspace/$INPUT_OUTPUT_FILE")
         fi
         if [ -n "$INPUT_OPTIONS" ]; then
           read -r -a opts <<< "$INPUT_OPTIONS"
           cmd+=("${opts[@]}")
         fi

         OUTPUT=$(docker run --rm \
           --user "$(id -u):$(id -g)" \
           -v "${{ github.workspace }}:/workspace" \
-          "ghcr.io/fernandotonon/qtmesheditor:${{ inputs.image-tag }}" \
+          "ghcr.io/fernandotonon/qtmesheditor:${INPUT_IMAGE_TAG}" \
           "${cmd[@]}")
📝 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
- id: run
shell: bash
env:
INPUT_COMMAND: ${{ inputs.command }}
INPUT_FILE: ${{ inputs.input-file }}
INPUT_OUTPUT_FILE: ${{ inputs.output-file }}
INPUT_OPTIONS: ${{ inputs.options }}
run: |
# Build command args safely via arrays to prevent injection
cmd=("$INPUT_COMMAND" "/workspace/$INPUT_FILE")
if [ -n "$INPUT_OUTPUT_FILE" ]; then
cmd+=("-o" "/workspace/$INPUT_OUTPUT_FILE")
fi
if [ -n "$INPUT_OPTIONS" ]; then
read -r -a opts <<< "$INPUT_OPTIONS"
cmd+=("${opts[@]}")
fi
OUTPUT=$(docker run --rm \
--user "$(id -u):$(id -g)" \
-v "${{ github.workspace }}:/workspace" \
"ghcr.io/fernandotonon/qtmesheditor:${{ inputs.image-tag }}" \
"${cmd[@]}")
- id: run
shell: bash
env:
INPUT_COMMAND: ${{ inputs.command }}
INPUT_FILE: ${{ inputs.input-file }}
INPUT_OUTPUT_FILE: ${{ inputs.output-file }}
INPUT_OPTIONS: ${{ inputs.options }}
INPUT_IMAGE_TAG: ${{ inputs.image-tag }}
run: |
# Build command args safely via arrays to prevent injection
cmd=("$INPUT_COMMAND" "/workspace/$INPUT_FILE")
if [ -n "$INPUT_OUTPUT_FILE" ]; then
cmd+=("-o" "/workspace/$INPUT_OUTPUT_FILE")
fi
if [ -n "$INPUT_OPTIONS" ]; then
read -r -a opts <<< "$INPUT_OPTIONS"
cmd+=("${opts[@]}")
fi
OUTPUT=$(docker run --rm \
--user "$(id -u):$(id -g)" \
-v "${{ github.workspace }}:/workspace" \
"ghcr.io/fernandotonon/qtmesheditor:${INPUT_IMAGE_TAG}" \
"${cmd[@]}")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/actions/qtmesh/action.yml around lines 30 - 52, The docker image tag
is injected unsafely via `${{ inputs.image-tag }}` in the docker run call;
instead pass the image tag through the action env (e.g., add INPUT_IMAGE_TAG:
${{ inputs.image-tag }} alongside the other INPUT_* env entries) and reference
it inside the run script as "$INPUT_IMAGE_TAG" when invoking docker (replace the
literal "ghcr.io/...:${{ inputs.image-tag }}" with a construct using the env
var), so the value is handled by the shell-safe variable expansion like the
other inputs and not pre-interpolated.

Comment on lines +54 to +56
echo "result<<EOF" >> "$GITHUB_OUTPUT"
echo "$OUTPUT" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Heredoc delimiter "EOF" could collide with command output.

If the qtmesh command outputs a line containing only "EOF", the GitHub Actions output will be truncated. Consider using a more unique delimiter.

🔧 Suggested fix: Use a unique delimiter
-        echo "result<<EOF" >> "$GITHUB_OUTPUT"
+        DELIM="EOF_$(date +%s%N)"
+        echo "result<<$DELIM" >> "$GITHUB_OUTPUT"
         echo "$OUTPUT" >> "$GITHUB_OUTPUT"
-        echo "EOF" >> "$GITHUB_OUTPUT"
+        echo "$DELIM" >> "$GITHUB_OUTPUT"
📝 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
echo "result<<EOF" >> "$GITHUB_OUTPUT"
echo "$OUTPUT" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
DELIM="EOF_$(date +%s%N)"
echo "result<<$DELIM" >> "$GITHUB_OUTPUT"
echo "$OUTPUT" >> "$GITHUB_OUTPUT"
echo "$DELIM" >> "$GITHUB_OUTPUT"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/actions/qtmesh/action.yml around lines 54 - 56, The heredoc uses the
generic delimiter "EOF" which can collide with OUTPUT content; update the three
lines that write to GITHUB_OUTPUT (the lines echoing "result<<EOF", echo
"$OUTPUT", and echo "EOF") to use a unique delimiter instead (e.g.,
"QTMESH_RESULT_<unique>" or a generated timestamp/UUID) so the opening and
closing heredoc markers match and cannot appear in $OUTPUT; ensure the modified
opening marker ("result<<DELIM") and the final marker ("DELIM") are identical
and unlikely to appear in command output.

@sonarqubecloud

sonarqubecloud Bot commented Mar 9, 2026

Copy link
Copy Markdown

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