aboutsummaryrefslogtreecommitdiffstats
path: root/.github/workflows/lint-test-deploy.yaml
blob: 754d2e495088a0ba325f994cce3d8a22afca4249 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
name: Lint, Test & Deploy

on:
  push:
    branches:
      - master
  # We use pull_request_target as we get PRs from
  # forks, but need to be able to add annotations
  # for our flake8 step.
  pull_request_target:


jobs:
  lint-test:
    runs-on: ubuntu-latest
    env:
      # Configure pip to cache dependencies and do a user install
      PIP_NO_CACHE_DIR: false
      PIP_USER: 1

      # Hide the graphical elements from pipenv's output
      PIPENV_HIDE_EMOJIS: 1
      PIPENV_NOSPIN: 1

      # Make sure pipenv does not try reuse an environment it's running in
      PIPENV_IGNORE_VIRTUALENVS: 1

      # Specify explicit paths for python dependencies and the pre-commit
      # environment so we know which directories to cache
      PYTHONUSERBASE: ${{ github.workspace }}/.cache/py-user-base
      PRE_COMMIT_HOME: ${{ github.workspace }}/.cache/pre-commit-cache

    steps:
      - name: Add custom PYTHONUSERBASE to PATH
        run: echo '${{ env.PYTHONUSERBASE }}/bin/' >> $GITHUB_PATH

      # We don't want to persist credentials, as our GitHub Action
      # may be run when a PR is made from a fork.
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          persist-credentials: false

      - name: Setup python
        id: python
        uses: actions/setup-python@v2
        with:
          python-version: '3.9'

      # This step caches our Python dependencies. To make sure we
      # only restore a cache when the dependencies, the python version,
      # the runner operating system, and the dependency location haven't
      # changed, we create a cache key that is a composite of those states.
      #
      # Only when the context is exactly the same, we will restore the cache.
      - name: Python Dependency Caching
        uses: actions/cache@v2
        id: python_cache
        with:
          path: ${{ env.PYTHONUSERBASE }}
          key: "python-0-${{ runner.os }}-${{ env.PYTHONUSERBASE }}-\
          ${{ steps.python.outputs.python-version }}-\
          ${{ hashFiles('./Pipfile', './Pipfile.lock') }}"

      # Install our dependencies if we did not restore a dependency cache
      - name: Install dependencies using pipenv
        if: steps.python_cache.outputs.cache-hit != 'true'
        run: |
          pip install pipenv
          pipenv install --dev --deploy --system

      # This step caches our pre-commit environment. To make sure we
      # do create a new environment when our pre-commit setup changes,
      # we create a cache key based on relevant factors.
      - name: Pre-commit Environment Caching
        uses: actions/cache@v2
        with:
          path: ${{ env.PRE_COMMIT_HOME }}
          key: "precommit-0-${{ runner.os }}-${{ env.PRE_COMMIT_HOME }}-\
          ${{ steps.python.outputs.python-version }}-\
          ${{ hashFiles('./.pre-commit-config.yaml') }}"

      # We will not run `flake8` here, as we will use a separate flake8
      # action. As pre-commit does not support user installs, we set
      # PIP_USER=0 to not do a user install.
      - name: Run pre-commit hooks
        run: export PIP_USER=0; SKIP=flake8 pre-commit run --all-files

      # This step requires `pull_request_target`, as adding annotations
      # requires "write" permissions to the repo.
      - name: Run flake8
        uses: julianwachholz/flake8-action@v1
        with:
          checkName: lint-test
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Run database using docker-compose
        run: docker-compose run -d -p 7777:5432 --name pydis_web postgres

      - name: Migrations and run tests with coverage.py
        run: |
          python manage.py makemigrations --check
          python manage.py migrate
          coverage run manage.py test --no-input
          coverage report -m
        env:
          CI: True
          DATABASE_URL: postgres://pysite:pysite@localhost:7777/pysite
          METRICITY_DB_URL: postgres://pysite:pysite@localhost:7777/metricity

      # This step will publish the coverage reports coveralls.io and
      # print a "job" link in the output of the GitHub Action
      - name: Publish coverage report to coveralls.io
        env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: coveralls

      - name: Tear down docker-compose containers
        run: docker-compose stop
        if: ${{ always() }}

  build-and-deploy:
    name: Build and Deploy to Kubernetes
    needs: lint-test
    if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/master'
    runs-on: ubuntu-latest

    steps:
      # Create a commit SHA-based tag for the container repositories
      - name: Create SHA Container Tag
        id: sha_tag
        run: |
          tag=$(cut -c 1-7 <<< $GITHUB_SHA)
          echo "::set-output name=tag::$tag"
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Login to Github Container Registry
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ secrets.GHCR_USER }}
          password: ${{ secrets.GHCR_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          file: ./Dockerfile
          push: true
          cache-from: type=registry,ref=ghcr.io/python-discord/site:latest
          tags: |
            ghcr.io/python-discord/site:latest
            ghcr.io/python-discord/site:${{ steps.sha_tag.outputs.tag }}

      - name: Authenticate with Kubernetes
        uses: azure/k8s-set-context@v1
        with:
          method: kubeconfig
          kubeconfig: ${{ secrets.KUBECONFIG }}

      - name: Deploy to Kubernetes
        uses: Azure/k8s-deploy@v1
        with:
          manifests: |
              deployment.yaml
          images: 'ghcr.io/python-discord/site:${{ steps.sha_tag.outputs.tag }}'
          kubectl-version: 'latest'