Updated Linux workflow

This commit is contained in:
Alexey Pustovalov 2026-03-27 21:20:21 +09:00
parent a439cdb47a
commit c9da78e52b
5 changed files with 179 additions and 78 deletions

18
.github/actions/attest-image/action.yml vendored Normal file
View file

@ -0,0 +1,18 @@
name: Attest image
description: Generate and push attestation for image
inputs:
subject_name:
required: true
subject_digest:
required: true
runs:
using: composite
steps:
- name: Attest image
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
with:
subject-name: ${{ inputs.subject_name }}
subject-digest: ${{ inputs.subject_digest }}
push-to-registry: true

34
.github/actions/cosign-sign/action.yml vendored Normal file
View file

@ -0,0 +1,34 @@
name: Cosign sign images
description: Sign image tags with digest via cosign
inputs:
digest:
required: true
description: Built image digest
tags:
required: true
description: Space-separated image tags
runs:
using: composite
steps:
- name: Sign images
shell: bash
env:
DIGEST: ${{ inputs.digest }}
TAGS: ${{ inputs.tags }}
run: |
set -euo pipefail
images=()
for tag in ${TAGS}; do
images+=("${tag}@${DIGEST}")
done
echo "::group::Images to sign"
printf '%s\n' "${images[@]}"
echo "::endgroup::"
echo "::group::Signing"
cosign sign --yes "${images[@]}"
echo "::endgroup::"

View file

@ -0,0 +1,38 @@
name: Cosign verify image
description: Verify container image signature with cosign and GitHub OIDC
inputs:
image:
required: true
description: Image reference in name@digest format
oidc_issuer:
required: true
description: OIDC issuer regexp
identity_regexp:
required: true
description: Certificate identity regexp
runs:
using: composite
steps:
- name: Verify image signature
shell: bash
env:
IMAGE: ${{ inputs.image }}
OIDC_ISSUER: ${{ inputs.oidc_issuer }}
IDENTITY_REGEX: ${{ inputs.identity_regexp }}
run: |
set -euo pipefail
echo "::group::Image sign data"
echo "OIDC issuer=$OIDC_ISSUER"
echo "Identity=$IDENTITY_REGEX"
echo "Image to verify=$IMAGE"
echo "::endgroup::"
echo "::group::Verify signature"
cosign verify \
--certificate-oidc-issuer-regexp "$OIDC_ISSUER" \
--certificate-identity-regexp "$IDENTITY_REGEX" \
"$IMAGE" | jq
echo "::endgroup::"

56
.github/actions/docker-meta/action.yml vendored Normal file
View file

@ -0,0 +1,56 @@
name: Docker metadata
description: Generate Docker tags and labels consistently
inputs:
image:
required: true
description: Full image name, e.g. docker.io/org/prefix-image
os:
required: true
description: OS suffix/prefix for tags
current_branch:
required: true
description: Current branch name
is_default_branch:
required: true
description: 'true' or 'false'
trunk_only_event:
required: true
description: 'true' or 'false'
event_name:
required: true
description: GitHub event name
outputs:
tags:
description: Generated Docker tags
value: ${{ steps.meta.outputs.tags }}
labels:
description: Generated Docker labels
value: ${{ steps.meta.outputs.labels }}
json:
description: Full metadata-action json output
value: ${{ steps.meta.outputs.json }}
version:
description: Generated version
value: ${{ steps.meta.outputs.version }}
runs:
using: composite
steps:
- name: Generate tags
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: ${{ inputs.image }}
context: ${{ inputs.trunk_only_event == 'true' && 'git' || '' }}
tags: |
type=semver,enable=${{ inputs.current_branch != 'trunk' }},pattern={{version}},prefix=${{ inputs.os }}-
type=semver,enable=${{ inputs.current_branch != 'trunk' }},pattern={{version}},suffix=-${{ inputs.os }}
type=ref,enable=${{ inputs.current_branch != 'trunk' && inputs.event_name != 'workflow_dispatch' }},event=branch,prefix=${{ inputs.os }}-,suffix=-latest
type=ref,enable=${{ inputs.current_branch != 'trunk' && inputs.event_name != 'workflow_dispatch' }},event=branch,suffix=-${{ inputs.os }}-latest
type=raw,enable=${{ inputs.current_branch != 'trunk' && inputs.is_default_branch == 'true' }},value=${{ inputs.os }}-latest
type=ref,enable=${{ inputs.current_branch == 'trunk' }},event=branch,prefix=${{ inputs.os }}-
type=ref,enable=${{ inputs.current_branch == 'trunk' || inputs.event_name == 'workflow_dispatch' }},event=branch,suffix=-${{ inputs.os }}
flavor: |
latest=${{ inputs.os == 'alpine' && inputs.event_name != 'workflow_dispatch' && inputs.is_default_branch == 'true' }}

