ci: Tag Docker images (#28088)

This commit is contained in:
Declan Carroll 2026-04-08 07:12:02 +01:00 committed by GitHub
parent fef91c97dd
commit a23fc0a867
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 3 deletions

View File

@ -9,7 +9,7 @@ class TagGenerator {
this.githubOutput = process.env.GITHUB_OUTPUT || null; this.githubOutput = process.env.GITHUB_OUTPUT || null;
} }
generate({ image, version, platform, includeDockerHub = false }) { generate({ image, version, platform, includeDockerHub = false, sha = '' }) {
let imageName = image; let imageName = image;
let versionSuffix = ''; let versionSuffix = '';
@ -27,6 +27,21 @@ class TagGenerator {
}; };
tags.all = [...tags.ghcr, ...tags.docker]; tags.all = [...tags.ghcr, ...tags.docker];
// Generate additional SHA-based tags for immutable references
if (sha) {
const shaVersion = `${version}-${sha}`;
const shaPlatformTag = `${shaVersion}${versionSuffix}${platformSuffix}`;
const shaGhcr = [`ghcr.io/${this.githubOwner}/${imageName}:${shaPlatformTag}`];
const shaDocker = includeDockerHub
? [`${this.dockerUsername}/${imageName}:${shaPlatformTag}`]
: [];
tags.all = [...tags.all, ...shaGhcr, ...shaDocker];
tags.ghcr = [...tags.ghcr, ...shaGhcr];
tags.docker = [...tags.docker, ...shaDocker];
tags.shaPrimaryTag = shaGhcr[0].replace(/-amd64$|-arm64$/, '');
}
return tags; return tags;
} }
@ -40,18 +55,21 @@ class TagGenerator {
`${prefixStr}docker_tag=${tags.docker[0] || ''}`, `${prefixStr}docker_tag=${tags.docker[0] || ''}`,
`${prefixStr}primary_tag=${primaryTag}`, `${prefixStr}primary_tag=${primaryTag}`,
]; ];
if (tags.shaPrimaryTag) {
outputs.push(`${prefixStr}sha_primary_tag=${tags.shaPrimaryTag}`);
}
appendFileSync(this.githubOutput, outputs.join('\n') + '\n'); appendFileSync(this.githubOutput, outputs.join('\n') + '\n');
} else { } else {
console.log(JSON.stringify(tags, null, 2)); console.log(JSON.stringify(tags, null, 2));
} }
} }
generateAll({ version, platform, includeDockerHub = false }) { generateAll({ version, platform, includeDockerHub = false, sha = '' }) {
const images = ['n8n', 'runners', 'runners-distroless']; const images = ['n8n', 'runners', 'runners-distroless'];
const results = {}; const results = {};
for (const image of images) { for (const image of images) {
const tags = this.generate({ image, version, platform, includeDockerHub }); const tags = this.generate({ image, version, platform, includeDockerHub, sha });
const prefix = image.replace('-distroless', '_distroless'); const prefix = image.replace('-distroless', '_distroless');
results[prefix] = tags; results[prefix] = tags;
@ -86,6 +104,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
version, version,
platform: getArg('platform'), platform: getArg('platform'),
includeDockerHub: hasFlag('include-docker'), includeDockerHub: hasFlag('include-docker'),
sha: getArg('sha') || '',
}); });
if (!generator.githubOutput) { if (!generator.githubOutput) {
console.log(JSON.stringify(results, null, 2)); console.log(JSON.stringify(results, null, 2));
@ -101,6 +120,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
version, version,
platform: getArg('platform'), platform: getArg('platform'),
includeDockerHub: hasFlag('include-docker'), includeDockerHub: hasFlag('include-docker'),
sha: getArg('sha') || '',
}); });
generator.output(tags); generator.output(tags);
} }

View File

