Repository: supakeen/pinnwand (language: python)

Issue:
CI to push Containerfile to container repo
Having the image in quay.io updated automatically would be nice.

This could be done using an action such as https://github.com/redhat-actions/push-to-registry if remaining on quay.i is desired.

Alternately, Github's own ghcr.io package repo could be used, which might aid in discoverability due to it being listed in the left bar on the repo homepage.

In either case, I'd be happy to take this on myself, if approved.

As a further enhancement to this, additional build stages could be added that include common database engines, such as mysql & postgres, separately tagged.

For example, `supakeen/pinnwand:1.5.0` would be the base, with just sqlite support, `supakeen/pinnwand:1.5.0-postgres` could then have psycopg2 pre-installed.


Discussion / hints:
I'd be happy to have them published by CI to `ghcr.io` I like the idea of having the `-postgres` and/or `-mysql` postfixes on the containers. If you can tell me how or want to do it yourself please do :)

Fix patch:
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 1f3655d..c99c8de 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -1,33 +1,83 @@
-name: CI
+name: Build & Deploy
 
 on:
-  push:
-  pull_request:
-  schedule:
-  # run at 7:00 on the first of every month
-  - cron: '0 7 1 * *'
+  workflow_call:
 
 jobs:
-  build:
+  build-base:
+    name: Build & push base image
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v3
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+
+      - name: Login to Github Container Registry
+        uses: docker/login-action@v2
+        with:
+          registry: ghcr.io
+          username: ${{ github.repository_owner }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Generate docker image metadata
+        uses: docker/metadata-action@v4
+        id: meta
+        with:
+            images: ghcr.io/supakeen/pinnwand
+            tags: |
+                type=ref,event=tag,enable=${{ startsWith(github.ref, 'refs/tags/') }}
+                type=raw,value=latest
+
+      - name: Build and push
+        uses: docker/build-push-action@v4
+        with:
+          context: .
+          file: ./Containerfile
+          target: base
+          push: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') }}
+          cache-from: type=registry,ref=ghcr.io/supakeen/pinnwand:latest
+          cache-to: type=inline
+          tags: ${{ steps.meta.outputs.tags }}
+
+  build-additional-images:
+    name: Build & push additional images
     runs-on: ubuntu-latest
-    continue-on-error: ${{ matrix.python-version == 'pypy-3.7' }}
     strategy:
       fail-fast: false
       matrix:
-        python-version: [3.8, 3.9, "3.10", "3.11"]
+        container-stage: ["psql","mysql"]
     steps:
-    - uses: actions/checkout@v2
-      with:
-        fetch-depth: 0
-    - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v2
-      with:
-        python-version: ${{ matrix.python-version }}
-    - name: Install dependencies
-      run: |
-        python -m pip install --upgrade pip
-        pip install -r requirements.txt
-        pip install pytest pytest-cov
-    - name: Test with pytest
-      run: |
-        pytest --cov=pinnwand
+      - name: Checkout code
+        uses: actions/checkout@v3
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+
+      - name: Login to Github Container Registry
+        uses: docker/login-action@v2
+        with:
+          registry: ghcr.io
+          username: ${{ github.repository_owner }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Generate docker image metadata
+        uses: docker/metadata-action@v4
+        id: meta
+        with:
+          images: ghcr.io/supakeen/pinnwand
+          tags: |
+              type=ref,event=tag,suffix=-${{ matrix.container-stage }},enable=${{ startsWith(github.ref, 'refs/tags/') }}
+              type=raw,value=latest-${{ matrix.container-stage }}
+
+      - name: Build and push
+        uses: docker/build-push-action@v4
+        with:
+          context: .
+          file: ./Containerfile
+          target: ${{ matrix.container-stage }}
+          push: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') }}
+          cache-from: type=registry,ref=ghcr.io/supakeen/pinnwand:latest-${{ matrix.container-stage }}
+          cache-to: type=inline
+          tags: ${{ steps.meta.outputs.tags }}
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index d4fd11c..fba17ec 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -1,32 +1,25 @@
 name: Linters
 
 on:
-  push:
-  pull_request:
+  workflow_call:
 
 jobs:
-  black:
+  lint:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
+
     - name: Set up Python
-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
+
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
-        pip install black codespell
+        pip install -r requirements.txt
+        pip install black codespell types-docutils mypy
+
     - name: Check with black
       run: black --check src/pinnwand
-#  mypy:
-#    runs-on: ubuntu-latest
-#    steps:
-#    - uses: actions/checkout@v2
-#    - name: Set up Python
-#      uses: actions/setup-python@v2
-#    - name: Install dependencies
-#      run: |
-#        python -m pip install --upgrade pip
-#        pip install -r requirements.txt
-#        pip install types-docutils mypy
-#    - name: Check with mypy
-#      run: mypy src/pinnwand
+
+    # - name: Check with mypy
+    #   run: mypy src/pinnwand
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
new file mode 100644
index 0000000..e805c56
--- /dev/null
+++ b/.github/workflows/main.yaml
@@ -0,0 +1,20 @@
+name: CI
+
+on:
+  push:
+  pull_request:
+  release:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  lint:
+    uses: ./.github/workflows/lint.yaml
+  test:
+    uses: ./.github/workflows/test.yaml
+  vuln:
+    uses: ./.github/workflows/vuln.yaml
+  build-push:
+    uses: ./.github/workflows/build.yaml
diff --git a/.github/workflows/vuln.yaml b/.github/workflows/vuln.yaml
index 6af1778..a63e9cd 100644
--- a/.github/workflows/vuln.yaml
+++ b/.github/workflows/vuln.yaml
@@ -1,31 +1,24 @@
 name: Vulnerability Scanners
 
 on:
-  push:
-  pull_request:
+  workflow_call:
 
 jobs:
   bandit:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
+
     - name: Set up Python
-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
+
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
-        pip install bandit
+        pip install bandit pip-audit
+
     - name: Check with bandit
       run: bandit -r src/pinnwand
-  pip-audit:
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/checkout@v2
-    - name: Set up Python
-      uses: actions/setup-python@v2
-    - name: Install dependencies
-      run: |
-        python -m pip install --upgrade pip
-        pip install pip-audit
+
     - name: Check with pip-audit
       run: pip-audit --requirement requirements.txt
diff --git a/Containerfile b/Containerfile
index af9b0d9..c748347 100644
--- a/Containerfile
+++ b/Containerfile
@@ -1,4 +1,4 @@
-FROM registry.fedoraproject.org/fedora-minimal:36
+FROM registry.fedoraproject.org/fedora-minimal:36 AS base
 
 RUN \
     microdnf install -y \
@@ -17,5 +17,29 @@ RUN venv/bin/pip install -r requirements.txt
 COPY src/pinnwand /usr/app/pinnwand
 
 EXPOSE 8000
+CMD ["venv/bin/python3", "-m", "pinnwand", "http"]
+
+# =========================================================================
+
+FROM base AS psql
+WORKDIR /usr/app
+COPY --from=base /usr/app ./
+RUN venv/bin/pip install psycopg2-binary
+
+EXPOSE 8000
+CMD ["venv/bin/python3", "-m", "pinnwand", "http"]
 
+# =========================================================================
+
+FROM base AS mysql
+WORKDIR /usr/app
+RUN \
+    microdnf install -y \
+        community-mysql-devel python3-devel gcc && \
+    microdnf clean all
+
+COPY --from=base /usr/app ./
+RUN venv/bin/pip install mysqlclient
+
+EXPOSE 8000
 CMD ["venv/bin/python3", "-m", "pinnwand", "http"]


Test patch:
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
new file mode 100644
index 0000000..2b3c6ad
--- /dev/null
+++ b/.github/workflows/test.yaml
@@ -0,0 +1,34 @@
+name: Test
+
+on:
+  workflow_call:
+  schedule:
+  # run at 7:00 on the first of every month
+  - cron: '0 7 1 * *'
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        python-version: [3.8, 3.9, "3.10", "3.11"]
+    steps:
+    - uses: actions/checkout@v3
+      with:
+        fetch-depth: 0
+
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v4
+      with:
+        python-version: ${{ matrix.python-version }}
+
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip
+        pip install -r requirements.txt
+        pip install pytest pytest-cov
+
+    - name: Test with pytest
+      run: |
+        pytest --cov=pinnwand