itsulu-blog-publisher/.gitlab-ci.yml
Nicholas Riegel c6c912b809 fix: remove duplicate itsulu_social_id field and fix CI addons path
- Remove duplicate BlogPost._inherit class from blog_schedule.py that
  redefined itsulu_social_id with invalid 'limit' parameter, causing
  'unknown parameter limit' warnings on every Odoo startup
- Use $CI_PROJECT_DIR instead of /builds/$CI_PROJECT_PATH for addons
  path in unit_tests — CI_PROJECT_DIR is the correct GitLab predefined
  variable that works across all runner types

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 02:20:54 -04:00

229 lines
6.8 KiB
YAML

stages:
- lint
- test
- build
- e2e
- notify
variables:
ODOO_IMAGE: odoo:17.0
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
POSTGRES_DB: odoo_test
POSTGRES_USER: odoo
POSTGRES_PASSWORD: odoo
TEMPLATE_DATABASE: odoo_primed
# ================================================================
# LINT & CODE QUALITY
# ================================================================
pylint-odoo:
stage: lint
image: $ODOO_IMAGE
script:
- pip install --no-cache-dir pylint-odoo
- pylint-odoo --rcfile=.pylintrc-odoo addons/itsulu_blog_publisher
allow_failure: true
black:
stage: lint
image: $ODOO_IMAGE
script:
- pip install --no-cache-dir black
- black --check addons/itsulu_blog_publisher
allow_failure: true
# ================================================================
# UNIT TESTS (TDD) & BDD
# ================================================================
unit_tests:
stage: test
image: $ODOO_IMAGE
services:
- name: postgres:15
alias: postgres
command:
- postgres
- -c
- fsync=off
- -c
- shared_buffers=512MB
before_script:
- export PGPASSWORD=$POSTGRES_PASSWORD
# Create primed template database
- createdb -h $POSTGRES_HOST -U $POSTGRES_USER $TEMPLATE_DATABASE
# Install Odoo + modules into template DB
- |
odoo -d $TEMPLATE_DATABASE \
-i base,website,website_blog,mail,itsulu_blog_publisher \
--addons-path=/usr/lib/python3/dist-packages/odoo/addons,$CI_PROJECT_DIR/addons \
--without-demo=all --stop-after-init --db_host=$POSTGRES_HOST --db_user=$POSTGRES_USER \
--db_password=$POSTGRES_PASSWORD
# Install test dependencies
- pip install --no-cache-dir pytest pytest-odoo pytest-bdd pytest-cov pytest-html
script:
- export PGPASSWORD=$POSTGRES_PASSWORD
# Clone template DB for test isolation
- createdb -h $POSTGRES_HOST -U $POSTGRES_USER -T $TEMPLATE_DATABASE $POSTGRES_DB
# Run TDD, BDD, and performance tests
- |
python3 -m pytest \
addons/itsulu_blog_publisher/tests \
-v \
--odoo-database=$POSTGRES_DB \
--cov=addons/itsulu_blog_publisher \
--cov-report=term-missing \
--cov-report=html \
--cov-report=xml \
--junitxml=report.xml \
--html=report-unit.html \
--self-contained-html
artifacts:
when: always
reports:
junit: report.xml
coverage_report:
coverage_format: cobertura
path: coverage.xml
paths:
- htmlcov/
- report-unit.html
expire_in: 30 days
coverage: '/^TOTAL.*\s+(\d+%)$/'
# ================================================================
# E2E TESTS (ITSulu K8s Cluster)
# ================================================================
e2e_tests:
stage: e2e
image: bitnami/kubectl:latest
needs: [build_image]
before_script:
- |
mkdir -p ~/.kube
echo "$KUBE_CONFIG" | base64 -d > ~/.kube/config
script:
# Create ephemeral E2E test job on K8s cluster
- |
TIMESTAMP=$(date +%s)
JOB_NAME="blog-publisher-e2e-test-${TIMESTAMP}"
kubectl apply -f - <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: $JOB_NAME
namespace: itsulu-testing
spec:
backoffLimit: 1
ttlSecondsAfterFinished: 3600
template:
spec:
serviceAccountName: test-runner
restartPolicy: Never
imagePullSecrets:
- name: gitlab-docker-creds
initContainers:
- name: setup-test-db
image: postgres:15-alpine
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: test-db-info
key: password
- name: DB_USER
valueFrom:
secretKeyRef:
name: test-db-info
key: username
command: [sh, -c]
args:
- |
until pg_isready -h test-db-svc -U $$DB_USER; do sleep 2; done
PGPASSWORD=$$PGPASSWORD dropdb -h test-db-svc -U $$DB_USER odoo_e2e --if-exists
PGPASSWORD=$$PGPASSWORD createdb -h test-db-svc -U $$DB_USER -T odoo_template odoo_e2e
containers:
- name: test-runner
image: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
imagePullPolicy: IfNotPresent
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: test-db-info
key: password
- name: DB_USER
valueFrom:
secretKeyRef:
name: test-db-info
key: username
- name: POSTGRES_HOST
value: test-db-svc
command: [sh, -c]
args:
- |
python3 -m pytest /mnt/extra-addons/itsulu_blog_publisher/tests/ \
--odoo-database=odoo_e2e \
-v --tb=short \
--html=/tmp/report-e2e.html --self-contained-html \
--junitxml=/tmp/report-e2e.xml
volumeMounts:
- name: test-results
mountPath: /tmp
volumes:
- name: test-results
emptyDir:
sizeLimit: 1Gi
EOF
# Wait for job completion
kubectl wait --for=condition=complete job/$JOB_NAME -n itsulu-testing --timeout=3600s || true
# Get pod name and download report
POD_NAME=$(kubectl get pods -n itsulu-testing -l batch.kubernetes.io/job-name=$JOB_NAME -o jsonpath='{.items[0].metadata.name}')
kubectl cp itsulu-testing/$POD_NAME:/tmp/report-e2e.html ./report-e2e.html || true
artifacts:
when: always
paths:
- report-e2e.html
expire_in: 1 week
only:
- merge_requests
allow_failure: true # E2E failures don't block merge (informational)
# ================================================================
# BUILD DOCKER IMAGE
# ================================================================
build_image:
stage: build
image: docker:latest
services:
- docker:dind
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG -t $CI_REGISTRY_IMAGE:latest .
- docker push $IMAGE_TAG
- docker push $CI_REGISTRY_IMAGE:latest
only:
- main
- merge_requests
# ================================================================
# NOTIFY ON FAILURE
# ================================================================
notify_failure:
stage: notify
script:
- echo "Pipeline failed for $CI_PROJECT_NAME on $CI_COMMIT_BRANCH"
when: on_failure
only:
- main