Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: prepare repo for multi-arch builds #15

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 186 additions & 59 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,51 @@ on:
workflow_dispatch:

env:
IMAGE_NAME: "main"
IMAGE_NAME: "rs-main-test"
IMAGE_DESC: "CentOS Stream-based images"
IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}"
DEFAULT_TAG: "latest"
CENTOS_VERSION: "stream10"
LOGO_URL: "https://avatars.githubusercontent.com/u/120078124?s=200&v=4"
README_URL: "https://raw.githubusercontent.com/${{ github.repository }}/main/README.md"
PLATFORMS: "amd64"

concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true

jobs:
generate_matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set matrix
id: set-matrix
run: |
# turn the comma separated string into a list
platforms=(${{ env.PLATFORMS }})

MATRIX="{\"include\":[]}"
for platform in "${platforms[@]}"; do
MATRIX=$(echo $MATRIX | jq ".include += [{\"platform\": \"$platform\"}]")
done

echo "matrix=$(echo $MATRIX | jq -c '.')" >> $GITHUB_OUTPUT

build_push:
name: Build and push image
runs-on: ubuntu-24.04

needs: generate_matrix
strategy:
fail-fast: false
matrix: ${{fromJson(needs.generate_matrix.outputs.matrix)}}
permissions:
contents: read
packages: write
id-token: write

steps:
# Checkout push-to-registry action GitHub repository
- name: Checkout Push to Registry action
- name: Checkout
uses: actions/checkout@v4

- name: Setup Just
Expand All @@ -54,48 +74,6 @@ jobs:
with:
remove-codeql: true

- name: Generate tags
id: generate-tags
shell: bash
run: |
# Generate a timestamp for creating an image version history
TIMESTAMP="$(date +%Y%m%d)"
COMMIT_TAGS=()
BUILD_TAGS=()

# Have tags for tracking builds during pull request
SHA_SHORT="${GITHUB_SHA::7}"
COMMIT_TAGS+=("pr-${{ github.event.number }}")
COMMIT_TAGS+=("${SHA_SHORT}")

# Append matching timestamp tags to keep a version history
for TAG in "${BUILD_TAGS[@]}"; do
BUILD_TAGS+=("${TAG}-${TIMESTAMP}")
done

BUILD_TAGS+=("${TIMESTAMP}")
BUILD_TAGS+=("${DEFAULT_TAG}")
BUILD_TAGS+=("${CENTOS_VERSION}")
BUILD_TAGS+=("${CENTOS_VERSION}.${TIMESTAMP}")

if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "Generated the following commit tags: "
for TAG in "${COMMIT_TAGS[@]}"; do
echo "${TAG}"
done

alias_tags=("${COMMIT_TAGS[@]}")
else
alias_tags=("${BUILD_TAGS[@]}")
fi

echo "Generated the following build tags: "
for TAG in "${BUILD_TAGS[@]}"; do
echo "${TAG}"
done

echo "alias_tags=${alias_tags[*]}" >> $GITHUB_OUTPUT

- name: Build Image
id: build-image
shell: bash
Expand All @@ -120,12 +98,18 @@ jobs:
io.artifacthub.package.logo-url=${{ env.LOGO_URL }}

- name: Load in podman and tag
id: load
run: |
IMAGE=$(podman pull ${{ steps.rechunk.outputs.ref }})
sudo rm -rf ${{ steps.rechunk.outputs.output }}
for tag in ${{ steps.generate-tags.outputs.alias_tags }}; do
podman tag $IMAGE ${{ env.IMAGE_NAME }}:$tag
done

podman image tag $IMAGE ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}

skopeo inspect --raw docker://$IMAGE

IMAGE_DIGEST=$(skopeo inspect docker://$IMAGE | jq -r '.Digest')
echo "image=$IMAGE" >> $GITHUB_OUTPUT
echo "digest=$IMAGE_DIGEST" >> $GITHUB_OUTPUT

# Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
# https://github.com/macbre/push-to-ghcr/issues/12
Expand All @@ -144,15 +128,19 @@ jobs:

# Push the image to GHCR (Image Registry)
- name: Push To GHCR
uses: redhat-actions/push-to-registry@v2
if: github.event_name != 'pull_request'
# if: github.event_name != 'pull_request'
id: push
with:
registry: ${{ steps.registry_case.outputs.lowercase }}
image: ${{ env.IMAGE_NAME }}
tags: ${{ steps.generate-tags.outputs.alias_tags }}
extra-args: |
--disable-content-trust
env:
IMAGE_REGISTRY: ${{ steps.registry_case.outputs.lowercase }}
IMAGE_NAME: ${{ env.IMAGE_NAME }}
IMAGE_DIGEST: ${{ steps.load.outputs.digest }}
run: |
for i in {1..3}; do
podman push --remove-signatures --digestfile=/tmp/digestfile $IMAGE_REGISTRY/$IMAGE_NAME@${IMAGE_DIGEST} && break || sleep $((5 * i));
done

REMOTE_IMAGE_DIGEST=$(cat /tmp/digestfile)
echo "remote_image_digest=$REMOTE_IMAGE_DIGEST" >> $GITHUB_OUTPUT

- name: Install Cosign
uses: sigstore/[email protected]
Expand All @@ -162,8 +150,147 @@ jobs:
if: github.event_name != 'pull_request'
run: |
IMAGE_FULL="${{ steps.registry_case.outputs.lowercase }}/${IMAGE_NAME}"
cosign sign -y --key env://COSIGN_PRIVATE_KEY ${IMAGE_FULL}@${TAGS}
cosign sign -y --key env://COSIGN_PRIVATE_KEY ${IMAGE_FULL}@${{ steps.push.outputs.remote_image_digest }}
env:
TAGS: ${{ steps.push.outputs.digest }}
COSIGN_EXPERIMENTAL: false
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}

