[#47] Add support for Dockerfiles + publishing#418
Conversation
|
No actionable comments were generated in the recent review. 🎉 📝 WalkthroughWalkthroughAdds optional Docker scaffold: Dockerfile and entrypoint, init prompts and removal logic, test and release GitHub Actions workflows (multi‑arch build/push), fixture and test updates, documentation and cspell entries for "Buildx", and minor CI coverage exclude tweak. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Tag as "Git Tag (push)"
participant GH as "GitHub Actions Runner"
participant QEMU as "QEMU setup"
participant Buildx as "Docker Buildx"
participant Meta as "docker/metadata-action"
participant Registry as "Docker Hub"
Tag->>GH: Trigger "Release Docker" workflow
GH->>GH: checkout repo
GH->>QEMU: setup QEMU emulation
GH->>Buildx: setup Buildx builder
GH->>Meta: compute image tags & labels
GH->>Buildx: build multi-arch images (linux/amd64, linux/arm64) with tags/labels
Buildx->>Registry: push images
Registry-->>GH: push status
GH-->>Tag: workflow completed
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
This comment has been minimized.
This comment has been minimized.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #418 +/- ##
==========================================
- Coverage 21.42% 20.49% -0.94%
==========================================
Files 5 6 +1
Lines 350 366 +16
==========================================
Hits 75 75
- Misses 275 291 +16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
063eeab to
bcd4fe6
Compare
This comment has been minimized.
This comment has been minimized.
bcd4fe6 to
cde2fcc
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
.github/workflows/release-docker.yml (2)
44-44: Preferlinux/amd64overlinux/amd64's aliaslinux/x86_64for platform consistency.Docker buildx and the OCI spec use
linux/amd64as the canonical platform string. Whilelinux/x86_64is recognized,linux/amd64is the standard form used in all Docker documentation and avoids potential edge-case rejection by some registries or manifest inspection tools.♻️ Proposed fix
- platforms: linux/x86_64,linux/arm64 + platforms: linux/amd64,linux/arm64🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release-docker.yml at line 44, Replace the non-canonical platform alias in the GitHub Actions workflow by changing the platforms string used in the release-docker job: update the value "platforms: linux/x86_64,linux/arm64" to use the canonical "linux/amd64" form (i.e., "platforms: linux/amd64,linux/arm64") so buildx and registries see the standard OCI platform name.
37-44: Consider adding a build cache to speed up release builds.Unlike
test-docker.yml, this workflow has nocache-from/cache-toconfiguration, so every tag push rebuilds from scratch. Adding GitHub Actions cache (consistent with the test workflow) would cut build times significantly.♻️ Proposed fix
- name: Build and push Docker image uses: docker/build-push-action@v6 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 + cache-from: type=gha + cache-to: type=gha,mode=max🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release-docker.yml around lines 37 - 44, The Docker build step ("Build and push Docker image" using docker/build-push-action@v6) has no build cache configured so every release rebuilds from scratch; add BuildKit cache settings by adding cache-from and cache-to entries under the step's with: block (e.g., cache-from: type=gha,scope or key; cache-to: type=gha,mode=max or inline) so the workflow reuses the GitHub Actions cache between runs; ensure you reference the same cache key/descriptor (or include ${{ steps.meta.outputs.tags }} or ${{ github.ref }} in the key) so successive builds can pull from and push to the cache.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.scaffold/docs/content/docker/README.mdx:
- Line 72: Replace the non-canonical platform string "linux/x86_64" with the
OCI-canonical "linux/amd64" wherever it appears (e.g., in the multi-arch image
list text and the CI workflow platform list). Search for the exact token
"linux/x86_64" and update it to "linux/amd64" in both occurrences to ensure
consistency with the OCI/Go GOARCH convention and with the existing
"linux/arm64" entry.
In
@.scaffold/tests/phpunit/fixtures/init/docker/.github/workflows/test-docker.yml:
- Around line 53-56: The "Setup tmate session" step's if-condition uses
github.event.inputs.enable_terminal which is a string ("true"/"false") and
therefore always truthy; update the condition to use the inputs context so the
boolean is respected (e.g., replace github.event.inputs.enable_terminal with
inputs.enable_terminal in the if expression) and keep the existing cancelled()
check (so the final if remains something like: !cancelled() &&
inputs.enable_terminal) to ensure the tmate step only runs when the checkbox is
actually checked.
In `@init.sh`:
- Around line 593-597: The current global replace_string_content call is
overwriting the Dockerfile's org.opencontainers.image.source by substituting the
image name; update the flow so the GitHub source URL is set from a dedicated
placeholder (e.g., __GITHUB_SOURCE_URL__) rather than derived from
docker_image_name: add code in process_internal (or just before the Docker block
in main) to replace that placeholder with the full
"https://github.com/${namespace}/${project}" value, and keep the existing
replace_string_content "yournamespace/yourproject" "${docker_image_name}" only
for the image name; this ensures replace_string_content, replace_string_content,
process_internal, docker_image_name and remove_docker usages no longer collide
and the org.opencontainers.image.source label remains the correct GitHub URL.
---
Nitpick comments:
In @.github/workflows/release-docker.yml:
- Line 44: Replace the non-canonical platform alias in the GitHub Actions
workflow by changing the platforms string used in the release-docker job: update
the value "platforms: linux/x86_64,linux/arm64" to use the canonical
"linux/amd64" form (i.e., "platforms: linux/amd64,linux/arm64") so buildx and
registries see the standard OCI platform name.
- Around line 37-44: The Docker build step ("Build and push Docker image" using
docker/build-push-action@v6) has no build cache configured so every release
rebuilds from scratch; add BuildKit cache settings by adding cache-from and
cache-to entries under the step's with: block (e.g., cache-from: type=gha,scope
or key; cache-to: type=gha,mode=max or inline) so the workflow reuses the GitHub
Actions cache between runs; ensure you reference the same cache key/descriptor
(or include ${{ steps.meta.outputs.tags }} or ${{ github.ref }} in the key) so
successive builds can pull from and push to the cache.
|
|
||
| 1. Sets up QEMU and Docker Buildx for multi-architecture builds | ||
| 2. Authenticates with Docker Hub | ||
| 3. Builds and pushes multi-arch images (`linux/x86_64`, `linux/arm64`) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check if the file exists and examine line 72
cat -n ".scaffold/docs/content/docker/README.mdx" | sed -n '68,76p'Repository: AlexSkrypnyk/scaffold
Length of output: 425
🏁 Script executed:
# Run the verification script from the review comment
rg -n "linux/x86_64" --type yaml
rg -n "linux/x86_64" --glob "*.mdx" --glob "*.md"Repository: AlexSkrypnyk/scaffold
Length of output: 47
🏁 Script executed:
# Also check what Docker documentation says about platform strings
# Let's search the codebase for any other platform strings being used
rg -n "linux/amd64|linux/arm64|linux/x86_64|linux/arm32" --type yaml --type jsonRepository: AlexSkrypnyk/scaffold
Length of output: 47
🏁 Script executed:
# Find workflow files
fd -e yml -e yaml | grep -i workflow || fd -e yml -e yamlRepository: AlexSkrypnyk/scaffold
Length of output: 86
🏁 Script executed:
# Check if release-docker.yml or similar workflow files exist
find . -name "*docker*.yml" -o -name "*release*.yml" 2>/dev/null | head -20Repository: AlexSkrypnyk/scaffold
Length of output: 1383
🌐 Web query:
Docker OCI platform strings canonical linux/amd64 linux/x86_64
💡 Result:
In OCI/Docker, the canonical platform syntax is:
os/arch[/variant](often called a “platform specifier”), e.g.linux/amd64(pkg.go.dev)
For the arch portion, OCI specifies you should use Go’s GOARCH values (and os should use Go’s GOOS values). (oci-playground.github.io)
So for x86-64 Linux:
- Canonical:
linux/amd64 - Not canonical (because
x86_64is not a GoGOARCHvalue):linux/x86_64(oci-playground.github.io)
Some tooling may accept x86_64 as an alias and normalize it to amd64, but for OCI manifests/indexes and for best interoperability, use amd64 (optionally adding /variant only when applicable, e.g. linux/arm64/v8). (oci-playground.github.io)
Citations:
- 1: https://pkg.go.dev/github.com/containerd/platforms?utm_source=openai
- 2: https://oci-playground.github.io/specs-latest/specs/image/v1.1.0-rc4/oci-image-spec.html
- 3: https://oci-playground.github.io/specs-latest/specs/image/v1.1.0-rc4/oci-image-spec.html
- 4: https://oci-playground.github.io/specs-latest/specs/image/v1.1.0-rc4/oci-image-spec.html
🏁 Script executed:
# Examine the release-docker.yml workflow to see what platform strings it uses
grep -n "linux/" "./.github/workflows/release-docker.yml"Repository: AlexSkrypnyk/scaffold
Length of output: 113
Use canonical Docker platform string linux/amd64 instead of linux/x86_64
Per OCI specification, the canonical platform string for x86-64 is linux/amd64 (based on Go's GOARCH values), not linux/x86_64. While some tooling accepts linux/x86_64 as an alias, it is non-canonical and inconsistent with linux/arm64.
This non-canonical string appears in two places:
.scaffold/docs/content/docker/README.mdxline 72./.github/workflows/release-docker.ymlline 44
Both should use the canonical linux/amd64 for consistency with OCI standards and Docker documentation.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.scaffold/docs/content/docker/README.mdx at line 72, Replace the
non-canonical platform string "linux/x86_64" with the OCI-canonical
"linux/amd64" wherever it appears (e.g., in the multi-arch image list text and
the CI workflow platform list). Search for the exact token "linux/x86_64" and
update it to "linux/amd64" in both occurrences to ensure consistency with the
OCI/Go GOARCH convention and with the existing "linux/arm64" entry.
.scaffold/tests/phpunit/fixtures/init/docker/.github/workflows/test-docker.yml
Show resolved
Hide resolved
cde2fcc to
63a79be
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
🧹 Nitpick comments (3)
.scaffold/tests/phpunit/src/InitTest.php (1)
114-126: Consider adding a test case for a customdocker_image_name.The current
dockerdataset only exercisesTUI_DEFAULT(accept the pre-fillednamespace/projectvalue) fordocker_image_name. There is no case that provides a literal string (e.g.,'myorg/custom-image'), so the text-input branch of that prompt and any substitution logic ininit.share not independently validated. Given the snapshot-based approach, a second case would be a low-cost way to lock in that behaviour.🔍 Suggested additional dataset
yield 'docker custom image name' => [ [ 'use_php' => self::$tuiNo, 'use_php_command' => self::TUI_SKIP, 'php_command_name' => self::TUI_SKIP, 'use_php_command_build' => self::TUI_SKIP, 'use_php_script' => self::TUI_SKIP, 'use_nodejs' => self::$tuiNo, 'use_shell' => self::$tuiNo, 'use_docker' => self::$tuiYes, + 'docker_image_name' => 'myorg/custom-image', ], ];🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.scaffold/tests/phpunit/src/InitTest.php around lines 114 - 126, Add a test dataset exercising a literal docker image name because the existing "docker" case only uses TUI_DEFAULT; add a new yield entry (e.g., key "docker custom image name") in the same dataset provider inside InitTest.php that mirrors the existing docker case (keeping use_docker => self::$tuiYes and the same TUI_SKIP/use flags) but sets 'docker_image_name' to a concrete string like 'myorg/custom-image' so the text-input branch and any substitution logic for docker_image_name are exercised..github/workflows/release-docker.yml (1)
37-44: Consider adding build cache to the release workflow.The test workflow configures
cache-from: type=gha/cache-to: type=gha,mode=max, but the release workflow omits cache configuration entirely. For multi-arch builds this results in a cold-start on every release tag, lengthening release times. Adding the same GHA cache configuration would reuse layers warmed by CI runs.♻️ Proposed addition
- name: Build and push Docker image uses: docker/build-push-action@v6 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/x86_64,linux/arm64 + cache-from: type=gha + cache-to: type=gha,mode=max🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release-docker.yml around lines 37 - 44, The release workflow's Docker step ("Build and push Docker image" using docker/build-push-action@v6) lacks cache configuration causing cold multi-arch builds; add the same GitHub Actions layer cache inputs used in CI: set with.cache-from to include "type=gha" and with.cache-to to "type=gha,mode=max" (and optionally with.cache-control or targets if used in CI) so the action can reuse warmed layers across runs and speed up multi-arch builds.init.sh (1)
534-535: Optional: showshell_command_namein the summary for consistency withdocker_image_name.This PR adds
docker_image_nameto the summary, butshell_command_name(set at line 504) is still silently omitted. A user who customises both would see the Docker image name but not the renamed shell script in the confirmation screen.♻️ Suggested addition to the summary block
echo "Use Shell : ${use_shell}" +[ "${use_shell}" = "y" ] && echo " Shell command name : ${shell_command_name}" echo "Use Docker : ${use_docker}" [ "${use_docker}" = "y" ] && echo " Docker image name : ${docker_image_name}"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@init.sh` around lines 534 - 535, The summary omits the user-provided shell_command_name while showing docker_image_name; add a matching summary line for shell_command_name so users see both customizations. Locate the summary block that prints use_docker and docker_image_name and add an echo for shell_command_name (e.g., print " Shell command name : ${shell_command_name}") and conditionally display it only when shell_command_name is non-empty (or when its relevant flag is set), similar to how docker_image_name is printed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In @.github/workflows/release-docker.yml:
- Line 44: Replace the non-canonical platform identifier in the GitHub Actions
docker build matrix: update the platforms entry that currently lists
"linux/x86_64,linux/arm64" to use "linux/amd64" instead of "linux/x86_64" (i.e.,
"platforms: linux/amd64,linux/arm64") so the platforms key uses the canonical
amd64 name.
In @.scaffold/docs/content/docker/README.mdx:
- Line 72: The platform string "linux/x86_64" in the Docker README is incorrect;
replace every occurrence of "linux/x86_64" with the OCI-canonical "linux/amd64"
(e.g., update the list item that currently reads "Builds and pushes multi-arch
images (`linux/x86_64`, `linux/arm64`)") so the documentation uses the correct
platform identifier.
In `@init.sh`:
- Around line 593-597: The replacement call replace_string_content
"yournamespace/yourproject" ${docker_image_name} in init.sh may still touch
non-Docker files; run a recursive search for the literal
"yournamespace/yourproject" (excluding .git, vendor, node_modules, etc.) and
confirm only Dockerfile/entrypoint/Docker workflow files contain it; if any
other files contain it, either (A) change those files to use a distinct
placeholder for the GitHub source URL used in Dockerfile, or (B) restrict
replace_string_content to only operate on Docker-related files (referencing the
init.sh call and the docker_image_name variable) so only intended files are
overwritten; update tests or add the verification script shown in the review to
prevent regressions.
---
Nitpick comments:
In @.github/workflows/release-docker.yml:
- Around line 37-44: The release workflow's Docker step ("Build and push Docker
image" using docker/build-push-action@v6) lacks cache configuration causing cold
multi-arch builds; add the same GitHub Actions layer cache inputs used in CI:
set with.cache-from to include "type=gha" and with.cache-to to
"type=gha,mode=max" (and optionally with.cache-control or targets if used in CI)
so the action can reuse warmed layers across runs and speed up multi-arch
builds.
In @.scaffold/tests/phpunit/src/InitTest.php:
- Around line 114-126: Add a test dataset exercising a literal docker image name
because the existing "docker" case only uses TUI_DEFAULT; add a new yield entry
(e.g., key "docker custom image name") in the same dataset provider inside
InitTest.php that mirrors the existing docker case (keeping use_docker =>
self::$tuiYes and the same TUI_SKIP/use flags) but sets 'docker_image_name' to a
concrete string like 'myorg/custom-image' so the text-input branch and any
substitution logic for docker_image_name are exercised.
In `@init.sh`:
- Around line 534-535: The summary omits the user-provided shell_command_name
while showing docker_image_name; add a matching summary line for
shell_command_name so users see both customizations. Locate the summary block
that prints use_docker and docker_image_name and add an echo for
shell_command_name (e.g., print " Shell command name : ${shell_command_name}")
and conditionally display it only when shell_command_name is non-empty (or when
its relevant flag is set), similar to how docker_image_name is printed.
- Added template Dockerfile and entrypoint.sh - Added test-docker.yml workflow (build + hadolint lint) - Added release-docker.yml workflow (multi-arch push to Docker Hub) - Added 'Use Docker' prompt to init.sh (defaults to No) - Added Docker image name prompt (defaults to namespace/project) - Added remove_docker() function for cleanup when Docker not selected - Added DOCKER token blocks to CLAUDE.md - Added 'docker' test case to InitTest.php - Updated test fixtures via snapshot auto-update - All 14 init tests passing
63a79be to
e7dba77
Compare
This comment has been minimized.
This comment has been minimized.
- Updated exclude pattern to catch entrypoint.sh in root and subdirectories - Addresses feedback from @AlexSkrypnyk in PR review
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
.github/workflows/release-docker.yml (1)
3-6: Broad tag glob'*'triggers release on every tag — intentional?
tags: - '*'will fire the release workflow on any tag push (e.g.v1.0.0,beta,test-tag), immediately pushing to Docker Hub. Consider tightening the pattern (e.g.'v[0-9]*') to avoid accidental publishes from non-version tags.♻️ Optional tighter tag filter
on: push: tags: - - '*' + - 'v[0-9]*'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release-docker.yml around lines 3 - 6, The workflow trigger currently uses a broad tag glob (on -> push -> tags: '*') which fires on every tag; narrow the pattern to only semantic/version tags by replacing the glob with a stricter pattern (for example 'v[0-9]*' or another regex matching your release tag format) in the on.push.tags entry of the release-docker.yml workflow so Docker publishes only for intended version tags.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.scaffold/tests/phpunit/fixtures/init/docker/Dockerfile:
- Around line 1-11: The Dockerfile currently leaves the container running as
root (no USER), so add steps to create a dedicated non-root user and switch to
it: create a group and user (e.g., addgroup/adduser or use adduser -D with
addgroup), chown the copied artifact (/usr/local/bin/entrypoint.sh) to that user
and set appropriate permissions, and then add a USER instruction before
ENTRYPOINT to switch to that non-root user; update the Dockerfile lines around
the COPY of entrypoint.sh and the ENTRYPOINT instruction accordingly so
ENTRYPOINT still points to /usr/local/bin/entrypoint.sh but runs as the new
non-root user.
In `@init.sh`:
- Around line 593-597: The current unconditional call to replace_string_content
"yournamespace/yourproject" "${docker_image_name}" corrupts non-Docker scaffold
files; update init.sh to (a) stop doing a global replace at that location and
instead only replace docker image references in Docker-specific files (e.g.,
Dockerfile, workflows) or call replace_string_content with an explicit file
list/grep-limited target, (b) introduce a separate placeholder (e.g.,
yourgithubnamespace/yourgithubproject) for GitHub source/repo references used in
Dockerfile labels and other scaffold files, and (c) ensure process_internal
still runs to restore scaffold-specific names; reference the existing symbols
use_docker, docker_image_name, replace_string_content, process_internal, and
remove_docker when making these changes.
---
Duplicate comments:
In
@.scaffold/tests/phpunit/fixtures/init/docker/.github/workflows/test-docker.yml:
- Around line 53-56: The "Setup tmate session" job step uses an if condition
that treats github.event.inputs.enable_terminal as always truthy; update the
condition on that step to perform an explicit comparison (e.g., compare to the
expected string/boolean value) or remove the redundant check if another guard
already ensures enable_terminal is meaningful; specifically, locate the step
named "Setup tmate session" and change the if expression that currently
references github.event.inputs.enable_terminal so it does an explicit equality
check (or drop the check) to avoid the always-truthy behavior.
---
Nitpick comments:
In @.github/workflows/release-docker.yml:
- Around line 3-6: The workflow trigger currently uses a broad tag glob (on ->
push -> tags: '*') which fires on every tag; narrow the pattern to only
semantic/version tags by replacing the glob with a stricter pattern (for example
'v[0-9]*' or another regex matching your release tag format) in the on.push.tags
entry of the release-docker.yml workflow so Docker publishes only for intended
version tags.
| # hadolint global ignore=DL3018 | ||
| FROM alpine:3 | ||
|
|
||
| LABEL org.opencontainers.image.authors="Luke Skywalker" \ | ||
| org.opencontainers.image.source="https://github.com/yodashut/force-crystal" | ||
|
|
||
| RUN apk add --no-cache bash | ||
|
|
||
| COPY entrypoint.sh /usr/local/bin/entrypoint.sh | ||
|
|
||
| ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] |
There was a problem hiding this comment.
Container runs as root — add a non-root USER directive.
Trivy rule DS-0002: the Dockerfile has no USER instruction, so every container spawned from this image runs as root. As a scaffold template this sets the pattern for all downstream projects.
🛡️ Proposed fix — add a dedicated non-root user
RUN apk add --no-cache bash
+
+RUN addgroup -S app && adduser -S app -G app
+USER app
COPY entrypoint.sh /usr/local/bin/entrypoint.sh📝 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.
| # hadolint global ignore=DL3018 | |
| FROM alpine:3 | |
| LABEL org.opencontainers.image.authors="Luke Skywalker" \ | |
| org.opencontainers.image.source="https://github.com/yodashut/force-crystal" | |
| RUN apk add --no-cache bash | |
| COPY entrypoint.sh /usr/local/bin/entrypoint.sh | |
| ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] | |
| # hadolint global ignore=DL3018 | |
| FROM alpine:3 | |
| LABEL org.opencontainers.image.authors="Luke Skywalker" \ | |
| org.opencontainers.image.source="https://github.com/yodashut/force-crystal" | |
| RUN apk add --no-cache bash | |
| RUN addgroup -S app && adduser -S app -G app | |
| USER app | |
| COPY entrypoint.sh /usr/local/bin/entrypoint.sh | |
| ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] |
🧰 Tools
🪛 Trivy (0.69.1)
[error] 1-1: Image user should not be 'root'
Specify at least 1 USER command in Dockerfile with non-root user as argument
Rule: DS-0002
(IaC/Dockerfile)
[error] 1-1: Image user should not be 'root'
Specify at least 1 USER command in Dockerfile with non-root user as argument
Rule: DS-0002
(IaC/Dockerfile)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.scaffold/tests/phpunit/fixtures/init/docker/Dockerfile around lines 1 - 11,
The Dockerfile currently leaves the container running as root (no USER), so add
steps to create a dedicated non-root user and switch to it: create a group and
user (e.g., addgroup/adduser or use adduser -D with addgroup), chown the copied
artifact (/usr/local/bin/entrypoint.sh) to that user and set appropriate
permissions, and then add a USER instruction before ENTRYPOINT to switch to that
non-root user; update the Dockerfile lines around the COPY of entrypoint.sh and
the ENTRYPOINT instruction accordingly so ENTRYPOINT still points to
/usr/local/bin/entrypoint.sh but runs as the new non-root user.
| if [ "${use_docker}" = "y" ]; then | ||
| replace_string_content "yournamespace/yourproject" "${docker_image_name}" | ||
| else | ||
| remove_docker | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 1. Check what placeholder(s) the Dockerfile uses for image name vs GitHub source URL
echo "=== Dockerfile contents (image-name and source label lines) ==="
grep -n "yournamespace\|yourproject\|opencontainers\|image.source\|docker_image\|FROM" Dockerfile 2>/dev/null || echo "Dockerfile not found"
# 2. Check if non-Docker scaffold files reference "yournamespace/yourproject" directly
# (excluding Dockerfile, entrypoint.sh, and the two docker workflows)
echo ""
echo "=== Non-Docker files with 'yournamespace/yourproject' ==="
grep -rn "yournamespace/yourproject" \
--exclude="Dockerfile" \
--exclude="entrypoint.sh" \
--exclude-dir=".git" \
--exclude-dir="node_modules" \
--exclude-dir="vendor" \
. 2>/dev/null | grep -v "test-docker\|release-docker\|init.sh" || echo "(none)"Repository: AlexSkrypnyk/scaffold
Length of output: 3264
Critical: Global replace of "yournamespace/yourproject" corrupts multiple non-Docker scaffold files.
The code at line 594 performs a global replace_string_content "yournamespace/yourproject" "${docker_image_name}" before process_internal runs. This has two confirmed impacts:
-
Dockerfile source label is overwritten: The
org.opencontainers.image.sourcelabel in the Dockerfile (line 5) contains the literal string"https://github.com/yournamespace/yourproject". This will be replaced with the Docker image name, corrupting the GitHub source URL metadata. -
Multiple scaffold files are corrupted: Non-Docker scaffold files contain
"yournamespace/yourproject"directly and will have this replaced withdocker_image_name:composer.json(package name, homepage, source URLs)README.dist.md(GitHub badges and links)package.json(package name, repository, bugs URLs)docs/docusaurus.config.js(GitHub URLs)docs/package.jsonanddocs/package-lock.json(package names)
Since
process_internalonly recreates"yournamespace/yourproject"from pre-existing"AlexSkrypnyk/scaffold"occurrences, these direct uses are never corrected.
Fix: Use distinct placeholders—e.g., yourgithubnamespace/yourgithubproject for the Dockerfile source label and other GitHub references, and apply the docker_image_name replacement only to files where it belongs (Dockerfile image layers, workflows).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@init.sh` around lines 593 - 597, The current unconditional call to
replace_string_content "yournamespace/yourproject" "${docker_image_name}"
corrupts non-Docker scaffold files; update init.sh to (a) stop doing a global
replace at that location and instead only replace docker image references in
Docker-specific files (e.g., Dockerfile, workflows) or call
replace_string_content with an explicit file list/grep-limited target, (b)
introduce a separate placeholder (e.g., yourgithubnamespace/yourgithubproject)
for GitHub source/repo references used in Dockerfile labels and other scaffold
files, and (c) ensure process_internal still runs to restore scaffold-specific
names; reference the existing symbols use_docker, docker_image_name,
replace_string_content, process_internal, and remove_docker when making these
changes.
Closes #47
Changes
Dockerfile(minimal alpine + bash + entrypoint) andentrypoint.shtest-docker.ymlworkflow — builds image + hadolint lintrelease-docker.ymlworkflow — multi-arch (linux/x86_64,linux/arm64) push to Docker Hub on tagUse Dockerprompt toinit.sh(defaults to No)namespace/project)remove_docker()function +#;< DOCKER/#;> DOCKERtoken blocksCLAUDE.mddockertest case toInitTest.phpwith full snapshot fixtureBuildxto cspell dictionaryDocker Hub Secrets
The release workflow expects:
DOCKER_USER— Docker Hub usernameDOCKER_PASS— Docker Hub access tokenBased on the pattern from docker-wait-for-dependencies.
Overview
This PR closes issue #47 by adding optional Docker support and publishing workflows to the scaffold. It introduces a template Dockerfile and entrypoint, CI workflows to test and publish images, interactive init prompts to opt-in to Docker, cleanup hooks, documentation, and test fixtures.
Key Changes
Docker files
GitHub Actions workflows
Initialization and removal
Documentation
Test fixtures and tests
Minor updates
Secrets required for release workflow
Testing
Possibly related to: issue #47