diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..36cf7a6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,172 @@ +name: ci + +# Run this workflow every time a new commit pushed to your repository +on: + push: + branches: + - main + tags: + - '*' + pull_request: + workflow_dispatch: + +env: + IMAGE_NAME: maykinmedia/referentielijsten + DJANGO_SETTINGS_MODULE: referentielijsten.conf.jenkins + DB_PASSWORD: '' + DB_USER: postgres + +jobs: + # determine changed files to decide if certain jobs can be skipped or not + changed-files: + runs-on: ubuntu-latest # windows-latest | macos-latest + name: Determine changed files + steps: + + - uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Get changed PY files + id: changed-py-files + uses: tj-actions/changed-files@v41 + with: + files: | + ^src/.+\.py + - name: Get changed JS files + id: changed-js-files + uses: tj-actions/changed-files@v41 + with: + files: | + ^src/.+\.js + - name: Get changed requirements files + id: changed-requirements + uses: tj-actions/changed-files@v41 + with: + files: ^backend/requirements/.+\.txt$ + + outputs: + changed-py-files: ${{ steps.changed-py-files.outputs.any_changed }} + changed-js-files: ${{ steps.changed-js-files.outputs.any_changed }} + changed-requirements: ${{ steps.changed-requirements.outputs.any_changed }} + + tests: + runs-on: ubuntu-latest + needs: + - changed-files + + # only run tests if source files have changed (e.g. skip for PRs that only update docs) + if: ${{ needs.changed-files.outputs.changed-py-files == 'true'|| needs.changed-files.outputs.changed-requirements == 'true'|| github.event_name == 'push' }} + + strategy: + matrix: + postgres: ['15', '16'] + + name: Tests (PG ${{ matrix.postgres }}) + + services: + postgres: + image: postgres:${{ matrix.postgres }} + env: + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - 5432:5432 + # Needed because the postgres container does not provide a healthcheck + options: + --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + steps: + - uses: actions/checkout@v4 + - name: Set up backend environment + uses: maykinmedia/setup-django-backend@v1 + with: + python-version: '3.11' + setup-node: 'yes' + npm-ci-flags: '--legacy-peer-deps' + - name: Run tests + run: | + python src/manage.py collectstatic --noinput --link + coverage run src/manage.py test src + env: + DJANGO_SETTINGS_MODULE: referentielijsten.conf.jenkins + SECRET_KEY: dummy + DB_USER: postgres + DB_PASSWORD: '' + + - name: Publish coverage report + uses: codecov/codecov-action@v1 + + docker: + needs: tests + name: Docker image build + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Determine tag/commit hash + id: vars + run: | + # Strip git ref prefix from version + VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + # Strip "v" prefix from tag name (if present at all) + [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') + # Use Docker `latest` tag convention + [ "$VERSION" == "master" ] && VERSION=latest + echo "tag=${VERSION}" >> $GITHUB_OUTPUT + echo "git_hash=${GITHUB_SHA}" >> $GITHUB_OUTPUT + - name: Build the Docker image + run: | + docker build . \ + --tag $IMAGE_NAME:$RELEASE_VERSION \ + --build-arg COMMIT_HASH=${{ steps.vars.outputs.git_hash }} \ + --build-arg RELEASE=${{ steps.vars.outputs.tag }} \ + env: + RELEASE_VERSION: ${{ steps.vars.outputs.tag }} + + - run: docker image save -o image.tar $IMAGE_NAME:${{ steps.vars.outputs.tag }} + - name: Store image artifact + uses: actions/upload-artifact@v3 + with: + name: docker-image + path: image.tar + retention-days: 1 + + publish: + needs: + - tests + - docker + + name: Push Docker image + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.repository_owner == 'referentielijsten' # exclude PRs/forks + + steps: + - uses: actions/checkout@v4 + - name: Download built image + uses: actions/download-artifact@v3 + with: + name: docker-image + + - name: Determine tag/commit hash + id: vars + run: | + # Strip git ref prefix from version + VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + + # Strip "v" prefix from tag name (if present at all) + [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') + + # Use Docker `latest` tag convention + [ "$VERSION" == "main" ] && VERSION=latest + + echo "tag=${VERSION}" >> $GITHUB_OUTPUT + + - name: Load image + run: | + docker image load -i image.tar + + - name: Log into registry + run: echo "${{ secrets.DOCKER_TOKEN }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin + + - name: Push the Docker image + run: docker push $IMAGE_NAME:${{ steps.vars.outputs.tag }}