|  | 
|  | 1 | +name: wipac ci/cd | 
|  | 2 | + | 
|  | 3 | +on: | 
|  | 4 | +  push: | 
|  | 5 | +    branches: | 
|  | 6 | +      - '**' | 
|  | 7 | +    tags-ignore: | 
|  | 8 | +      - '**' | 
|  | 9 | + | 
|  | 10 | +env: | 
|  | 11 | +  py_version: '3.13' | 
|  | 12 | +  REGISTRY_IMAGE: ghcr.io/wipacrepo/scitoken-issuer | 
|  | 13 | + | 
|  | 14 | +jobs: | 
|  | 15 | + | 
|  | 16 | +  flake8: | 
|  | 17 | +    runs-on: ubuntu-latest | 
|  | 18 | +    steps: | 
|  | 19 | +      - uses: actions/checkout@v4 | 
|  | 20 | +        with: | 
|  | 21 | +          ref: ${{ github.sha }}  # lock to triggered commit (github.ref is dynamic) | 
|  | 22 | +      - uses: astral-sh/ruff-action@v3 | 
|  | 23 | + | 
|  | 24 | +  py-versions: | 
|  | 25 | +    runs-on: ubuntu-latest | 
|  | 26 | +    outputs: | 
|  | 27 | +      matrix: ${{ steps.versions.outputs.matrix }} | 
|  | 28 | +    steps: | 
|  | 29 | +      - uses: actions/checkout@v4 | 
|  | 30 | +        with: | 
|  | 31 | +          ref: ${{ github.sha }}  # lock to triggered commit (github.ref is dynamic) | 
|  | 32 | +      - id: versions | 
|  | 33 | +        uses: WIPACrepo/wipac-dev-py-versions-action@v2.5 | 
|  | 34 | + | 
|  | 35 | +  mypy: | 
|  | 36 | +    needs: [ py-versions ] | 
|  | 37 | +    runs-on: ubuntu-latest | 
|  | 38 | +    strategy: | 
|  | 39 | +      max-parallel: 4 | 
|  | 40 | +      fail-fast: false | 
|  | 41 | +      matrix: | 
|  | 42 | +        py3: ${{ fromJSON(needs.py-versions.outputs.matrix) }} | 
|  | 43 | +    steps: | 
|  | 44 | +      - uses: actions/checkout@v4 | 
|  | 45 | +        with: | 
|  | 46 | +          ref: ${{ github.sha }}  # lock to triggered commit (github.ref is dynamic) | 
|  | 47 | +      - uses: actions/setup-python@v5 | 
|  | 48 | +        with: | 
|  | 49 | +          python-version: ${{ matrix.py3 }} | 
|  | 50 | +      - uses: WIPACrepo/wipac-dev-mypy-action@v2.0 | 
|  | 51 | + | 
|  | 52 | +  tests: | 
|  | 53 | +    needs: [py-versions] | 
|  | 54 | +    runs-on: ubuntu-latest | 
|  | 55 | +    strategy: | 
|  | 56 | +      max-parallel: 4 | 
|  | 57 | +      fail-fast: false | 
|  | 58 | +      matrix: | 
|  | 59 | +        version: ${{ fromJSON(needs.py-versions.outputs.matrix) }} | 
|  | 60 | +    services: | 
|  | 61 | +      keycloak: | 
|  | 62 | +        image: ghcr.io/wipacrepo/keycloak-rest-services:test-keycloak-master | 
|  | 63 | +        env: | 
|  | 64 | +          KEYCLOAK_ADMIN: admin | 
|  | 65 | +          KEYCLOAK_ADMIN_PASSWORD: admin | 
|  | 66 | +          CMD: start-dev | 
|  | 67 | +        ports: | 
|  | 68 | +        - 8080:8080 | 
|  | 69 | +      mongo: | 
|  | 70 | +        image: mongo:8 | 
|  | 71 | +        ports: | 
|  | 72 | +        - 27017:27017 | 
|  | 73 | +    env: | 
|  | 74 | +      CI_TESTING: "true" | 
|  | 75 | +      IDP_ADDRESS: http://localhost:8080 | 
|  | 76 | +      USERNAME: admin | 
|  | 77 | +      PASSWORD: admin | 
|  | 78 | +    steps: | 
|  | 79 | +      - uses: actions/checkout@v4 | 
|  | 80 | +        with: | 
|  | 81 | +          ref: ${{ github.sha }}  # lock to triggered commit (github.ref is dynamic) | 
|  | 82 | +      - uses: actions/setup-python@v5 | 
|  | 83 | +        with: | 
|  | 84 | +          python-version: ${{ matrix.version }} | 
|  | 85 | +      - run: | | 
|  | 86 | +          pip install --upgrade pip wheel setuptools | 
|  | 87 | +          pip install -e .[tests] | 
|  | 88 | +          pytest -v --log-level debug --tb=short | 
|  | 89 | +
 | 
