From 2e6052866708d5ef76fa322077a8ab34741ea151 Mon Sep 17 00:00:00 2001 From: Haydar Ghasemi Date: Sat, 26 Sep 2026 13:38:27 +0330 Subject: [PATCH] fix(preferences): add git ci add git ci --- .dockerignore | 13 ++++++ .gitlab-ci.yml | 116 +++++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 17 +++++--- 3 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 .dockerignore create mode 100644 .gitlab-ci.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..514ebd7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.git +.idea +.forgejo +.gitlab-ci.yml +.env +venv +.venv +__pycache__ +*.pyc +log +logs +media +preferences_db diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..68c79b0 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,116 @@ +stages: + - build + - test + - deploy + +# Builds the Docker image and pushes it to the GitLab container registry on +# port 443 (not 5050). Uses Docker-in-Docker (dind); the runner must have +# privileged = true and no host docker.sock mounted into services. TLS must +# stay off (DOCKER_TLS_CERTDIR: "") or the daemon listens on 2376 only. +# Tagged with the commit SHA; :latest is also pushed on the default branch. +build: + stage: build + image: docker:29.8.1 + services: + - docker:29.8.1-dind + variables: + DOCKER_HOST: tcp://docker:2375 + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" + rules: + - if: $CI_PIPELINE_SOURCE == "push" + script: + - | + echo "Waiting for dind daemon..." + for i in $(seq 1 60); do + if docker info >/dev/null 2>&1; then + echo "dind daemon is up" + break + fi + sleep 1 + done + - docker info + # registry.gitlab.winsoo.org:443 flaps (~50% of connects time out from the + # runner's network), so retry the registry operations. + - | + retry() { + local n=1 max=6 delay=10 + until "$@"; do + if [ $n -ge $max ]; then + echo "giving up after $n attempts" + return 1 + fi + echo "attempt $n failed, retrying in ${delay}s..." + n=$((n + 1)) + sleep $delay + done + } + - retry sh -c 'echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "registry.gitlab.winsoo.org"' + - docker build --pull -t "registry.gitlab.winsoo.org/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA" . + - retry docker push "registry.gitlab.winsoo.org/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA" + - | + if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then + docker tag "registry.gitlab.winsoo.org/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA" "registry.gitlab.winsoo.org/$CI_PROJECT_PATH:latest" + retry docker push "registry.gitlab.winsoo.org/$CI_PROJECT_PATH:latest" + fi + after_script: + - docker rmi "registry.gitlab.winsoo.org/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA" 2>/dev/null || true + +test: + stage: test + image: debian:13 + services: + - name: postgres:16 + alias: preferences_db + rules: + - if: $CI_PIPELINE_SOURCE == "push" + cache: + key: pip + paths: + - .cache/pip + variables: + PIP_CACHE_DIR: $CI_PROJECT_DIR/.cache/pip + # postgres service + POSTGRES_USER: root + POSTGRES_PASSWORD: ci-password + POSTGRES_DB: preferences_db + # app settings; dummy values only, real secrets never belong in a test job + DEBUG: "true" + DB_NAME: preferences_db + DB_USER: root + DB_PASSWORD: ci-password + DB_HOST: preferences_db + DB_PORT: "5432" + BASE_OAUTH2_PROVIDER_PUBLIC_URL: https://accounts.invalid/oauth2 + BASE_OAUTH2_PROVIDER_PRIVATE_URL: https://accounts.invalid/oauth2 + CLIENT_ID: ci + CLIENT_SECRET: ci + SCOPES: "" + before_script: + # keep in sync with the Dockerfile + - apt-get update + - apt-get install -y python3 python3-pip binutils libproj-dev gdal-bin + - pip3 install --break-system-packages --ignore-installed -r requirements.txt + - pip3 install --break-system-packages setuptools + script: + - python3 manage.py test --noinput + +# Runs on the staging host through a shell runner tagged `staging` that can use +# the docker CLI. The compose stack keeps its ./preferences checkout (mounted at +# /app), so this updates that checkout and restarts the service. +# Set DEPLOY_DIR in Settings > CI/CD > Variables (the directory that holds +# docker-compose.yml and the ./preferences checkout). +deploy_staging: + stage: deploy + tags: + - staging + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + when: manual + allow_failure: true # otherwise the pipeline shows "blocked" until someone deploys + environment: + name: staging + script: + - cd "$DEPLOY_DIR" + - git -C preferences pull --ff-only origin "$CI_DEFAULT_BRANCH" + - docker compose up -d --build preferences diff --git a/Dockerfile b/Dockerfile index 072fa8e..c36b464 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,14 @@ -FROM debian:12 -ENV PYTHONUNBUFFERED 1 +FROM debian:13 +ENV PYTHONUNBUFFERED=1 WORKDIR /app -RUN date -RUN apt update -RUN apt install gnupg2 netcat-traditional libssl-dev libcrypto++-dev lsb-release python3-pip -y + +RUN apt update && \ + apt install -y python3 python3-pip binutils libproj-dev gdal-bin cron && \ + rm -rf /var/lib/apt/lists/* COPY requirements.txt /app/requirements.txt -RUN pip3 install --break-system-packages -r requirements.txt +RUN pip3 install --break-system-packages --ignore-installed -r requirements.txt +RUN pip3 install --break-system-packages setuptools +# In docker compose the ./preferences:/app volume overrides this copy; +# in CI the image has to carry the code itself. +COPY . /app #ENTRYPOINT ["./run.sh"]