stages: - verify - test - security - build workflow: rules: - if: $CI_COMMIT_TAG - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH default: interruptible: true variables: PIP_DISABLE_PIP_VERSION_CHECK: "1" PIP_NO_INPUT: "1" PYTHONDONTWRITEBYTECODE: "1" dependency-source-policy: stage: verify image: "$INTERNAL_CONTAINER_PROXY/alpine:3.20" script: - test -n "$INTERNAL_CONTAINER_PROXY" || (echo "INTERNAL_CONTAINER_PROXY must point to the approved container-image proxy" && exit 1) - test -n "$INTERNAL_PYPI_URL" || (echo "INTERNAL_PYPI_URL must point to the approved PyPI proxy" && exit 1) - test -n "$INTERNAL_NPM_REGISTRY" || (echo "INTERNAL_NPM_REGISTRY must point to the approved npm proxy" && exit 1) rules: - if: $CI_COMMIT_BRANCH || $CI_MERGE_REQUEST_ID || $CI_COMMIT_TAG backend-tests: stage: test image: "$INTERNAL_CONTAINER_PROXY/python:3.11-slim" needs: ["dependency-source-policy"] cache: key: files: - backend/requirements.txt paths: - .cache/pip variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" SECRET_KEY: "ci-test-secret-not-for-deployment" CREDENTIAL_ENCRYPTION_KEY: "Q6NgOwoM3sna4ti4UeEo3Lo2cIzxc8wJMvMZ2cmw7lU=" DATABASE_URL: "sqlite:///./ci-test.db" REDIS_URL: "redis://localhost:6379/15" CASDOOR_ENDPOINT: "https://casdoor.example.test" CASDOOR_CLIENT_ID: "ci-client" CASDOOR_CLIENT_SECRET: "ci-client-secret" CASDOOR_ORG_NAME: "ci-org" CASDOOR_APP_NAME: "ci-app" before_script: - python -m pip install --index-url "$INTERNAL_PYPI_URL" --upgrade pip - python -m pip install --index-url "$INTERNAL_PYPI_URL" -r backend/requirements.txt script: - cd backend - python -m compileall -q app - pytest -q --junitxml=../reports/backend-junit.xml artifacts: when: always reports: junit: reports/backend-junit.xml paths: - reports/backend-junit.xml expire_in: 30 days frontend-build: stage: test image: "$INTERNAL_CONTAINER_PROXY/node:20-alpine" needs: ["dependency-source-policy"] cache: key: files: - frontend/package-lock.json paths: - frontend/.npm/ before_script: - npm config set registry "$INTERNAL_NPM_REGISTRY" script: - cd frontend - npm ci --cache .npm --prefer-offline - npm run build artifacts: paths: - frontend/dist/ expire_in: 7 days python-dependency-audit: stage: security image: "$INTERNAL_CONTAINER_PROXY/python:3.11-slim" needs: ["dependency-source-policy"] cache: key: files: - backend/requirements.txt - ci/requirements-audit.txt paths: - .cache/pip variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" before_script: - python -m pip install --index-url "$INTERNAL_PYPI_URL" --upgrade pip - python -m pip install --index-url "$INTERNAL_PYPI_URL" -r ci/requirements-audit.txt script: - mkdir -p reports - pip-audit --index-url "$INTERNAL_PYPI_URL" -r backend/requirements.txt --format json --output reports/pip-audit.json artifacts: when: always paths: - reports/pip-audit.json expire_in: 30 days container-build: stage: build image: "$INTERNAL_CONTAINER_PROXY/docker:27-cli" needs: ["backend-tests", "frontend-build", "python-dependency-audit"] services: - name: "$INTERNAL_CONTAINER_PROXY/docker:27-dind" variables: DOCKER_HOST: tcp://docker:2375 DOCKER_TLS_CERTDIR: "" script: - docker build --pull --build-arg "PYTHON_BASE_IMAGE=$INTERNAL_CONTAINER_PROXY/python:3.11-slim" --build-arg "PIP_INDEX_URL=$INTERNAL_PYPI_URL" --label "org.opencontainers.image.revision=$CI_COMMIT_SHA" --tag "h3c-onu-ms-backend:$CI_COMMIT_SHA" backend - docker build --pull --build-arg "NODE_BASE_IMAGE=$INTERNAL_CONTAINER_PROXY/node:20-alpine" --build-arg "NGINX_BASE_IMAGE=$INTERNAL_CONTAINER_PROXY/nginx:alpine" --build-arg "NPM_CONFIG_REGISTRY=$INTERNAL_NPM_REGISTRY" --label "org.opencontainers.image.revision=$CI_COMMIT_SHA" --tag "h3c-onu-ms-frontend:$CI_COMMIT_SHA" frontend rules: - if: $CI_COMMIT_BRANCH || $CI_MERGE_REQUEST_ID || $CI_COMMIT_TAG