View file

@ -320,20 +320,14 @@ jobs:
- name: Generate tags
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
uses: ./.github/actions/docker-meta
with:
images: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_BUILD_NAME ) }}
context: ${{ env.TRUNK_ONLY_EVENT == 'true' && 'git' || '' }}
tags: |
type=semver,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},pattern={{version}},prefix=${{ matrix.os }}-
type=semver,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},pattern={{version}},suffix=-${{ matrix.os }}
type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,prefix=${{ matrix.os }}-,suffix=-latest
type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,suffix=-${{ matrix.os }}-latest
type=raw,enable=${{ (needs.init_build.outputs.current_branch != 'trunk') && (needs.init_build.outputs.is_default_branch == 'true') }},value=${{ matrix.os }}-latest
type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,prefix=${{ matrix.os }}-
type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' || contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,suffix=-${{ matrix.os }}
flavor: |
latest=${{ (matrix.os == 'alpine') && (!contains(fromJSON('["workflow_dispatch"]'), github.event_name)) && (needs.init_build.outputs.is_default_branch == 'true') }}
image: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_BUILD_NAME ) }}
os: ${{ matrix.os }}
current_branch: ${{ needs.init_build.outputs.current_branch }}
is_default_branch: ${{ needs.init_build.outputs.is_default_branch }}
trunk_only_event: ${{ env.TRUNK_ONLY_EVENT }}
event_name: ${{ github.event_name }}
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
@ -365,31 +359,16 @@ jobs:
dockerfile: ${{ format('{0}/{1}/{2}/Dockerfile', env.DOCKERFILES_DIRECTORY, env.BASE_BUILD_NAME, matrix.os) }}
- name: Sign the images with GitHub OIDC Token
env:
DIGEST: ${{ steps.docker_build.outputs.digest }}
TAGS: ${{ steps.meta.outputs.tags }}
run: |
images=""
for tag in ${TAGS}; do
images+="${tag}@${DIGEST} "
done
echo "::group::Images to sign"
echo "$images"
echo "::endgroup::"
echo "::group::Signing"
echo "cosign sign --yes $images"
cosign sign --yes ${images}
echo "::endgroup::"
uses: ./.github/actions/cosign-sign
with:
digest: ${{ steps.docker_build.outputs.digest }}
tags: ${{ steps.meta.outputs.tags }}
- name: Attest images
id: attest
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
uses: ./.github/actions/attest-image
with:
subject-name: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_BUILD_NAME ) }}
subject-digest: ${{ steps.docker_build.outputs.digest }}
push-to-registry: true
subject_name: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_BUILD_NAME ) }}
subject_digest: ${{ steps.docker_build.outputs.digest }}
- name: Image metadata
env:
@ -504,20 +483,14 @@ jobs:
- name: Generate tags
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
uses: ./.github/actions/docker-meta
with:
images: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, matrix.build) }}
context: ${{ env.TRUNK_ONLY_EVENT == 'true' && 'git' || '' }}
tags: |
type=semver,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},pattern={{version}},prefix=${{ matrix.os }}-
type=semver,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},pattern={{version}},suffix=-${{ matrix.os }}
type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,prefix=${{ matrix.os }}-,suffix=-latest
type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,suffix=-${{ matrix.os }}-latest
type=raw,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && needs.init_build.outputs.is_default_branch == 'true' }},value=${{ matrix.os }}-latest
type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,prefix=${{ matrix.os }}-
type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' || contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,suffix=-${{ matrix.os }}
flavor: |
latest=${{ matrix.os == 'alpine' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) && needs.init_build.outputs.is_default_branch == 'true' }}
image: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, matrix.build) }}
os: ${{ matrix.os }}
current_branch: ${{ needs.init_build.outputs.current_branch }}
is_default_branch: ${{ needs.init_build.outputs.is_default_branch }}
trunk_only_event: ${{ env.TRUNK_ONLY_EVENT }}
event_name: ${{ github.event_name }}
- name: Download artifact metadata of ${{ env.BASE_BUILD_NAME }}:${{ matrix.os }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
@ -544,23 +517,11 @@ jobs:
echo "base_build_image=${image_name}@${image_digest}" >> "$GITHUB_OUTPUT"
- name: Verify ${{ env.BASE_BUILD_NAME }}:${{ matrix.os }} cosign
env:
BASE_IMAGE: ${{ steps.base_build.outputs.base_build_image }}
OIDC_ISSUER: ${{ env.OIDC_ISSUER }}
IDENTITY_REGEX: ${{ env.IDENTITY_REGEX }}
run: |
echo "::group::Image sign data"
echo "OIDC issuer=$OIDC_ISSUER"
echo "Identity=$IDENTITY_REGEX"
echo "Image to verify=$BASE_IMAGE"
echo "::endgroup::"
echo "::group::Verify signature"
cosign verify \
--certificate-oidc-issuer-regexp "$OIDC_ISSUER" \
--certificate-identity-regexp "$IDENTITY_REGEX" \
"$BASE_IMAGE" | jq
echo "::endgroup::"
uses: ./.github/actions/cosign-verify
with:
image: ${{ steps.base_build.outputs.base_build_image }}
oidc_issuer: ${{ env.OIDC_ISSUER }}
identity_regexp: ${{ env.IDENTITY_REGEX }}
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
@ -832,20 +793,14 @@ jobs:
- name: Generate tags
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
uses: ./.github/actions/docker-meta
with:
images: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, matrix.build) }}
context: ${{ env.TRUNK_ONLY_EVENT == 'true' && 'git' || '' }}
tags: |
type=semver,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},pattern={{version}},prefix=${{ matrix.os }}-
type=semver,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},pattern={{version}},suffix=-${{ matrix.os }}
type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,prefix=${{ matrix.os }}-,suffix=-latest
type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,suffix=-${{ matrix.os }}-latest
type=raw,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && needs.init_build.outputs.is_default_branch == 'true' }},value=${{ matrix.os }}-latest
type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,prefix=${{ matrix.os }}-
type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' || contains(fromJSON('["workflow_dispatch"]'), github.event_name) }},event=branch,suffix=-${{ matrix.os }}
flavor: |
latest=${{ matrix.os == 'alpine' && !contains(fromJSON('["workflow_dispatch"]'), github.event_name) && needs.init_build.outputs.is_default_branch == 'true' }}
image: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, matrix.build) }}
os: ${{ matrix.os }}
current_branch: ${{ needs.init_build.outputs.current_branch }}
is_default_branch: ${{ needs.init_build.outputs.is_default_branch }}
trunk_only_event: ${{ env.TRUNK_ONLY_EVENT }}
event_name: ${{ github.event_name }}
- name: Download artifact metadata of ${{ steps.build_base_image.outputs.build_base }}:${{ matrix.os }}
if: ${{ matrix.build != 'snmptraps' }}