Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6e2f63b
refactor(workflows): use reusable workflows with a single branch
gustavovalverde Apr 13, 2025
1c6c296
fix(workflows): build on different nodes
gustavovalverde Apr 13, 2025
c5aebc2
fix(workflows): use the correct matrix combination
gustavovalverde Apr 13, 2025
755aac3
fix(workflows): use the correct way
gustavovalverde Apr 13, 2025
041f388
fix(build): use correct image references
gustavovalverde Apr 13, 2025
4f7551e
fix(build): default python 12 without pinned greenlet
gustavovalverde Apr 13, 2025
6cb9528
fix(build): correctly handle user with ARGs
gustavovalverde Apr 13, 2025
79cc1be
fix(build): better odoo/python/os combination
gustavovalverde Apr 13, 2025
d39872b
fix(build): better wkhtmltopdf handling
gustavovalverde Apr 13, 2025
5f54bd9
imp(build): use the correct runner for arm images
gustavovalverde Apr 13, 2025
54036d4
fix(build): default runner
gustavovalverde Apr 13, 2025
1412f66
fix the matrix
gustavovalverde Apr 13, 2025
3d2e655
fix(test): use correct image tag for a single platform
gustavovalverde Apr 13, 2025
8c6bcf1
fix(tags): use a predictable tag name
gustavovalverde Apr 14, 2025
63b24ef
fix(registry): use raw input for PRs
gustavovalverde Apr 14, 2025
61fd67e
fix(registry): avoid duplication
gustavovalverde Apr 14, 2025
6940219
imp(build): add caching mechanism
gustavovalverde Apr 14, 2025
ad2f424
ref(multiarch): use recommended docker approach
gustavovalverde Apr 14, 2025
ec81ef8
fix(ci): push normally
gustavovalverde Apr 14, 2025
acc0810
fix(distribution): labeling strategy
gustavovalverde Apr 14, 2025
8873743
fix(test): add missing library
gustavovalverde Apr 14, 2025
3b83d3c
chore: use a non-alpine DB
gustavovalverde Apr 14, 2025
f97d5d7
fix(cache): scope the cache to the specific platform
gustavovalverde Apr 14, 2025
91bc162
fix(tests): use correct versions and disable flaky test
gustavovalverde Apr 16, 2025
c6ca0e2
fix(ci): do not fail fast tests
gustavovalverde Apr 16, 2025
c389af3
fix(test): remove flaky and non-standard tests
gustavovalverde Apr 16, 2025
7b175c9
fix(test): add more flaky test exceptions
gustavovalverde Apr 16, 2025
6aa51ae
fix(test): remaining flaky tests
gustavovalverde Apr 16, 2025
3965d7c
feat(ci): implement new build-test-publish workflow and image builder
gustavovalverde Apr 16, 2025
eebd26b
fix: escape characters
gustavovalverde Apr 16, 2025
f19d929
chore: more legible matrix
gustavovalverde Apr 16, 2025
a9b3ec2
ref(ci): simplify the whole pipeline
gustavovalverde Apr 16, 2025
468f15a
chore: missing push
gustavovalverde Apr 16, 2025
a41daa6
fix(ci): try to avoid setting empty values to other versions
gustavovalverde Apr 16, 2025
2ab047a
chore: change condition
gustavovalverde Apr 16, 2025
9a7983c
ref: break 15.0 versions
gustavovalverde Apr 16, 2025
3200e61
ref(ci): use better handling
gustavovalverde Apr 16, 2025
c1c33c6
fix(dockerfile): remove deprecation warnings
gustavovalverde Apr 16, 2025
4ed783a
feat(ci): add scheduled trigger for weekly builds
gustavovalverde Apr 16, 2025
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
70 changes: 70 additions & 0 deletions .github/workflows/build-test-publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Test and Publish

on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 1"
push:
branches: [main]
paths:
- "**/resources/**"
- Dockerfile
pull_request:
paths:
- "**/workflows/**"
- "**/resources/**"
- Dockerfile

permissions:
contents: read
packages: write
id-token: write

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

