diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 000000000..f95dc1fe5 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,46 @@ +name: Create and publish a Docker image + +on: + push: + branches: ["main"] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + latest=true + tags: | + type=ref,event=branch + type=sha + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/docker-test-build.yml b/.github/workflows/docker-test-build.yml new file mode 100644 index 000000000..d50a34594 --- /dev/null +++ b/.github/workflows/docker-test-build.yml @@ -0,0 +1,37 @@ +name: Docker test build + +on: + pull_request: + push: + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build-image: + runs-on: ubuntu-latest + + strategy: + matrix: + req_file: + - prod.txt + - tests.txt + + # steps taken (and trimmed) from docker-publish.yml + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Test docker image build (local development) + uses: docker/build-push-action@v6 + with: + context: . + push: false + build-args: | + REQ_FILE=requirements/${{ matrix.req_file }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cca9433a4..609354933 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ on: jobs: tests: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -29,9 +29,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: "3.8" - name: Install dependencies run: | python -m pip install --upgrade pip setuptools coveralls "tox<4" diff --git a/.gitignore b/.gitignore index 6edafa945..a8dc6f44a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ locale/*/LC_MESSAGES/django.mo */locale/*/LC_MESSAGES/django.mo .sass-cache/ .coverage +.direnv +.envrc .tox djangoproject/cache djangoproject/static/js/lib/jquery-flot/examples diff --git a/Dockerfile b/Dockerfile index b8c447e25..cce04edec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,13 +13,17 @@ RUN apt-get update \ && apt-get install --assume-yes --no-install-recommends \ gettext \ git \ + libpq5 \ make \ netcat-openbsd \ npm \ postgresql-client-13 \ rsync \ + zlib1g \ && rm -rf /var/lib/apt/lists/* +ARG REQ_FILE=requirements/prod.txt + # install python dependencies COPY ./requirements ./requirements RUN apt-get update \ @@ -28,22 +32,21 @@ RUN apt-get update \ gcc \ libc6-dev \ libpq-dev \ - && python3 -m pip install --no-cache-dir -r requirements/tests.txt \ + zlib1g-dev \ + && python3 -m pip install --no-cache-dir -r ${REQ_FILE} \ && apt-get purge --assume-yes --auto-remove \ gcc \ libc6-dev \ libpq-dev \ + zlib1g-dev \ && rm -rf /var/lib/apt/lists/* # install node dependencies COPY ./package.json ./package.json RUN npm install -# copy docker-entrypoint.sh -COPY ./docker-entrypoint.sh ./docker-entrypoint.sh - # copy project COPY . . # run docker-entrypoint.sh -ENTRYPOINT ["./docker-entrypoint.sh"] +ENTRYPOINT ["./docker-entrypoint.prod.sh"] diff --git a/djangoproject/settings/prod.py b/djangoproject/settings/prod.py index 37b70717c..363253866 100644 --- a/djangoproject/settings/prod.py +++ b/djangoproject/settings/prod.py @@ -1,15 +1,17 @@ from .common import * # noqa +DOMAIN_NAME = os.getenv("DOMAIN_NAME", "djangoproject.com") + ALLOWED_HOSTS = [ - "www.djangoproject.com", - "djangoproject.com", - "docs.djangoproject.com", - "dashboard.djangoproject.com", + f"www.{DOMAIN_NAME}", + DOMAIN_NAME, + f"docs.{DOMAIN_NAME}", + f"dashboard.{DOMAIN_NAME}", ] + SECRETS.get("allowed_hosts", []) -LOCALE_MIDDLEWARE_EXCLUDED_HOSTS = ["docs.djangoproject.com"] +LOCALE_MIDDLEWARE_EXCLUDED_HOSTS = [f"docs.{DOMAIN_NAME}"] -DEBUG = False +DEBUG = os.getenv("DJANGO_DEBUG", "false").lower() == "true" THUMBNAIL_DEBUG = DEBUG CACHES = { @@ -37,7 +39,7 @@ MEDIA_ROOT = str(DATA_DIR.joinpath("media")) -MEDIA_URL = "https://media.djangoproject.com/" +MEDIA_URL = f"https://media.{DOMAIN_NAME}/" MIDDLEWARE = ( ["django.middleware.cache.UpdateCacheMiddleware"] @@ -58,7 +60,7 @@ STATIC_ROOT = str(DATA_DIR.joinpath("static")) -STATIC_URL = "https://static.djangoproject.com/" +STATIC_URL = f"https://static.{DOMAIN_NAME}/" # Docs settings DOCS_BUILD_ROOT = DATA_DIR.joinpath("data", "docbuilds") @@ -67,7 +69,7 @@ HOST_SCHEME = "https" -PARENT_HOST = "djangoproject.com" +PARENT_HOST = DOMAIN_NAME # django-push settings diff --git a/docker-compose.yml b/docker-compose.yml index 72693b9b7..f0143f9b4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,9 @@ services: build: context: ./ dockerfile: Dockerfile + args: + - REQ_FILE=requirements/tests.txt + entrypoint: docker-entrypoint.dev.sh command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/usr/src/app/ diff --git a/docker-entrypoint.dev.sh b/docker-entrypoint.dev.sh new file mode 100755 index 000000000..515d5dac8 --- /dev/null +++ b/docker-entrypoint.dev.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +echo "Waiting for postgres..." + +while ! nc -z db 5432; do + sleep 0.1 +done + +echo "PostgreSQL started" + +python -m manage flush --no-input +# PGPASSWORD=djangoproject psql --host db --port 5432 --username=code.djangoproject --dbname=code.djangoproject < tracdb/trac.sql +python -m manage migrate +make compile-scss # must come before collectstatic +python -m manage collectstatic --no-input --clear +python -m manage loaddata dev_sites +python -m manage loaddata doc_releases +# git config --global url."https://".insteadOf git:// +# python -m manage update_docs +python -m manage loaddata dashboard_production_metrics +# python -m manage loaddata dashboard_example_data +python -m manage update_metrics +#python -m manage update_index + +exec "$@" diff --git a/docker-entrypoint.prod.sh b/docker-entrypoint.prod.sh new file mode 100755 index 000000000..a78cb5641 --- /dev/null +++ b/docker-entrypoint.prod.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +python -m manage migrate +python -m manage compilemessages +make compile-scss # must come before collectstatic +python -m manage collectstatic --no-input --clear + +exec "$@" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index 554200f9c..000000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -echo "Waiting for postgres..." - -while ! nc -z db 5432; do - sleep 0.1 -done - -echo "PostgreSQL started" - -python manage.py flush --no-input -# PGPASSWORD=djangoproject psql --host db --port 5432 --username=code.djangoproject --dbname=code.djangoproject < tracdb/trac.sql -python manage.py migrate -python manage.py collectstatic --no-input --clear -python manage.py loaddata dev_sites -python manage.py loaddata doc_releases -# git config --global url."https://".insteadOf git:// -# python manage.py update_docs -python manage.py loaddata dashboard_production_metrics -# python manage.py loaddata dashboard_example_data -python manage.py update_metrics -#python manage.py update_index -make compile-scss - -exec "$@" diff --git a/requirements/prod.txt b/requirements/prod.txt index 2d1f8e889..acf14bdce 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -1,3 +1,4 @@ -r common.txt +gunicorn==23.0.0 redis==5.0.8 -sentry-sdk==2.11.0 +sentry-sdk==2.14.0