Skip to content

docs: Update README examples to use v2.1.0 #6

docs: Update README examples to use v2.1.0

docs: Update README examples to use v2.1.0 #6

Workflow file for this run

name: PR Preview
on:
pull_request_target:
types: [opened, synchronize, reopened]
jobs:
request-approval:
name: Request Approval
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Comment requesting approval
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
// Check if approval comment already exists
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const approvalComment = comments.find(comment =>
comment.body.includes('<!-- approval-request-comment -->')
);
// Only create comment if it doesn't exist
if (!approvalComment) {
const body = `<!-- approval-request-comment -->
## ⚠️ &nbsp;Manual approval required
A repository owner must approve the Docker preview deployment for this PR.
**PR Author:** @${{ github.event.pull_request.user.login }}
**Head SHA:** \`${{ github.event.pull_request.head.sha }}\`
[Review and approve in Actions →](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body
});
}
pr-preview:
name: Deploy on Docker
runs-on: ubuntu-latest
needs: request-approval
environment:
name: "PR Preview"
url: https://github.com/${{ github.repository }}/pkgs/container/actions-clever-cloud
permissions:
contents: read
packages: write
pull-requests: write
steps:
# SECURITY: Checkout the base ref (trusted code) for the workflow
# This prevents untrusted PR code from accessing secrets
- name: Checkout base (trusted)
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ github.event.pull_request.base.sha }}
- name: Get PR head SHA
id: sha
run: echo "sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
- name: Get Docker tag
id: docker-tag
run: echo "tag=pr-${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
- name: Get package version
id: package
run: |
VERSION=$(jq -r '
.version |
if test("^[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?(\\+[0-9A-Za-z.-]+)?$")
then .
else error("Invalid semver format in package.json")
end
' package.json 2>&1)
if [ $? -ne 0 ]; then
echo "::error::$VERSION" # Expand the error into an annotation
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Validate inputs (security check)
run: |
# Ensure tag matches expected pattern
if [[ ! "${{ steps.docker-tag.outputs.tag }}" =~ ^pr-[0-9]+$ ]]; then
echo "::error::Security violation: Invalid PR tag pattern"
exit 1
fi
# Ensure version is a valid semver
if ! echo "${{ steps.package.outputs.version }}" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'; then
echo "::error::Security violation: Invalid version format"
exit 1
fi
- name: Collect Docker labels & tags
id: docker-labels-tags
run: |
echo 'labels<<__LABELS_EOF__' >> $GITHUB_OUTPUT
echo "org.opencontainers.image.title=47ng/actions-clever-cloud" >> $GITHUB_OUTPUT
echo "org.opencontainers.image.description=GitHub action to deploy to Clever Cloud (PR preview)" >> $GITHUB_OUTPUT
echo "org.opencontainers.image.version=${{ steps.package.outputs.version }}-pr.${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
echo "org.opencontainers.image.revision=${{ steps.sha.outputs.sha }}" >> $GITHUB_OUTPUT
echo "org.opencontainers.image.licenses=MIT" >> $GITHUB_OUTPUT
echo "org.opencontainers.image.source=https://github.com/${{github.repository}}/tree/${{ steps.sha.outputs.sha }}" >> $GITHUB_OUTPUT
echo "org.opencontainers.image.documentation=https://github.com/${{github.repository}}/pull/${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
echo "org.opencontainers.image.url=https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}" >> $GITHUB_OUTPUT
echo '__LABELS_EOF__' >> $GITHUB_OUTPUT
echo 'tags<<__TAGS_EOF__' >> $GITHUB_OUTPUT
echo "ghcr.io/47ng/actions-clever-cloud:${{ steps.docker-tag.outputs.tag }}" >> $GITHUB_OUTPUT
echo "ghcr.io/47ng/actions-clever-cloud:git-${{ steps.sha.outputs.sha }}" >> $GITHUB_OUTPUT
echo '__TAGS_EOF__' >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
# SECURITY: Checkout the PR head for building
# We do this AFTER extracting all metadata to prevent tampering
- name: Checkout PR head (untrusted code)
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
ref: ${{ steps.sha.outputs.sha }}
- name: Build and push
id: docker-build-push
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
labels: "${{ steps.docker-labels-tags.outputs.labels }}"
tags: "${{ steps.docker-labels-tags.outputs.tags }}"
push: true
- name: Generate step summary
run: |
echo "## 🐳 &nbsp;Docker image" >> $GITHUB_STEP_SUMMARY
echo "Digest: \`${{ steps.docker-build-push.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY
echo "### 📌 &nbsp;Tags" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.docker-labels-tags.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "### 🏷 &nbsp;Labels" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.docker-labels-tags.outputs.labels }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
- name: Comment on PR
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const body = `<!-- docker-build-comment -->
## 🐳 &nbsp;Docker image preview
Preview this PR in your workflow:
\`\`\`yaml
# Use the PR number to follow changes in this PR
- uses: docker://ghcr.io/47ng/actions-clever-cloud:${{ steps.docker-tag.outputs.tag }}
# Use the git SHA for pinning to a specific commit
- uses: docker://ghcr.io/47ng/actions-clever-cloud:git-${{ steps.sha.outputs.sha }}
\`\`\`
<details>
<summary>Image metadata</summary>
<br/>
Digest: \`${{ steps.docker-build-push.outputs.digest }}\`
### 📌 &nbsp;Tags
\`\`\`
${{ steps.docker-labels-tags.outputs.tags }}
\`\`\`
### 🏷 &nbsp;Labels
\`\`\`
${{ steps.docker-labels-tags.outputs.labels }}
\`\`\`
</details>
---
<sub>🤖 This comment is updated on every push</sub>`;
// Find existing comment by marker
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.body.startsWith('<!-- docker-build-comment -->')
);
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}