aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/.github/workflows/ci.yml
blob: 51fd8f0856c09cab1ce20a2c1c2ef4849e512609 (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
name: CI

on:
  push:
  pull_request:
  workflow_dispatch:

jobs:
  test_local:
    # Unpin when this is fixed:
    # https://github.com/actions/setup-python/issues/544
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        python-version: ['3.6', '3.7', '3.8', '3.9', '3.10']
    name: 'Test / ${{ matrix.python-version }}'
    env:
      # API request rate limit is easily exceeded otherwise:
      CGITIZE_GITHUB_TOKEN: '${{ secrets.CGITIZE_GITHUB_TOKEN }}'
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '${{ matrix.python-version }}'
          cache: pip
      - name: Initialize Git
        run: |
          git config --global user.name 'John Doe'
          git config --global user.email 'John.Doe@example.com'
      - name: Install dependencies
        run: pip install -q -e .
      - name: Integration test (local)
        run: ./test/integration/local/test.sh
      - name: Unit tests
        run: python -m unittest --buffer

  test_docker:
    runs-on: ubuntu-latest
    name: 'Test / Docker'
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Integration test (Docker)
        run: sudo ./test/integration/docker/test.sh

  test_example_config:
    needs: [test_local, test_docker]
    runs-on: ubuntu-latest
    name: 'Test / example config'
    env:
      # API request rate limit is easily exceeded otherwise:
      CGITIZE_GITHUB_TOKEN: '${{ secrets.CGITIZE_GITHUB_TOKEN }}'
      # Consider creating a separate user (without my private repositories)
      # for testing Bitbucket).
      #CGITIZE_BITBUCKET_USERNAME: egor-tensin
      #CGITIZE_BITBUCKET_TOKEN: '${{ secrets.CGITIZE_BITBUCKET_TOKEN }}'
      # Same goes for GitLab.
      #CGITIZE_GITLAB_USERNAME: egor-tensin
      #CGITIZE_GITLAB_TOKEN: '${{ secrets.CGITIZE_GITLAB_TOKEN}}'
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
          cache: pip
      - name: Install dependencies
        run: pip install -q -r requirements.txt
      - name: Set up ssh-agent
        uses: webfactory/ssh-agent@v0.7.0
        with:
          ssh-private-key: '${{ secrets.SSH_KEY }}'
      - name: Integration test (example config)
        run: ./test/integration/example/test.sh

  publish_docker:
    needs: [test_local, test_example_config, test_docker]
    runs-on: ubuntu-latest
    strategy:
      matrix:
        service: [backend, frontend]
        include:
          - {service: backend, file: docker/Dockerfile, image: cgitize}
          - {service: frontend, context: docker/frontend, image: cgitize-frontend}
    name: 'Publish / Docker Hub / ${{ matrix.service }}'
    if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      # https://github.com/docker/metadata-action#semver
      - id: meta
        name: Docker Hub metadata
        uses: docker/metadata-action@v4
        with:
          images: '${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image }}'
          flavor: |
            latest=auto
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=semver,pattern={{major}}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: '${{ secrets.DOCKERHUB_USERNAME }}'
          password: '${{ secrets.DOCKERHUB_TOKEN }}'
      - id: platforms
        name: Which platforms?
        # Building for ARM for every commit in master is too time-consuming.
        run: |
          if [ '${{ github.ref }}' = 'refs/heads/master' ]; then
              echo 'platforms=amd64' >> "$GITHUB_OUTPUT"
          else
              echo 'platforms=amd64,armhf,arm64' >> "$GITHUB_OUTPUT"
          fi
      - name: Build and publish
        uses: docker/build-push-action@v3
        with:
          context: '${{ matrix.context }}'
          file: '${{ matrix.file }}'
          labels: '${{ steps.meta.outputs.labels }}'
          platforms: '${{ steps.platforms.outputs.platforms }}'
          push: true
          tags: '${{ steps.meta.outputs.tags }}'

  publish_pypi:
    needs: [test_local, test_example_config, test_docker, publish_docker]
    runs-on: ubuntu-latest
    name: 'Publish / PyPI'
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      - name: Verify package can be installed
        run: pip install -q .
      - name: Install package builder
        run: pip install -q --upgrade build
      - name: Build package
        run: python -m build
      - name: Publish as artifact
        uses: actions/upload-artifact@v3
        with:
          name: dist
          path: dist
          if-no-files-found: error
      - name: Publish to PyPI
        if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          user: __token__
          password: '${{ secrets.PYPI_API_TOKEN }}'