Skip to content
Merged
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
66 changes: 54 additions & 12 deletions .github/actions/build-docker/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ inputs:
required: true
description: 'Deno version'
type: string
arch:
required: false
description: 'Architecture'
default: 'amd64'
service:
required: false
description: 'Container to build'
Expand Down Expand Up @@ -46,7 +50,7 @@ runs:
password: ${{ inputs.CR_PAT }}

- name: Restore packages build
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
name: packages-build
path: /tmp
Expand All @@ -58,7 +62,7 @@ runs:

- name: Restore meteor build
if: inputs.service == 'rocketchat'
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
name: build-${{ inputs.type }}
path: /tmp/build
Expand All @@ -71,26 +75,64 @@ runs:
tar xzf Rocket.Chat.tar.gz
rm Rocket.Chat.tar.gz

- name: Build Docker images
shell: bash
run: |
export DENO_VERSION="${{ inputs.deno-version }}"
- name: Set up Docker
uses: docker/setup-docker-action@v4
with:
daemon-config: |
{
"debug": true,
"features": {
"containerd-snapshotter": true
}
}

docker compose -f docker-compose-ci.yml build ${{ inputs.service }}
- uses: docker/setup-buildx-action@v3
with:
buildkitd-flags: --oci-worker-gc --oci-worker-gc-keepstorage=4000

- name: Publish Docker images to GitHub Container Registry
if: inputs.publish-image == 'true' && github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
- name: Build Docker images
shell: bash
run: |
set -o xtrace
export DENO_VERSION="${{ inputs.deno-version }}"

if [[ "${{ inputs.publish-image }}" == 'true' ]]; then
LOAD_OR_PUSH="--push"
else
LOAD_OR_PUSH="--load"
fi

# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "${{ inputs.service }}" '.services[$s].image')
IMAGE_NO_TAG=$(echo "$IMAGE" | sed 's/:.*$//')

docker tag ${IMAGE} ${IMAGE}-gha-run-${{ github.run_id }}
docker buildx bake \
-f docker-compose-ci.yml \
${LOAD_OR_PUSH} \
--allow=fs.read=/tmp/build \
--set "*.tags+=${IMAGE}-gha-run-${{ github.run_id }}" \
--set "*.labels.org.opencontainers.image.description=Build run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--set *.platform=linux/${{ inputs.arch }} \
--set *.cache-from=type=gha \
--set *.cache-to=type=gha,mode=max \
--provenance=false \
--sbom=false \
--metadata-file "/tmp/meta.json" \
"${{ inputs.service }}"

docker push --all-tags ${IMAGE_NO_TAG}
echo "Contents of /tmp/meta.json:"
cat /tmp/meta.json

mkdir -p /tmp/digests/${{ inputs.service }}${{ inputs.type == 'coverage' && '-cov' || '' }}/${{ inputs.arch }}
DIGEST=$(jq -r '.["${{ inputs.service }}"].["containerimage.digest"]' "/tmp/meta.json")
IMAGE_NO_TAG=$(echo "$IMAGE" | sed 's/:.*$//')
echo "${IMAGE_NO_TAG}@${DIGEST}" > "/tmp/digests/${{ inputs.service }}${{ inputs.type == 'coverage' && '-cov' || '' }}/${{ inputs.arch }}/digest.txt"

- uses: actions/upload-artifact@v4
if: inputs.publish-image == 'true'
with:
name: digests-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
path: /tmp/digests
retention-days: 5

- name: Clean up temporary files
if: inputs.service == 'rocketchat'
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/meteor-build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ runs:
run: meteor reset

- name: Restore packages build
uses: actions/download-artifact@v4
uses: actions/download-artifact@v6
with:
name: packages-build
path: /tmp
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/setup-node/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ runs:
apps/meteor/ee/server/services/node_modules
packages/apps-engine/node_modules
packages/apps-engine/.deno-cache
key: node-modules-${{ hashFiles('yarn.lock') }}-deno-v${{ inputs.deno-version }}-${{ hashFiles('packages/apps-engine/deno-runtime/deno.lock') }}
key: node-modules-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('yarn.lock') }}-deno-v${{ inputs.deno-version }}-${{ hashFiles('packages/apps-engine/deno-runtime/deno.lock') }}
#
# Could use this command to list all paths to save:
# find . -name 'node_modules' -prune | grep -v "/\.meteor/" | grep -v "/meteor/packages/"
Expand Down
115 changes: 100 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -267,21 +267,23 @@ jobs:
build-gh-docker:
name: 🚢 Build Docker
needs: [build, release-versions]
runs-on: ubuntu-24.04
runs-on: ubuntu-24.04${{ matrix.arch == 'arm64' && '-arm' || '' }}

env:
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}-${{ matrix.arch }}
LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }}

strategy:
fail-fast: false
matrix:
arch: ['amd64', 'arm64']
service: ${{ fromJson(needs.release-versions.outputs.services) }}
type: ['production']
include:
# for rocketchat monolith and on develop branch builds we create a coverage image to run tests against it
# and keep the baseline of the coverage for other PRs
- service: rocketchat
- arch: amd64
service: rocketchat
type: coverage