@ -79,6 +79,9 @@ jobs:
primary_ghcr_manifest_tag: ${{ steps.determine-tags.outputs.n8n_primary_tag }} primary_ghcr_manifest_tag: ${{ steps.determine-tags.outputs.n8n_primary_tag }}
runners_primary_ghcr_manifest_tag: ${{ steps.determine-tags.outputs.runners_primary_tag }} runners_primary_ghcr_manifest_tag: ${{ steps.determine-tags.outputs.runners_primary_tag }}
runners_distroless_primary_ghcr_manifest_tag: ${{ steps.determine-tags.outputs.runners_distroless_primary_tag }} runners_distroless_primary_ghcr_manifest_tag: ${{ steps.determine-tags.outputs.runners_distroless_primary_tag }}
n8n_sha_manifest_tag: ${{ steps.determine-tags.outputs.n8n_sha_primary_tag }}
runners_sha_manifest_tag: ${{ steps.determine-tags.outputs.runners_sha_primary_tag }}
runners_distroless_sha_manifest_tag: ${{ steps.determine-tags.outputs.runners_distroless_sha_primary_tag }}
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@ -101,6 +104,7 @@ jobs:
--all \ --all \
--version "${{ needs.determine-build-context.outputs.n8n_version }}" \ --version "${{ needs.determine-build-context.outputs.n8n_version }}" \
--platform "${{ matrix.docker_platform }}" \ --platform "${{ matrix.docker_platform }}" \
--sha "${GITHUB_SHA::7}" \
${{ needs.determine-build-context.outputs.push_to_docker == 'true' && '--include-docker' || '' }} ${{ needs.determine-build-context.outputs.push_to_docker == 'true' && '--include-docker' || '' }}
echo "=== Generated Docker Tags ===" echo "=== Generated Docker Tags ==="
@ -228,6 +232,11 @@ jobs:
create_manifest "runners" "${{ needs.build-and-push-docker.outputs.runners_primary_ghcr_manifest_tag }}" create_manifest "runners" "${{ needs.build-and-push-docker.outputs.runners_primary_ghcr_manifest_tag }}"
create_manifest "runners-distroless" "${{ needs.build-and-push-docker.outputs.runners_distroless_primary_ghcr_manifest_tag }}" create_manifest "runners-distroless" "${{ needs.build-and-push-docker.outputs.runners_distroless_primary_ghcr_manifest_tag }}"
# Create SHA-tagged manifests (immutable references for deployments)
create_manifest "n8n (sha)" "${{ needs.build-and-push-docker.outputs.n8n_sha_manifest_tag }}"
create_manifest "runners (sha)" "${{ needs.build-and-push-docker.outputs.runners_sha_manifest_tag }}"
create_manifest "runners-distroless (sha)" "${{ needs.build-and-push-docker.outputs.runners_distroless_sha_manifest_tag }}"
- name: Create Docker Hub manifests - name: Create Docker Hub manifests
if: needs.determine-build-context.outputs.push_to_docker == 'true' if: needs.determine-build-context.outputs.push_to_docker == 'true'
run: | run: |
@ -241,6 +250,8 @@ jobs:
["runners-distroless"]="${VERSION}-distroless" ["runners-distroless"]="${VERSION}-distroless"
) )
SHORT_SHA="${GITHUB_SHA::7}"
for image in "${!images[@]}"; do for image in "${!images[@]}"; do
TAG_SUFFIX="${images[$image]}" TAG_SUFFIX="${images[$image]}"
IMAGE_NAME="${image//-distroless/}" # Remove -distroless from image name IMAGE_NAME="${image//-distroless/}" # Remove -distroless from image name
@ -250,6 +261,20 @@ jobs:
--tag "${DOCKER_BASE}/${IMAGE_NAME}:${TAG_SUFFIX}" \ --tag "${DOCKER_BASE}/${IMAGE_NAME}:${TAG_SUFFIX}" \
"${DOCKER_BASE}/${IMAGE_NAME}:${TAG_SUFFIX}-amd64" \ "${DOCKER_BASE}/${IMAGE_NAME}:${TAG_SUFFIX}-amd64" \
"${DOCKER_BASE}/${IMAGE_NAME}:${TAG_SUFFIX}-arm64" "${DOCKER_BASE}/${IMAGE_NAME}:${TAG_SUFFIX}-arm64"
# Create SHA-tagged manifest (immutable reference)
# For distroless, insert SHA between version and -distroless suffix
# to match docker-tags.mjs format: nightly-abc1234-distroless (not nightly-distroless-abc1234)
if [[ "$image" == *"-distroless"* ]]; then
SHA_SUFFIX="${VERSION}-${SHORT_SHA}-distroless"
else
SHA_SUFFIX="${TAG_SUFFIX}-${SHORT_SHA}"
fi
echo "Creating Docker Hub SHA manifest for $image: ${SHA_SUFFIX}"
docker buildx imagetools create \
--tag "${DOCKER_BASE}/${IMAGE_NAME}:${SHA_SUFFIX}" \
"${DOCKER_BASE}/${IMAGE_NAME}:${SHA_SUFFIX}-amd64" \
"${DOCKER_BASE}/${IMAGE_NAME}:${SHA_SUFFIX}-arm64"
done done
- name: Get manifest digests for attestation - name: Get manifest digests for attestation