|  | 90 | +  docker-build: | 
|  | 91 | +    name: "Docker Image" | 
|  | 92 | +    runs-on: ubuntu-latest | 
|  | 93 | +    steps: | 
|  | 94 | +      # Note: we need to checkout the repository at the workflow sha in case during the workflow | 
|  | 95 | +      # the branch was updated. To keep PSR working with the configured release branches, | 
|  | 96 | +      # we force a checkout of the desired release branch but at the workflow sha HEAD. | 
|  | 97 | +      - name: Setup | Checkout Repository at workflow sha | 
|  | 98 | +        uses: actions/checkout@v4 | 
|  | 99 | +        with: | 
|  | 100 | +          fetch-depth: 0 | 
|  | 101 | +          ref: ${{ github.sha }} | 
|  | 102 | +      - name: Build Docker Image | 
|  | 103 | +        uses: docker/build-push-action@v4 | 
|  | 104 | +        with: | 
|  | 105 | +          context: . | 
|  | 106 | +          push: false | 
|  | 107 | + | 
|  | 108 | +  release: | 
|  | 109 | +    if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' }} | 
|  | 110 | +    needs: [flake8, tests, docker-build] | 
|  | 111 | +    runs-on: ubuntu-latest | 
|  | 112 | +    concurrency: release | 
|  | 113 | + | 
|  | 114 | +    permissions: | 
|  | 115 | +      id-token: write | 
|  | 116 | +      contents: write | 
|  | 117 | + | 
|  | 118 | +    outputs: | 
|  | 119 | +      released: ${{ steps.release.outputs.released }} | 
|  | 120 | +      tag: ${{ steps.release.outputs.tag }} | 
|  | 121 | + | 
|  | 122 | +    steps: | 
|  | 123 | +      # Note: we need to checkout the repository at the workflow sha in case during the workflow | 
|  | 124 | +      # the branch was updated. To keep PSR working with the configured release branches, | 
|  | 125 | +      # we force a checkout of the desired release branch but at the workflow sha HEAD. | 
|  | 126 | +      - name: Setup | Checkout Repository at workflow sha | 
|  | 127 | +        uses: actions/checkout@v4 | 
|  | 128 | +        with: | 
|  | 129 | +          fetch-depth: 0 | 
|  | 130 | +          ref: ${{ github.sha }} | 
|  | 131 | + | 
|  | 132 | +      - name: Setup | Force correct release branch on workflow sha | 
|  | 133 | +        run: | | 
|  | 134 | +          git checkout -B ${{ github.ref_name }} ${{ github.sha }} | 
|  | 135 | +
 | 
|  | 136 | +      - name: Action | Semantic Version Release | 
|  | 137 | +        id: release | 
|  | 138 | +        # Adjust tag with desired version if applicable. | 
|  | 139 | +        uses: python-semantic-release/python-semantic-release@v9.8.1 | 
|  | 140 | +        with: | 
|  | 141 | +          github_token: ${{ secrets.GITHUB_TOKEN }} | 
|  | 142 | +          git_committer_name: "github-actions" | 
|  | 143 | +          git_committer_email: "actions@users.noreply.github.com" | 
|  | 144 | + | 
|  | 145 | +      - name: Publish | Upload to GitHub Release Assets | 
|  | 146 | +        uses: python-semantic-release/publish-action@v9.16.1 | 
|  | 147 | +        if: steps.release.outputs.released == 'true' | 
|  | 148 | +        with: | 
|  | 149 | +          github_token: ${{ secrets.GITHUB_TOKEN }} | 
|  | 150 | +          tag: ${{ steps.release.outputs.tag }} | 
|  | 151 | + | 
|  | 152 | +  docker_release: | 
|  | 153 | +    if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' && needs.release.outputs.released == 'true' }} | 
|  | 154 | +    needs: [release] | 
|  | 155 | +    runs-on: ubuntu-latest | 
|  | 156 | +    strategy: | 
|  | 157 | +      fail-fast: false | 
|  | 158 | +      matrix: | 
|  | 159 | +        platform: | 
|  | 160 | +          - linux/amd64 | 
|  | 161 | +          - linux/arm64 | 
|  | 162 | + | 
|  | 163 | +    permissions: | 
|  | 164 | +      packages: write | 
|  | 165 | + | 
|  | 166 | +    steps: | 
|  | 167 | +      # Note: we checkout the just created tag here | 
|  | 168 | +      - name: Setup | Checkout Repository at tag | 
|  | 169 | +        uses: actions/checkout@v4 | 
|  | 170 | +        with: | 
|  | 171 | +          fetch-depth: 0 | 
|  | 172 | +          ref: ${{ needs.release.outputs.tag }} | 
|  | 173 | + | 
|  | 174 | +      - name: Prepare | 
|  | 175 | +        run: | | 
|  | 176 | +          platform=${{ matrix.platform }} | 
|  | 177 | +          echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV | 
|  | 178 | +
 | 
