From ac125e9719d65366d3d3224b06ee2db3da50f0c1 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Thu, 26 Sep 2024 20:47:18 -0700 Subject: [PATCH 1/9] Fix OAuth2 env var names in example .env file --- env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/env.example b/env.example index 658b0405..440ab97f 100644 --- a/env.example +++ b/env.example @@ -30,5 +30,5 @@ DJANGO_SECURE_SSL_REDIRECT=False DJANGO_ACCOUNT_ALLOW_REGISTRATION=True # application settings -OAUTH_OSM_KEY= -OAUTH_OSM_SECRET= +OAUTH2_OSM_KEY= +OAUTH2_OSM_SECRET= From 6ef05bd0f4b45dc616e806356d5768e7b2265cb1 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Thu, 26 Sep 2024 23:28:33 -0700 Subject: [PATCH 2/9] Split Postgres client and server env vars --- README.rst | 10 +++++----- config/settings/aws_production.py | 16 ---------------- config/settings/common.py | 12 +++++------- config/settings/local.py | 9 --------- config/settings/production.py | 15 --------------- env.example | 17 +++++++++++------ 6 files changed, 21 insertions(+), 58 deletions(-) diff --git a/README.rst b/README.rst index 99558813..09240919 100644 --- a/README.rst +++ b/README.rst @@ -50,11 +50,11 @@ DJANGO_DEFAULT_FROM_EMAIL DEFAULT_FROM_EMAIL n/a DJANGO_SERVER_EMAIL SERVER_EMAIL n/a "osmcha-django " DJANGO_EMAIL_SUBJECT_PREFIX EMAIL_SUBJECT_PREFIX n/a "[osmcha-django] " DJANGO_CHANGESETS_FILTER CHANGESETS_FILTER None None -POSTGRES_USER POSTGRES_USER None None -POSTGRES_PASSWORD POSTGRES_PASSWORD None None -PGHOST PGHOST localhost localhost -OAUTH_OSM_KEY SOCIAL_AUTH_OPENSTREETMAP_KEY None None -OAUTH_OSM_SECRET SOCIAL_AUTH_OPENSTREETMAP_SECRET None None +PGUSER DATABASES None None +PGPASSWORD DATABASES None None +PGHOST DATABASES localhost localhost +OAUTH2_OSM_KEY SOCIAL_AUTH_OPENSTREETMAP_KEY None None +OAUTH2_OSM_SECRET SOCIAL_AUTH_OPENSTREETMAP_SECRET None None DJANGO_ANON_USER_THROTTLE_RATE ANON_USER_THROTTLE_RATE None 30/min DJANGO_COMMON_USER_THROTTLE_RATE COMMON_USER_THROTTLE_RATE None 180/min DJANGO_NON_STAFF_USER_THROTTLE_RATE NON_STAFF_USER_THROTTLE_RATE 3/min 3/min diff --git a/config/settings/aws_production.py b/config/settings/aws_production.py index 88da9850..27a7dba7 100644 --- a/config/settings/aws_production.py +++ b/config/settings/aws_production.py @@ -43,22 +43,6 @@ ]), ] -# DATABASE CONFIGURATION -# ------------------------------------------------------------------------------ -# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ -# DATABASES = { -# 'default': env.db('DATABASE_URL', default='postgres:///osmcha'), -# } -DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': env('POSTGRES_DATABASE', default='osmcha'), - 'USER': env('POSTGRES_USER'), - 'PASSWORD': env('POSTGRES_PASSWORD'), - 'HOST': env('PGHOST', default='localhost') - } -} - REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', diff --git a/config/settings/common.py b/config/settings/common.py index 5e959896..cd7f7c7e 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -122,16 +122,14 @@ # DATABASE CONFIGURATION # ------------------------------------------------------------------------------ # See: https://docs.djangoproject.com/en/dev/ref/settings/#databases -# DATABASES = { -# 'default': env.db('DATABASE_URL', default='postgres:///osmcha'), -# } DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': env('POSTGRES_DATABASE', default='osmcha'), - 'USER': env('POSTGRES_USER'), - 'PASSWORD': env('POSTGRES_PASSWORD'), - 'HOST': env('PGHOST', default='localhost') + 'HOST': env('PGHOST', default=''), + 'PORT': env('PGPORT', default=''), + 'USER': env('PGUSER', default=''), + 'PASSWORD': env('PGPASSWORD', default=''), + 'NAME': env('PGDATABASE', default=''), } } DATABASES['default']['ATOMIC_REQUESTS'] = True diff --git a/config/settings/local.py b/config/settings/local.py index 86721375..d3c7ba75 100644 --- a/config/settings/local.py +++ b/config/settings/local.py @@ -63,14 +63,5 @@ # DATABASE CONFIGURATION # ------------------------------------------------------------------------------ # See: https://docs.djangoproject.com/en/dev/ref/settings/#databases -DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': 'osmcha', - 'USER': env('POSTGRES_USER'), - 'PASSWORD': env('POSTGRES_PASSWORD'), - 'HOST': env('PGHOST', default='localhost') - } -} # Your local stuff: Below this line define 3rd party library settings diff --git a/config/settings/production.py b/config/settings/production.py index 5bb34575..dac17004 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -58,21 +58,6 @@ ]), ] -# DATABASE CONFIGURATION -# ------------------------------------------------------------------------------ -# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ -# DATABASES = { -# 'default': env.db('DATABASE_URL', default='postgres:///osmcha'), -# } -DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': env('POSTGRES_DATABASE', default='osmcha'), - 'USER': env('POSTGRES_USER'), - 'PASSWORD': env('POSTGRES_PASSWORD'), - 'HOST': env('PGHOST', default='localhost') - } -} # CACHING # ------------------------------------------------------------------------------ # Configured to use Redis, if you prefer another method, comment the REDIS and diff --git a/env.example b/env.example index 440ab97f..2f00f516 100644 --- a/env.example +++ b/env.example @@ -1,10 +1,15 @@ -# PostgreSQL -POSTGRES_USER=postgresuser -POSTGRES_PASSWORD=mysecretpass -# Uncomment the next line if you want to use another postgres server (outside your docker instance) -# and define it with the host URL -# PGHOST= +# Settings for PostgreSQL client +PGHOST= +PGPORT= +PGUSER= +PGPASSWORD= +PGDATABASE= + +# Settings for PostgreSQL server (should match above) +POSTGRES_USER= +POSTGRES_PASSWORD= +POSTGRES_DB= # General settings # DJANGO_READ_DOT_ENV_FILE=True From 78f43f150b789874f7c1361f14326812dc9b2b5a Mon Sep 17 00:00:00 2001 From: Jake Low Date: Mon, 30 Sep 2024 11:42:36 -0700 Subject: [PATCH 3/9] Simplify docker entrypoint script --- compose/django/entrypoint.sh | 28 ++++------------------------ env.example | 2 ++ 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/compose/django/entrypoint.sh b/compose/django/entrypoint.sh index 73628e47..4d3c488c 100644 --- a/compose/django/entrypoint.sh +++ b/compose/django/entrypoint.sh @@ -1,32 +1,12 @@ -#!/bin/bash +#!/bin/sh set -e -cmd="$@" -# This entrypoint is used to play nicely with the current cookiecutter configuration. -# Since docker-compose relies heavily on environment variables itself for configuration, we'd have to define multiple -# environment variables just to support cookiecutter out of the box. That makes no sense, so this little entrypoint -# does all this for us. -export REDIS_URL=redis://redis:6379 -# the official postgres image uses 'postgres' as default user if not set explictly. -if [ -z "$POSTGRES_USER" ]; then - export POSTGRES_USER=postgres -fi - -if [ -z "$POSTGRES_HOST" ]; then - export POSTGRES_HOST=postgres -fi - -export PGHOST=$POSTGRES_HOST -export POSTGRES_USER=$POSTGRES_USER -export POSTGRES_PASSWORD=$POSTGRES_PASSWORD -# export DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$POSTGRES_USER - -function postgres_ready(){ +postgres_ready() { python << END import sys import psycopg2 try: - conn = psycopg2.connect(dbname="$POSTGRES_USER", user="$POSTGRES_USER", password="$POSTGRES_PASSWORD", host="$POSTGRES_HOST") + conn = psycopg2.connect("") # use environment variables for connection except psycopg2.OperationalError: sys.exit(-1) sys.exit(0) @@ -39,4 +19,4 @@ until postgres_ready; do done >&2 echo "Postgres is up - continuing..." -exec $cmd +exec $@ diff --git a/env.example b/env.example index 2f00f516..0502d2a8 100644 --- a/env.example +++ b/env.example @@ -11,6 +11,8 @@ POSTGRES_USER= POSTGRES_PASSWORD= POSTGRES_DB= +REDIS_URL=redis://redis:6379 + # General settings # DJANGO_READ_DOT_ENV_FILE=True DJANGO_ADMIN_URL= From d6f009c31122cff9c026e6341512e6ba81637637 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Mon, 30 Sep 2024 17:59:00 -0700 Subject: [PATCH 4/9] Run osmcha-frontend container in compose app This brings the local dev environment closer to production by using the same frontend container. It also changes the backend to serve with gunicorn by default, even in dev mode. Also, static files are now always served by the frontend and never by Django, even in dev mode. --- Dockerfile | 17 ++++++------ Procfile | 1 - compose/django/gunicorn.sh | 3 --- compose/django/start-dev.sh | 2 +- compose/nginx/Dockerfile | 4 --- compose/nginx/nginx.conf | 52 ------------------------------------- config/settings/common.py | 2 +- config/urls.py | 13 +--------- docker-compose.yml | 20 ++++++++++---- env.example | 1 + 10 files changed, 28 insertions(+), 87 deletions(-) delete mode 100644 Procfile delete mode 100644 compose/django/gunicorn.sh delete mode 100644 compose/nginx/Dockerfile delete mode 100644 compose/nginx/nginx.conf diff --git a/Dockerfile b/Dockerfile index 2002a188..9c0f0d9e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM python:3.10-slim-bookworm ARG DEBIAN_FRONTEND=noninteractive +ARG REQUIREMENTS_FILE=production.txt +ARG DJANGO_SETTINGS_MODULE=config.settings.production RUN apt-get update -qq -y \ && apt-get install -y curl wget python3 python3-dev python3-pip git \ @@ -10,21 +12,20 @@ RUN apt-get update -qq -y \ # Requirements have to be pulled and installed here, otherwise caching won't work COPY ./requirements /requirements - -RUN pip install -r /requirements/production.txt +RUN pip install -r /requirements/$REQUIREMENTS_FILE COPY . /app RUN useradd django RUN chown -R django:django /app +WORKDIR /app + +RUN python manage.py collectstatic --noinput -COPY ./compose/django/gunicorn.sh /gunicorn.sh COPY ./compose/django/entrypoint.sh /entrypoint.sh -RUN sed -i 's/\r//' /entrypoint.sh \ - && sed -i 's/\r//' /gunicorn.sh \ - && chmod +x /entrypoint.sh \ - && chmod +x /gunicorn.sh +RUN chmod +x /entrypoint.sh -WORKDIR /app USER django +VOLUME /app/staticfiles ENTRYPOINT ["/entrypoint.sh"] +CMD ["gunicorn", "config.wsgi", "-w", "4", "-b", "0.0.0.0:5000", "--chdir", "/app"] diff --git a/Procfile b/Procfile deleted file mode 100644 index c00f4235..00000000 --- a/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: gunicorn config.wsgi:application diff --git a/compose/django/gunicorn.sh b/compose/django/gunicorn.sh deleted file mode 100644 index 014f173e..00000000 --- a/compose/django/gunicorn.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -python /app/manage.py collectstatic --noinput -/usr/local/bin/gunicorn config.wsgi -w 4 -b 0.0.0.0:5000 --chdir=/app \ No newline at end of file diff --git a/compose/django/start-dev.sh b/compose/django/start-dev.sh index 04e06981..b11d73e3 100644 --- a/compose/django/start-dev.sh +++ b/compose/django/start-dev.sh @@ -1,3 +1,3 @@ #!/bin/sh python manage.py migrate -python manage.py runserver_plus 0.0.0.0:8000 +python manage.py runserver_plus 0.0.0.0:5000 diff --git a/compose/nginx/Dockerfile b/compose/nginx/Dockerfile deleted file mode 100644 index 61efea46..00000000 --- a/compose/nginx/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM nginx:latest -ADD nginx.conf /etc/nginx/nginx.conf - - diff --git a/compose/nginx/nginx.conf b/compose/nginx/nginx.conf deleted file mode 100644 index 505b5e54..00000000 --- a/compose/nginx/nginx.conf +++ /dev/null @@ -1,52 +0,0 @@ -user nginx; -worker_processes 1; - -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; - -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - upstream app { - server django:5000; - } - - server { - listen 80; - charset utf-8; - - - - location / { - # checks for static file, if not found proxy to app - try_files $uri @proxy_to_app; - } - - # cookiecutter-django app - location @proxy_to_app { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_redirect off; - proxy_pass http://app; - - } - } -} diff --git a/config/settings/common.py b/config/settings/common.py index cd7f7c7e..e2f80cf7 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -205,7 +205,7 @@ STATIC_ROOT = str(ROOT_DIR('staticfiles')) # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url -STATIC_URL = '/static/' +STATIC_URL = '/static/django/' # See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS STATICFILES_DIRS = [] diff --git a/config/urls.py b/config/urls.py index 25a28151..e6192c1d 100644 --- a/config/urls.py +++ b/config/urls.py @@ -19,16 +19,6 @@ urlpatterns = [] -# If static files are not intercepted by the web-server, serve them with the dev-server: -if settings.DEBUG is False: # if DEBUG is True it will be served automatically - urlpatterns += [ - path( - 'static/', - static_views.serve, - {'document_root': settings.STATIC_ROOT} - ), - ] - api_urls = [ path( '{}'.format(API_BASE_URL), @@ -90,8 +80,7 @@ def health_check(request): '', include(api_urls) ), - - ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + ] if settings.DEBUG: # This allows the error pages to be debugged during development, just visit diff --git a/docker-compose.yml b/docker-compose.yml index b180a910..59084008 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,17 +18,27 @@ services: depends_on: - postgres - redis - command: /gunicorn.sh + volumes: + # copy static files into a shared volume so the frontend can serve them + - staticfiles:/app/staticfiles env_file: .env - nginx: - build: ./compose/nginx + frontend: + image: osmcha-frontend depends_on: - django + volumes: + # frontend serves django app's static files via shared volume + - staticfiles:/srv/www/static/django + env_file: .env ports: - - "0.0.0.0:80:80" - + - "0.0.0.0:8000:80" redis: image: redis:latest + +volumes: + staticfiles: + postgres_data: + postgres_backup: diff --git a/env.example b/env.example index 0502d2a8..2ffe7cab 100644 --- a/env.example +++ b/env.example @@ -11,6 +11,7 @@ POSTGRES_USER= POSTGRES_PASSWORD= POSTGRES_DB= +BACKEND_URL=http://django:5000 REDIS_URL=redis://redis:6379 # General settings From d6e366705452a19144ce3980a5e19ea496bf45b4 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Mon, 30 Sep 2024 18:41:11 -0700 Subject: [PATCH 5/9] Fix Postgres auth for Github Actions test workflow --- .github/workflows/django.yml | 10 +++++----- config/settings/common.py | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index 4a51c1f3..b0e566ac 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -8,7 +8,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.9, '3.10'] + python-version: ['3.9', '3.10'] steps: - uses: actions/checkout@v2 @@ -33,7 +33,7 @@ jobs: run: | coverage run manage.py test --settings=config.settings.tests env: - OAUTH_OSM_KEY: ${{ secrets.OAUTH_OSM_KEY }} - OAUTH_OSM_SECRET: ${{ secrets.OAUTH_OSM_SECRET }} - POSTGRES_USER: ${{ secrets.POSTGRES_USER }} - POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + OAUTH2_OSM_KEY: ${{ secrets.OAUTH_OSM_KEY }} + OAUTH2_OSM_SECRET: ${{ secrets.OAUTH_OSM_SECRET }} + PGUSER: ${{ secrets.POSTGRES_USER }} + PGPASSWORD: ${{ secrets.POSTGRES_PASSWORD }} diff --git a/config/settings/common.py b/config/settings/common.py index e2f80cf7..01605676 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -125,11 +125,11 @@ DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'HOST': env('PGHOST', default=''), - 'PORT': env('PGPORT', default=''), - 'USER': env('PGUSER', default=''), + 'HOST': env('PGHOST', default='localhost'), + 'PORT': env('PGPORT', default='5432'), + 'USER': env('PGUSER', default='postgres'), 'PASSWORD': env('PGPASSWORD', default=''), - 'NAME': env('PGDATABASE', default=''), + 'NAME': env('PGDATABASE', default='postgres'), } } DATABASES['default']['ATOMIC_REQUESTS'] = True From 4d950ce7976e0eb1a8fc9158e475a1f0a3b463e4 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Wed, 23 Oct 2024 22:41:54 -0700 Subject: [PATCH 6/9] Remove redundant volume definitions from docker-compose.yml --- docker-compose.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 59084008..81deef74 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,5 @@ version: '2' -volumes: - postgres_data: {} - postgres_backup: {} - services: postgres: build: ./compose/postgres From b537366ac1ea378ad00acb620fdb5168318dbf97 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Tue, 29 Oct 2024 17:46:58 -0700 Subject: [PATCH 7/9] Move some production settings overrides to Dockerfile --- Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9c0f0d9e..46a6e7d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,5 +27,9 @@ RUN chmod +x /entrypoint.sh USER django VOLUME /app/staticfiles +# Default number of gunicorn worker processes. Using an env var instead of --workers +# in the command below lets users of this docker image override the default easily. +ENV WEB_CONCURRENCY 4 + ENTRYPOINT ["/entrypoint.sh"] -CMD ["gunicorn", "config.wsgi", "-w", "4", "-b", "0.0.0.0:5000", "--chdir", "/app"] +CMD ["gunicorn", "config.wsgi", "-t", "120", "-b", "0.0.0.0:5000", "--access-logfile", "-"] From cc0d27b1fa22de963b4a60a1d7e3ee0cf32ecd38 Mon Sep 17 00:00:00 2001 From: Jake Low Date: Tue, 29 Oct 2024 17:48:55 -0700 Subject: [PATCH 8/9] Remove broken 404 and 500 error pages --- osmchadjango/templates/404.html | 1 - osmchadjango/templates/500.html | 1 - 2 files changed, 2 deletions(-) delete mode 100644 osmchadjango/templates/404.html delete mode 100644 osmchadjango/templates/500.html diff --git a/osmchadjango/templates/404.html b/osmchadjango/templates/404.html deleted file mode 100644 index 830cfb5c..00000000 --- a/osmchadjango/templates/404.html +++ /dev/null @@ -1 +0,0 @@ -{% extends "frontend/index.html" %} diff --git a/osmchadjango/templates/500.html b/osmchadjango/templates/500.html deleted file mode 100644 index 8dcd327f..00000000 --- a/osmchadjango/templates/500.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'frontend/index.html' %} From c2835297de559139e82a1dc98c1ff931aa0adc0e Mon Sep 17 00:00:00 2001 From: Jake Low Date: Wed, 6 Nov 2024 12:22:18 -0800 Subject: [PATCH 9/9] Update GitHub Actions docker build/push workflow --- .github/workflows/docker-publish.yml | 40 +++++++++++++++++++--------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 3fd75943..18793643 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -2,8 +2,12 @@ name: Build Docker Image, Push to GHCR on: push: - branches: - - master + branches: [ "main" ] + tags: [ 'v*.*.*' ] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: osmcha/osmcha-django jobs: build: @@ -11,25 +15,37 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 + # Enable BuildKit for docker builds. This enables building + # multi-platform images and exporting the layer cache + # https://github.com/docker/setup-buildx-action - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + # https://github.com/docker/login-action + - name: Login to Registry ${{ env.REGISTRY }} + uses: docker/login-action@v3 with: - registry: ghcr.io + registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . push: true - tags: | - ghcr.io/osmcha/osmcha-django:latest - ghcr.io/osmcha/osmcha-django:${{ github.sha }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file + cache-to: type=gha,mode=max