diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cbedb44..fa904ff 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,368 +1,128 @@ -name: Build and Release Container +name: Release on: push: - paths: - - '.github/workflows/release.yaml' - - 'plugins/**' - - 'containers/**' - - 'charts/**' branches: - - 'main' - -env: - HARBOR_REGISTRY: ${{ vars.HARBOR_REGISTRY }} - HARBOR_PROJECT: ${{ vars.HARBOR_PROJECT }} - HARBOR_REPO: ${{ vars.HARBOR_REPO }} - HARBOR_USER: ${{ vars.HARBOR_USER }} - HARBOR_TOKEN: ${{ secrets.HARBOR_TOKEN }} + - main jobs: - release-jupyter-container: - runs-on: [self-hosted, linux, x64] - - env: - TAG_PREFIX: 'DARE-Jupyter-Container' - TAG_FORMAT: 'DARE-Jupyter-Container-${version}' - HARBOR_JUPYTER_REPO: ${{ vars.HARBOR_REPO }} - - steps: - - name: clone repo - uses: actions/checkout@v3 - - - uses: dorny/paths-filter@v2 - id: container-changes - with: - filters: | - src: - - '.github/workflows/release.yaml' - - 'containers/jupyterlab/**' - - 'plugins/**' - - # build pip wheels - - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: build cloudbeaver proxy wheel - run: | - python -m pip install --user --upgrade build - python -m build --outdir ./dist ./containers/custom-packages/jupyter-cloudbeaver-proxy - - - name: build rstudio server proxy wheel - run: | - python -m pip install --user --upgrade build - python -m build --outdir ./dist ./containers/custom-packages/jupyter-rsession-proxy - - - name: build container - if: steps.container-changes.outputs.src == 'true' - run: | - docker build -t image -f "containers/jupyterlab/standard.Dockerfile" . - - - name: registry login - if: steps.container-changes.outputs.src == 'true' - run: | - echo "$HARBOR_TOKEN" | docker login $HARBOR_REGISTRY -u $HARBOR_USER --password-stdin - - - name: generate token - if: steps.container-changes.outputs.src == 'true' - id: generate-token - uses: tibdex/github-app-token@v1.8.0 - with: - app_id: ${{ vars.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} - - - name: semantic release dry run - if: steps.container-changes.outputs.src == 'true' - uses: docker://ghcr.io/codfish/semantic-release-action:v2 - id: semantic-dry - with: - dry_run: true - - branches: | - [ - '+([0-9])?(.{+([0-9]),x}).x', - 'main' - ] - - tag_format: ${{ env.TAG_FORMAT }} - - plugins: |- - [ - ['@semantic-release/commit-analyzer', { - "releaseRules": [ - {"type": "major", "release": "major"}, - {"type": "minor", "release": "minor"}, - {"type": "patch", "release": "patch"}, - {"type": "no-release", "release": false}, - - {"type": "chore", "release": "patch"}, - {"type": "refactor", "release": "patch"}, - {"type": "style", "release": "patch"}, - - {"type": "docs", "release": false}, - {"type": "test", "release": false}, - {"type": "ci", "release": false}, - - {"type": "feat", "release": "minor"}, - - {"type": "revert", "release": "patch"}, - {"type": "perf", "release": "patch"}, - {"type": "fix", "release": "patch"}, - {"type": "build", "release": "patch"}, - ], - }] - ] - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - - - name: semantic release - if: steps.container-changes.outputs.src == 'true' && steps.semantic-dry.outputs.new-release-published == 'true' - uses: docker://ghcr.io/codfish/semantic-release-action:v2 - id: semantic - with: - branches: | - [ - '+([0-9])?(.{+([0-9]),x}).x', - 'main' - ] - - tag_format: ${{ env.TAG_FORMAT }} - - additional_packages: | - ['@semantic-release/exec'] - - plugins: |- - [ - ['@semantic-release/commit-analyzer', { - "releaseRules": [ - {"type": "major", "release": "major"}, - {"type": "minor", "release": "minor"}, - {"type": "patch", "release": "patch"}, - {"type": "no-release", "release": false}, - - {"type": "chore", "release": "patch"}, - {"type": "refactor", "release": "patch"}, - {"type": "style", "release": "patch"}, - - {"type": "docs", "release": false}, - {"type": "test", "release": false}, - {"type": "ci", "release": false}, - - {"type": "feat", "release": "minor"}, - - {"type": "revert", "release": "patch"}, - {"type": "perf", "release": "patch"}, - {"type": "fix", "release": "patch"}, - {"type": "build", "release": "patch"}, - ], - }], - ['@semantic-release/exec', { - "generateNotesCmd": "echo '${ process.env.RELEASE_NOTES }'" - }], - '@semantic-release/release-notes-generator', - ['@semantic-release/github', { - "successComment": false, - "failTitle": false - }] - ] - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - RELEASE_NOTES: | - ``` - echo "" | docker login ${{ env.HARBOR_REGISTRY }} -u --password-stdin - docker pull ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.HARBOR_JUPYTER_REPO }}:${{ steps.semantic-dry.outputs.release-version }} - ``` - - - name: container push to registry - id: container-push - if: steps.container-changes.outputs.src == 'true' && steps.semantic.outputs.new-release-published == 'true' - run: | - docker tag image $HARBOR_REGISTRY/$HARBOR_PROJECT/$HARBOR_JUPYTER_REPO:$TAG - docker push $HARBOR_REGISTRY/$HARBOR_PROJECT/$HARBOR_JUPYTER_REPO:$TAG - env: - TAG: ${{ steps.semantic.outputs.release-version }} - - - name: delete orphaned release on container push failure - uses: dev-drprasad/delete-tag-and-release@v0.2.1 - if: (failure() && steps.container-push.outcome == 'failure') && steps.semantic.outputs.new-release-published == 'true' - with: - tag_name: ${ env.TAG_PREFIX }-${{ steps.semantic.outputs.release-version }} - delete_release: true - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - - release-chart: - needs: release-jupyter-container - runs-on: [ self-hosted, linux, x64 ] - - env: - TAG_PREFIX: 'DARE-Jupyter-Helm' - TAG_FORMAT: 'DARE-Jupyter-Helm-${version}' - - steps: - - name: clone repo - uses: actions/checkout@v3 - - - uses: dorny/paths-filter@v2 - id: chart-changes - with: - filters: | - src: - - '.github/workflows/release.yaml' - - 'charts/**' - - - name: generate token - if: steps.chart-changes.outputs.src == 'true' - id: generate-token - uses: tibdex/github-app-token@v1.8.0 - with: - app_id: ${{ vars.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} - - - name: install helm - if: steps.chart-changes.outputs.src == 'true' - uses: azure/setup-helm@v3 - with: - version: 'latest' - token: ${{ steps.generate-token.outputs.token }} - - - name: semantic release dry run - if: steps.chart-changes.outputs.src == 'true' - uses: docker://ghcr.io/codfish/semantic-release-action:v2 - id: semantic-dry - with: - dry_run: true - - branches: | - [ - '+([0-9])?(.{+([0-9]),x}).x', - 'main' - ] - - tag_format: ${{ env.TAG_FORMAT }} - - plugins: |- - [ - ['@semantic-release/commit-analyzer', { - "releaseRules": [ - {"type": "major", "release": "major"}, - {"type": "minor", "release": "minor"}, - {"type": "patch", "release": "patch"}, - {"type": "no-release", "release": false}, - - {"type": "chore", "release": "patch"}, - {"type": "refactor", "release": "patch"}, - {"type": "style", "release": "patch"}, - - {"type": "docs", "release": false}, - {"type": "test", "release": false}, - {"type": "ci", "release": false}, - - {"type": "feat", "release": "minor"}, - - {"type": "revert", "release": "patch"}, - {"type": "perf", "release": "patch"}, - {"type": "fix", "release": "patch"}, - {"type": "build", "release": "patch"}, - ], - }] - ] - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - - - name: helm package - if: steps.chart-changes.outputs.src == 'true' && steps.semantic-dry.outputs.new-release-published == 'true' - run: | - set -x - helm package ./charts/$HARBOR_REPO -d . --version $TAG --app-version $TAG - tar -xzf $(echo *.tgz) -C ./charts $HARBOR_REPO/Chart.yaml - env: - TAG: ${{ steps.semantic-dry.outputs.release-version }} - - - name: semantic release - if: steps.chart-changes.outputs.src == 'true' && steps.semantic-dry.outputs.new-release-published == 'true' - uses: docker://ghcr.io/codfish/semantic-release-action:v2 - id: semantic - with: - branches: | - [ - '+([0-9])?(.{+([0-9]),x}).x', - 'main' - ] - - tag_format: ${{ env.TAG_FORMAT }} - - additional_packages: | - ['@semantic-release/exec', '@semantic-release/git'] - - plugins: |- - [ - ['@semantic-release/commit-analyzer', { - "releaseRules": [ - {"type": "major", "release": "major"}, - {"type": "minor", "release": "minor"}, - {"type": "patch", "release": "patch"}, - {"type": "no-release", "release": false}, - - {"type": "chore", "release": "patch"}, - {"type": "refactor", "release": "patch"}, - {"type": "style", "release": "patch"}, - - {"type": "docs", "release": false}, - {"type": "test", "release": false}, - {"type": "ci", "release": false}, - - {"type": "feat", "release": "minor"}, - - {"type": "revert", "release": "patch"}, - {"type": "perf", "release": "patch"}, - {"type": "fix", "release": "patch"}, - {"type": "build", "release": "patch"}, - ], - }], - ['@semantic-release/exec', { - "generateNotesCmd": "echo '${ process.env.RELEASE_NOTES }'" - }], - '@semantic-release/release-notes-generator', - ['@semantic-release/git', { - "assets": ["./charts/**"], - "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" - }], - ['@semantic-release/github', { - "successComment": false, - "failTitle": false - }] - ] - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - RELEASE_NOTES: | - ``` - helm repo add --pass-credentials --username --password https://${{ env.HARBOR_REGISTRY }}/chartrepo/${{ env.HARBOR_PROJECT }} - helm pull --version ${{ steps.semantic-dry.outputs.release-version }} /${{ env.HARBOR_REPO }} - ls *.tgz - # ${{ env.HARBOR_REPO }}-${{ steps.semantic-dry.outputs.release-version }}.tgz - ``` - - - name: helm push to registry - id: chart-push - if: steps.chart-changes.outputs.src == 'true' && steps.semantic.outputs.new-release-published == 'true' - run: | - set -x - helm plugin install https://github.com/chartmuseum/helm-push - helm repo add --pass-credentials --username "$HARBOR_USER" --password "$HARBOR_TOKEN" harbor https://$HARBOR_REGISTRY/chartrepo/$HARBOR_PROJECT - helm cm-push $(echo *.tgz) harbor - sleep 2 - helm repo update - helm pull harbor/$HARBOR_REPO --version $TAG - env: - TAG: ${{ steps.semantic.outputs.release-version }} - - name: delete orphaned release on chart push failure - uses: dev-drprasad/delete-tag-and-release@v0.2.1 - if: (failure() && steps.chart-push.outcome == 'failure') && steps.semantic.outputs.new-release-published == 'true' - with: - tag_name: ${ env.TAG_PREFIX }-${{ steps.semantic.outputs.release-version }} - delete_release: true - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + ###################################################################################################################### + # Pre-Tasks + ###################################################################################################################### + + slack: + # Open a new PR thread on Slack for this CI run + uses: SwanseaUniversityMedical/workflows/.github/workflows/slack-release-thread.yaml@v2.1.0 + with: + slack-channel: ${{ vars.SLACK_CHANNEL }} + secrets: + slack-token: ${{ secrets.SLACK_TOKEN }} + + changes: + # Detect which files have been changed on this PR's full history + needs: slack + uses: SwanseaUniversityMedical/workflows/.github/workflows/changes.yaml@v2.1.0 + with: + slack-channel: ${{ vars.SLACK_CHANNEL }} + slack-thread: ${{ needs.slack.outputs.thread }} + github-app-id: ${{ vars.APP_ID }} + filters: | + jupyter-container: + - './.github/workflows/release.yaml' + - 'containers/jupyterlab/**' + - 'plugins/**' + chart: + - './.github/workflows/release.yaml' + - 'charts/**' + + secrets: + slack-token: ${{ secrets.SLACK_TOKEN }} + github-app-private-key: ${{ secrets.APP_PRIVATE_KEY }} + + ###################################################################################################################### + # Container Tasks + ###################################################################################################################### + + jupyter-container: + # Build the DARE Jupyter container and push it as :rc-1.0.0 + needs: + - slack + - changes + if: fromJSON(needs.changes.outputs.changes).jupyter-container == 'true' + uses: SwanseaUniversityMedical/workflows/.github/workflows/on-release-container.yaml@v2.1.0 + with: + job-name: jupyter-container + container-registry: ${{ vars.HARBOR_REGISTRY }} + github-app-id: ${{ vars.APP_ID }} + container-registry-user: ${{ vars.HARBOR_USER }} + container-registry-project: ${{ vars.HARBOR_PROJECT }} + container-registry-repo: ${{ vars.HARBOR_REPO }} + release-tag-format: 'DARE-Jupyter-Container-${version}' + slack-channel: ${{ vars.SLACK_CHANNEL }} + slack-thread: ${{ needs.slack.outputs.thread }} + build-command: | + sudo apt update && + sudo apt install python3.8-venv && + python -m pip install --user --upgrade build && + python -m build --outdir ./dist ./containers/custom-packages/jupyter-cloudbeaver-proxy && + python -m build --outdir ./dist ./containers/custom-packages/jupyter-rsession-proxy && + docker build -t $IMAGE -f containers/jupyterlab/standard.Dockerfile . + test-command: | + echo '0' + secrets: + container-registry-token: ${{ secrets.HARBOR_TOKEN }} + slack-token: ${{ secrets.SLACK_TOKEN }} + github-app-private-key: ${{ secrets.APP_PRIVATE_KEY }} + + + ###################################################################################################################### + # Chart Tasks + ###################################################################################################################### + + chart: + # Build the chart and push it as x.y.z-rc + needs: + - slack + - changes + if: fromJSON(needs.changes.outputs.changes).chart == 'true' + uses: SwanseaUniversityMedical/workflows/.github/workflows/on-release-chart.yaml@v2.1.0 + with: + job-name: chart + chart-registry: ${{ vars.HARBOR_REGISTRY }} + chart-registry-user: ${{ vars.HARBOR_USER }} + chart-registry-project: ${{ vars.HARBOR_PROJECT }} + chart-registry-repo: ${{ vars.HARBOR_REPO }} + release-tag-format: 'DARE-Jupyter-Helm-${version}' + github-app-id: ${{ vars.APP_ID }} + slack-channel: ${{ vars.SLACK_CHANNEL }} + slack-thread: ${{ needs.slack.outputs.thread }} + chart: charts/** + test-command: | + helm template $CHART --values charts/jupyter/values.yaml + secrets: + chart-registry-token: ${{ secrets.HARBOR_TOKEN }} + github-app-private-key: ${{ secrets.APP_PRIVATE_KEY }} + slack-token: ${{ secrets.SLACK_TOKEN }} + + ###################################################################################################################### + # Post-Tasks + ###################################################################################################################### + + slack-update: + # Update the original Slack message with the final workflow status + # WARNING! ALL UPSTREAM JOBS MUST BE DECLARED HERE TO REPORT FAILURES CORRECTLY! + needs: + - slack + - changes + - jupyter-container + - chart + + uses: SwanseaUniversityMedical/workflows/.github/workflows/slack-release-thread.yaml@v2.1.0 + if: always() + with: + slack-channel: ${{ vars.SLACK_CHANNEL }} + slack-thread: ${{ needs.slack.outputs.thread }} + status: ${{ contains(join(needs.*.result, ','), 'failure') && ':no_entry:' || ':white_check_mark:' }} + secrets: + slack-token: ${{ secrets.SLACK_TOKEN }} \ No newline at end of file