|  | 179 | +      - name: Docker meta | 
|  | 180 | +        id: docker_meta | 
|  | 181 | +        uses: docker/metadata-action@v5 | 
|  | 182 | +        with: | 
|  | 183 | +          images: ${{ env.REGISTRY_IMAGE }} | 
|  | 184 | + | 
|  | 185 | +      - name: Login to GitHub Container Registry | 
|  | 186 | +        uses: docker/login-action@v3 | 
|  | 187 | +        with: | 
|  | 188 | +          registry: ghcr.io | 
|  | 189 | +          username: ${{ github.actor }} | 
|  | 190 | +          password: ${{ secrets.GITHUB_TOKEN }} | 
|  | 191 | + | 
|  | 192 | +      - name: Set up Docker Buildx | 
|  | 193 | +        uses: docker/setup-buildx-action@v3 | 
|  | 194 | + | 
|  | 195 | +      - name: Push Docker Image | 
|  | 196 | +        id: build | 
|  | 197 | +        uses: docker/build-push-action@v6 | 
|  | 198 | +        with: | 
|  | 199 | +          context: . | 
|  | 200 | +          platforms: ${{ matrix.platform }} | 
|  | 201 | +          build-args: | | 
|  | 202 | +            SETUPTOOLS_SCM_PRETEND_VERSION=${{ needs.release.outputs.tag }} | 
|  | 203 | +          tags: ${{ env.REGISTRY_IMAGE }} | 
|  | 204 | +          labels: ${{ steps.docker_meta.outputs.labels }} | 
|  | 205 | +          outputs: type=image,push-by-digest=true,name-canonical=true,push=true | 
|  | 206 | + | 
|  | 207 | +      - name: Export digest | 
|  | 208 | +        run: | | 
|  | 209 | +          mkdir -p ${{ runner.temp }}/digests | 
|  | 210 | +          digest="${{ steps.build.outputs.digest }}" | 
|  | 211 | +          touch "${{ runner.temp }}/digests/${digest#sha256:}" | 
|  | 212 | +
 | 
|  | 213 | +      - name: Upload digest | 
|  | 214 | +        uses: actions/upload-artifact@v4 | 
|  | 215 | +        with: | 
|  | 216 | +          name: digests-${{ env.PLATFORM_PAIR }} | 
|  | 217 | +          path: ${{ runner.temp }}/digests/* | 
|  | 218 | +          if-no-files-found: error | 
|  | 219 | +          retention-days: 1 | 
|  | 220 | + | 
|  | 221 | +  docker_merge: | 
|  | 222 | +    if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' && needs.release.outputs.released == 'true' }} | 
|  | 223 | +    needs: [release, docker_release] | 
|  | 224 | +    runs-on: ubuntu-latest | 
|  | 225 | + | 
|  | 226 | +    permissions: | 
|  | 227 | +      packages: write | 
|  | 228 | + | 
|  | 229 | +    steps: | 
|  | 230 | +      - name: Download digests | 
|  | 231 | +        uses: actions/download-artifact@v4 | 
|  | 232 | +        with: | 
|  | 233 | +          path: ${{ runner.temp }}/digests | 
|  | 234 | +          pattern: digests-* | 
|  | 235 | +          merge-multiple: true | 
|  | 236 | + | 
|  | 237 | +      - name: Login to Docker Hub | 
|  | 238 | +        uses: docker/login-action@v3 | 
|  | 239 | +        with: | 
|  | 240 | +          registry: ghcr.io | 
|  | 241 | +          username: ${{ github.actor }} | 
|  | 242 | +          password: ${{ secrets.GITHUB_TOKEN }} | 
|  | 243 | + | 
|  | 244 | +      - name: Set up Docker Buildx | 
|  | 245 | +        uses: docker/setup-buildx-action@v3 | 
|  | 246 | + | 
|  | 247 | +      - name: Docker meta | 
|  | 248 | +        id: docker_meta | 
|  | 249 | +        uses: docker/metadata-action@v5 | 
|  | 250 | +        with: | 
|  | 251 | +          images: | | 
|  | 252 | +            ${{ env.REGISTRY_IMAGE }} | 
|  | 253 | +          tags: | | 
|  | 254 | +            type=semver,pattern={{major}},value=${{ needs.release.outputs.tag }} | 
|  | 255 | +            type=semver,pattern={{major}}.{{minor}},value=${{ needs.release.outputs.tag }} | 
|  | 256 | +            type=semver,pattern={{major}}.{{minor}}.{{patch}},value=${{ needs.release.outputs.tag }} | 
|  | 257 | +
 | 
|  | 258 | +      - name: Create manifest list and push | 
|  | 259 | +        working-directory: ${{ runner.temp }}/digests | 
|  | 260 | +        run: | | 
|  | 261 | +          docker buildx imagetools create \ | 
|  | 262 | +            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -cr '.tags | map("-t " + .) | join(" ")') \ | 
|  | 263 | +            $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) | 
|  | 264 | +#            $(echo $DOCKER_METADATA_OUTPUT_JSON | jq -r '.annotations | map("--annotation \"" + . + "\"") | join(" ")') | 
0 commit comments