Release Pipeline #20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Pipeline | |
| on: | |
| workflow_dispatch: | |
| jobs: | |
| lint: | |
| name: Lint | |
| uses: ./.github/workflows/lint.yml | |
| secrets: inherit | |
| # ------------------------ | |
| # Release (manual, main only) | |
| # ------------------------ | |
| release: | |
| name: Release | |
| if: github.ref == 'refs/heads/main' | |
| needs: [lint] | |
| runs-on: ubuntu-latest | |
| environment: release | |
| concurrency: release | |
| outputs: | |
| release_version: ${{ steps.bump_version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.RELEASE_PAT }} | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Bump version | |
| id: bump_version | |
| run: | | |
| node scripts/updatePackageJson.js | |
| VERSION=$(node -e "const pkg=require('./package.json');console.log(pkg.version)") | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| - name: Configure git | |
| run: | | |
| git config user.name "kotahi release bot" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Create release branch | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | |
| run: | | |
| git checkout -b release/${{ steps.bump_version.outputs.version }} | |
| git add -A | |
| git commit -m "release version ${{ steps.bump_version.outputs.version }}" || echo "No changes to commit" | |
| git push origin release/${{ steps.bump_version.outputs.version }} | |
| # - name: Run Lint on release branch | |
| # uses: ./.github/workflows/lint.yml | |
| # secrets: inherit | |
| - name: Create PR | |
| if: success() | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | |
| run: | | |
| gh pr create \ | |
| --base main \ | |
| --head release/${{ steps.bump_version.outputs.version }} \ | |
| --title "Release ${{ steps.bump_version.outputs.version }}" \ | |
| --body "Automated release of version ${{ steps.bump_version.outputs.version }}" | |
| - name: Wait for Lint check | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | |
| run: | | |
| PR_NUMBER=$(gh pr list --head release/${{ steps.bump_version.outputs.version }} --json number -q '.[0].number') | |
| echo "Waiting for Lint to complete on PR #$PR_NUMBER" | |
| for i in {1..60}; do | |
| state=$(gh pr checks $PR_NUMBER --json name,state -q '.[] | select(.name=="Lint") | .state' 2>/dev/null || echo "") | |
| if [ -z "$state" ]; then | |
| echo "Lint not started yet, retrying in 10s... ($i/60)" | |
| elif [ "$state" == "SUCCESS" ]; then | |
| echo "Lint passed ✅" | |
| exit 0 | |
| elif [ "$state" == "FAILURE" ]; then | |
| echo "Lint failed ❌" | |
| exit 1 | |
| else | |
| echo "Lint status: $state (still running), retrying in 10s... ($i/60)" | |
| fi | |
| sleep 10 | |
| done | |
| echo "Timed out waiting for Lint check" | |
| exit 1 | |
| - name: Merge PR | |
| if: success() | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | |
| run: | | |
| PR_NUMBER=$(gh pr list --head release/${{ steps.bump_version.outputs.version }} --json number -q '.[0].number') | |
| gh pr merge $PR_NUMBER --merge --admin | |
| - name: Tag release | |
| if: success() | |
| env: | |
| GH_TOKEN: ${{ secrets.RELEASE_PAT }} | |
| run: | | |
| git fetch origin main | |
| git checkout main | |
| git pull origin main | |
| git tag -f ${{ steps.bump_version.outputs.version }} | |
| git push -f origin ${{ steps.bump_version.outputs.version }} | |
| # ------------------------ | |
| # Publish (DockerHub) | |
| # ------------------------ | |
| publish_client: | |
| name: Publish client | |
| if: github.ref == 'refs/heads/main' | |
| needs: [release] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Docker login | |
| run: echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin | |
| - name: Docker push client | |
| run: | | |
| cd packages/client | |
| docker build -t cokoapps/kotahi-client:${{ needs.release.outputs.release_version }} -f Dockerfile-production . | |
| docker push cokoapps/kotahi-client:${{ needs.release.outputs.release_version }} | |
| publish_server: | |
| name: Publish server | |
| if: github.ref == 'refs/heads/main' | |
| needs: [release] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Docker login | |
| run: echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin | |
| - name: Docker push server | |
| run: | | |
| cd packages/server | |
| docker build -t cokoapps/kotahi-server:${{ needs.release.outputs.release_version }} -f Dockerfile-production . | |
| docker push cokoapps/kotahi-server:${{ needs.release.outputs.release_version }} | |
| publish_docs: | |
| name: Publish docs | |
| if: github.ref == 'refs/heads/main' | |
| needs: [release] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Login | |
| run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | |
| - name: Docker push docs | |
| run: | | |
| cd packages/devdocs | |
| docker build -t ghcr.io/${{ github.repository }}/devdocs:${{ github.sha }} -f Dockerfile-production . | |
| docker push ghcr.io/${{ github.repository }}/devdocs:${{ github.sha }} | |
| deploy_docs: | |
| name: Deploy docs | |
| if: github.ref == 'refs/heads/main' | |
| needs: [publish_docs] | |
| runs-on: ubuntu-latest | |
| container: | |
| image: cokoapps/fly | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Deploy docs to fly | |
| run: fly deploy -c .fly/kotahi-dev-docs.toml --image ghcr.io/${{ github.repository }}/devdocs:${{ github.sha }} | |
| env: | |
| FLY_API_TOKEN: ${{ secrets.FLY_DEV_DOCS_TOKEN }} |