- name: Create job outputs
env:
IMAGE_NAME: ${{ env.IMAGE_NAME }}
PLATFORM: ${{ matrix.platform }}
DIGEST: ${{ steps.push.outputs.remote_image_digest }}
run: |
mkdir -p /tmp/outputs/digests
echo "${DIGEST}" > /tmp/outputs/digests/${IMAGE_NAME}-${PLATFORM}.txt

- name: Upload Output Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ env.IMAGE_NAME }}-${{ matrix.platform }}
retention-days: 1
if-no-files-found: error
path: |
/tmp/outputs/digests/*.txt


manifest:
runs-on: ubuntu-latest
needs:
- build_push
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Generate tags
id: generate-tags
shell: bash
run: |
# Generate a timestamp for creating an image version history
TIMESTAMP="$(date +%Y%m%d)"
COMMIT_TAGS=()
BUILD_TAGS=()

# Have tags for tracking builds during pull request
SHA_SHORT="${GITHUB_SHA::7}"
COMMIT_TAGS+=("pr-${{ github.event.number }}")
COMMIT_TAGS+=("${SHA_SHORT}")

# Append matching timestamp tags to keep a version history
for TAG in "${BUILD_TAGS[@]}"; do
BUILD_TAGS+=("${TAG}-${TIMESTAMP}")
done

BUILD_TAGS+=("${TIMESTAMP}")
BUILD_TAGS+=("${DEFAULT_TAG}")
BUILD_TAGS+=("${CENTOS_VERSION}")
BUILD_TAGS+=("${CENTOS_VERSION}.${TIMESTAMP}")

if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "Generated the following commit tags: "
for TAG in "${COMMIT_TAGS[@]}"; do
echo "${TAG}"
done

alias_tags=("${COMMIT_TAGS[@]}")
else
alias_tags=("${BUILD_TAGS[@]}")
fi

echo "Generated the following build tags: "
for TAG in "${BUILD_TAGS[@]}"; do
echo "${TAG}"
done

echo "alias_tags=${alias_tags[*]}" >> $GITHUB_OUTPUT

- name: Fetch Build Outputs
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
with:
pattern: ${{ env.IMAGE_NAME }}-*.txt
merge-multiple: true
path: /tmp/artifacts

- name: Load Outputs
id: load-outputs
run: |
DIGESTS_JSON=$(jq -n '{}')

for file in /tmp/artifacts/*.txt; do
# Extract the platform from the file name
PLATFORM=$(basename $digest_file | rev | cut -d'-' -f1 | rev | cut -d'.' -f1)
DIGEST=$(cat $digest_file)

# Add the platform and digest to the JSON object
DIGESTS_JSON=$(echo "$DIGESTS_JSON" | jq --arg key "$PLATFORM" --arg value "$DIGEST" '. + {($key): $value}')
done

echo "DIGESTS_JSON=$(echo $DIGESTS_JSON | jq -c '.')" >> $GITHUB_OUTPUT

- name: Create Manifest
id: create-manifest
run: |
podman manifest create ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}
echo "MANIFEST=${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT

- name: Populate Manifest
env:
MANIFEST: ${{ steps.create-manifest.outputs.MANIFEST }}
DIGESTS_JSON: ${{ steps.load-outputs.outputs.DIGESTS_JSON }}
run: |
DIGESTS=$(echo "$DIGESTS_JSON" | jq -c '.')
PLATFORMS=(${{ env.PLATFORMS }})

for platform in ${PLATFORMS[@]}; do
digest=$(echo $DIGESTS | jq -r ".$platform")
podman manifest add $MANIFEST ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:$digest --arch $platform
done

- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Tag Manifest
id: tag-manifest
run: |
MANIFEST_TAGS=()
for tag in ${{ steps.generate-tags.outputs.alias_tags }}; do
podman manifest tag ${{ steps.create-manifest.outputs.MANIFEST }} ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:$tag
MANIFEST_TAGS+=(${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:$tag)
done
MANIFEST_TAGS_JSON=$(printf '%s\n' "${MANIFEST_TAGS[@]}" | jq -R . | jq -cs .)
echo "MANIFEST_TAGS_JSON=${MANIFEST_TAGS_JSON}" >> $GITHUB_OUTPUT

- name: Push Manifest
env:
MANIFEST: ${{ steps.create-manifest.outputs.MANIFEST }}
MANIFEST_TAGS_JSON: ${{ steps.tag-manifest.outputs.MANIFEST_TAGS_JSON }}
run: |
for tag in $(echo $MANIFEST_TAGS_JSON | jq -r '.[]'); do
podman manifest push --all=false $MANIFEST $tag
done
12 changes: 6 additions & 6 deletions Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ ARG MAJOR_VERSION="${MAJOR_VERSION:-stream10}"
FROM quay.io/centos-bootc/centos-bootc:$MAJOR_VERSION

#Install codecs, Workstation, EPEL, CRB, etc.
COPY build.sh /tmp/build.sh
RUN chmod +x /tmp/build.sh &&\
/tmp/build.sh && \
dnf clean all && \
ostree container commit
# COPY build.sh /tmp/build.sh
# RUN chmod +x /tmp/build.sh &&\
# /tmp/build.sh && \
# dnf clean all && \
# ostree container commit

# Just gotta get this green!
RUN bootc container lint || exit 0
RUN bootc container lint || exit 0
Loading