jobs:
build:
name: Build Odoo ${{ matrix.odoo_version }}
strategy:
fail-fast: false
matrix:
odoo_version: ["15.0", "16.0", "17.0", "18.0", master]
uses: ./.github/workflows/image-builder.yaml
with:
odoo_version: ${{ matrix.odoo_version }}
dockerfile_path: Dockerfile
dockerfile_target: production
secrets: inherit

test:
name: Test Odoo ${{ matrix.odoo_version }}
needs: build
strategy:
fail-fast: false
matrix:
odoo_version: ["15.0", "16.0", "17.0", "18.0", master]
exclude:
# TODO: Tests are failing on master. Remove this when fixed
# See: https://github.com/odoo/odoo/pull/44001#issuecomment-2808975399
- odoo_version: master
uses: ./.github/workflows/unit-tests.yaml
with:
odoo_version: ${{ matrix.odoo_version }}
secrets: inherit

publish:
name: Publish Odoo ${{ matrix.odoo_version }}
needs: [build, test]
strategy:
fail-fast: false
matrix:
odoo_version: ["15.0", "16.0", "17.0", "18.0", master]
if: ${{ github.event_name != 'pull_request' }}
uses: ./.github/workflows/image-builder.yaml
with:
odoo_version: ${{ matrix.odoo_version }}
dockerfile_path: Dockerfile
dockerfile_target: production
secrets: inherit
256 changes: 256 additions & 0 deletions .github/workflows/image-builder.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
name: Build and Push Images

on:
workflow_call:
inputs:
odoo_version:
required: true
type: string
python_version:
required: false
type: string
default: 3.12-slim
os_variant:
required: false
type: string
default: bookworm
dockerfile_path:
required: true
type: string
dockerfile_target:
required: true
type: string
no_cache:
description: Disable the Docker cache for this build
required: false
type: boolean
default: false

outputs:
image_digest:
description: The image digest to be used on a caller workflow
value: ${{ jobs.build.outputs.image_digest }}

jobs:
build:
name: Build for ${{ matrix.platform }}
timeout-minutes: 30
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
include:
# Platform-specific runner overrides
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
outputs:
image_digest: ${{ steps.build.outputs.digest }}
image_name: ${{ fromJSON(steps.build.outputs.metadata)['image.name'] }}
permissions:
contents: read
id-token: write
packages: write
env:
DOCKER_BUILD_SUMMARY: ${{ github.event_name == 'pull_request' && false || true }}
steps:
- uses: actions/checkout@v4.2.2
with:
persist-credentials: false

- name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v5.1.0
with:
short-length: 7

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

- name: Login to Google Container Registry
uses: docker/login-action@v3.4.0
if: ${{ github.event_name != 'pull_request' }}
with:
registry: gcr.io
username: _json_key
password: ${{ secrets.GKE_SA_KEY }}

- name: Login to DockerHub
uses: docker/login-action@v3.4.0
if: ${{ github.event_name != 'pull_request' }}
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Prepare manifest
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV

- name: Docker meta
id: meta
uses: docker/metadata-action@v5.7.0
with:
# Use the same image list pattern as the merge job for consistency
images: |
ghcr.io/iterativo-git/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }}
iterativodo/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }},enable=${{ github.event_name != 'pull_request' }}
gcr.io/iterativo/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }},enable=${{ github.event_name != 'pull_request' }}

# Setup Docker Buildx
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3.10.0

- name: Build & push
id: build
uses: docker/build-push-action@v6.15.0
with:
target: ${{ inputs.dockerfile_target }}
file: ${{ inputs.dockerfile_path }}
context: .
# IMPORTANT: When using push-by-digest for multi-platform, we cannot:
# 1. Use tags directly during the build (we'll apply them in the merge job)
# 2. Push to multiple registries at once (we'll distribute in the merge job)
# This is a requirement of the Docker buildx multi-platform workflow
labels: ${{ steps.meta.outputs.labels }}
build-args: |
ODOO_VERSION=${{ inputs.odoo_version }}
OS_VARIANT=${{ inputs.os_variant }}
PYTHON_VERSION=${{ inputs.python_version }}
platforms: ${{ matrix.platform }}
# We must use a single registry for the digest source
# GitHub Container Registry is used regardless of PR/non-PR status
outputs: type=image,push-by-digest=true,name=ghcr.io/iterativo-git/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }},push=true
# Don't read from the cache if the caller disabled it.
# https://docs.docker.com/engine/reference/commandline/buildx_build/#options
no-cache: ${{ inputs.no_cache }}
cache-from: type=gha,scope=odoo-${{ inputs.odoo_version }}-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=odoo-${{ inputs.odoo_version }}-${{ matrix.platform }}

- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4.6.2
with:
name: digests-${{ inputs.odoo_version }}-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1

merge:
name: Merge platform manifests
runs-on: ubuntu-latest
needs:
- build
steps:
- uses: actions/checkout@v4.2.2
with:
persist-credentials: false

- name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v5.1.0
with:
short-length: 7

- name: Download digests
uses: actions/download-artifact@v4.2.1
with:
path: ${{ runner.temp }}/digests
pattern: digests-${{ inputs.odoo_version }}-*
merge-multiple: true

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

- name: Login to Google Container Registry
uses: docker/login-action@v3.4.0
if: ${{ github.event_name != 'pull_request' }}
with:
registry: gcr.io
username: _json_key
password: ${{ secrets.GKE_SA_KEY }}

- name: Login to DockerHub
uses: docker/login-action@v3.4.0
if: ${{ github.event_name != 'pull_request' }}
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3.10.0

# Automatic tag management and OCI Image Format Specification for labels
- name: Docker meta
id: meta
uses: docker/metadata-action@v5.7.0
with:
# list of Docker images to use as base name for tags
images: |
ghcr.io/iterativo-git/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }}
iterativodo/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }},enable=${{ github.event_name != 'pull_request' }}
gcr.io/iterativo/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }},enable=${{ github.event_name != 'pull_request' }}
# Use predefined flavor with version customization
flavor: |
latest=false
# Generate Docker tags based on predefined rules
tags: |
type=raw,event=push,value=${{ inputs.odoo_version }},enable={{is_default_branch}}
type=raw,event=pr,value=${{ env.GITHUB_REF_SLUG }}-${{ inputs.odoo_version }}
type=schedule,value=${{ inputs.odoo_version }}

- name: Prepare registry sources and targets
id: registry-vars
run: |
# Base image name used as the source for digests
SOURCE_IMAGE="ghcr.io/iterativo-git/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }}"
echo "SOURCE_IMAGE=${SOURCE_IMAGE}" >> $GITHUB_ENV

# Extract all target registries/images from metadata
TARGET_REFS=$(jq -r '.tags[]' <<< "$DOCKER_METADATA_OUTPUT_JSON" | cut -d':' -f1 | sort -u | tr '\n' ' ')
echo "TARGET_REFS=${TARGET_REFS}" >> $GITHUB_ENV

- name: Create manifest lists and push to all registries
working-directory: ${{ runner.temp }}/digests
run: |
# For each tag pattern in the metadata
for TAG_PATTERN in $(jq -r '.tags | map(. | split(":")[1]) | unique[]' <<< "$DOCKER_METADATA_OUTPUT_JSON"); do
echo "Processing tag pattern: ${TAG_PATTERN}"

# For each registry/image combination
for TARGET_REF in ${{ env.TARGET_REFS }}; do
echo "Creating manifest for ${TARGET_REF}:${TAG_PATTERN}"

# Create the manifest list with appropriate tags
docker buildx imagetools create -t "${TARGET_REF}:${TAG_PATTERN}" \
$(printf '${{ env.SOURCE_IMAGE }}@sha256:%s ' *)
done
done

- name: Inspect manifests
run: |
# For each tag pattern in the metadata
for TAG_PATTERN in $(jq -r '.tags | map(. | split(":")[1]) | unique[]' <<< "$DOCKER_METADATA_OUTPUT_JSON"); do
# For each registry/image combination
for TARGET_REF in ${{ env.TARGET_REFS }}; do
echo "Inspecting ${TARGET_REF}:${TAG_PATTERN}"
docker buildx imagetools inspect "${TARGET_REF}:${TAG_PATTERN}"
done
done
Loading