steps:
Expand All @@ -298,9 +300,79 @@ jobs:
node-version: ${{ needs.release-versions.outputs.node-version }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
arch: ${{ matrix.arch }}
service: ${{ matrix.service }}
type: ${{ matrix.type }}

build-gh-docker-publish:
name: 🚢 Publish Docker Images (ghcr.io)
needs: [build-gh-docker, release-versions]
runs-on: ubuntu-24.04

env:
DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}
LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }}

steps:
- uses: actions/checkout@v4
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
with:
sparse-checkout: |
docker-compose-ci.yml
sparse-checkout-cone-mode: false
ref: ${{ github.ref }}

- name: Login to GitHub Container Registry
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.CR_USER }}
password: ${{ secrets.CR_PAT }}

- name: Download digests
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: actions/download-artifact@v6
with:
pattern: digests-*
path: /tmp/digests
merge-multiple: true

- name: Create and push multi-arch manifests
if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
run: |
set -o xtrace
shopt -s nullglob

for service_dir in /tmp/digests/*; do
[[ -d "$service_dir" ]] || continue
service="$(basename "$service_dir")"
echo "Creating manifest for $service"

mapfile -t refs < <(
find "$service_dir" -type f -name 'digest.txt' -print0 \
| xargs -0 -I{} sh -c "tr -d '\r' < '{}' | sed '/^[[:space:]]*$/d'"
)

echo "Digest for ${service}: ${refs[@]}"

# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
if [ "$service" == "rocketchat-cov" ]; then
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "rocketchat" '.services[$s].image')-cov
else
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$service" '.services[$s].image')
fi

echo $IMAGE

docker buildx imagetools create \
--debug \
--annotation "manifest-descriptor:org.opencontainers.image.description=Build run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--tag "${IMAGE}" \
--tag "${IMAGE}-gha-run-${{ github.run_id }}" \
${refs[@]}
done

checks:
needs: [release-versions, packages-build]

Expand Down Expand Up @@ -335,7 +407,7 @@ jobs:

test-api:
name: 🔨 Test API (CE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
Expand All @@ -351,7 +423,7 @@ jobs:

test-ui:
name: 🔨 Test UI (CE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
Expand All @@ -376,7 +448,7 @@ jobs:

test-api-ee:
name: 🔨 Test API (EE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
Expand All @@ -395,7 +467,7 @@ jobs:

test-ui-ee:
name: 🔨 Test UI (EE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
Expand All @@ -422,7 +494,7 @@ jobs:

test-ui-ee-watcher:
name: 🔨 Test UI (EE)
needs: [checks, build-gh-docker, release-versions]
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
Expand Down Expand Up @@ -490,7 +562,7 @@ jobs:
name: 🚀 Publish build assets
runs-on: ubuntu-24.04
if: github.event_name == 'release' || github.ref == 'refs/heads/develop'
needs: [build-gh-docker, release-versions]
needs: [build-gh-docker-publish, release-versions]

steps:
- uses: actions/checkout@v5
Expand Down Expand Up @@ -587,8 +659,13 @@ jobs:
- name: Pull Docker image
run: docker pull ${{ steps.gh-docker.outputs.gh-image-name }}

- name: Publish Docker image
- name: Publish Docker images
run: |
set -euo pipefail

sudo apt-get update -y
sudo apt-get install -y skopeo

if [[ '${{ matrix.service }}' == 'rocketchat' ]]; then
IMAGE_NAME="${{ needs.release-versions.outputs.lowercase-repo }}/rocket.chat"
else
Expand Down Expand Up @@ -624,17 +701,25 @@ jobs:

echo "Tags: ${TAGS[*]}"

# get first tag as primary
PRIMARY="${TAGS[0]}"

SRC="${{ steps.gh-docker.outputs.gh-image-name }}"
DEST_REPO="docker.io/${IMAGE_NAME}"

if (( ${#TAGS[@]} > 0 )); then
for t in "${TAGS[@]:0}"; do
echo "Copying $SRC to ${DEST_REPO}:${t}"
docker tag $SRC "${DEST_REPO}:${t}"
# build --additional-tag for all other tags
EXTRA_ARGS=()
if (( ${#TAGS[@]} > 1 )); then
for t in "${TAGS[@]:1}"; do
EXTRA_ARGS+=( --additional-tag "${DEST_REPO}:${t}" )
done
fi

docker push --all-tags $DEST_REPO
echo "Copying $SRC to ${DEST_REPO}:${PRIMARY} with extras ${EXTRA_ARGS[*]}"
skopeo copy --all \
"docker://${SRC}" \
"docker://${DEST_REPO}:${PRIMARY}" \
"${EXTRA_ARGS[@]}"

notify-services:
name: 🚀 Notify external services
Expand Down
Loading
Loading