diff --git a/.github/actions/build-test-and-deploy/cloud-platform-deploy/action.yml b/.github/actions/build-test-and-deploy/cloud-platform-deploy/action.yml new file mode 100644 index 0000000..cfed494 --- /dev/null +++ b/.github/actions/build-test-and-deploy/cloud-platform-deploy/action.yml @@ -0,0 +1,141 @@ +name: Cloud Platform Deploy +description: Deploy to Cloud Platform using Helm + +inputs: + environment: + description: The environment to deploy to (dev/preprod/prod) + required: true + version: + description: The version of the service to deploy + required: true + api: + description: The KUBE_ENV_API + required: true + cert: + description: The KUBE_CERT + required: true + cluster: + description: The KUBE_CLUSTER + required: true + namespace: + description: The KUBE_NAMESPACE + required: true + token: + description: The KUBE_TOKEN + required: true + k8s_deployment_name: + description: "Kubernetes deployment name" + default: 'PROJECT_NAME' + required: false + changelog_git_paths: + default: "" + description: When set it will limit the file changes shown in the changelog to the specified paths only. This is useful for multi-project builds where otherwise it will show all changes from all projects. + required: false + show_changelog: + description: Whether the changelog should be sent by slack + required: false + helm_additional_args: + description: any additional helm arguments + required: false + default: "" + helm_timeout: + description: helm timeout period + required: false + default: 5m + helm_dir: + description: location of helm configuration + required: false + default: helm_deploy + helm_allowlist_groups: + description: values for location of allowlist groups file + required: false + helm_allowlist_version: + description: setting for version of allowlist file + required: false + certificate: + description: certificate + required: true + +outputs: + deployment_changelog: + description: "The changelog for the deployment" + value: ${{ steps.version_history.outputs.deployment_changelog }} + +runs: + using: composite + steps: + - uses: actions/checkout@v4 + - name: Authenticate + uses: ministryofjustice/hmpps-github-actions/.github/actions/build-test-and-deploy/cloud-platform-auth@v2 # WORKFLOW_VERSION + with: + api: ${{ inputs.api }} + cert: ${{ inputs.cert }} + cluster: ${{ inputs.cluster }} + namespace: ${{ inputs.namespace }} + token: ${{ inputs.token }} + + - name: Get environment details + shell: bash + id: env + run: | + case ${{ inputs.environment }} in + 'development') environment='dev' ;; + 'preproduction') environment='preprod' ;; + 'production') environment='prod' ;; + *) environment=${{ inputs.environment }} ;; + esac + echo "environment=${environment}" | tee -a "$GITHUB_OUTPUT" + + - name: get version history + uses: ministryofjustice/hmpps-github-actions/.github/actions/version_history@v2 # WORKFLOW VERSION + if: ${{ inputs.show_changelog }} + id: version_history + with: + app_version: ${{ inputs.version }} + environment: ${{ inputs.environment }} + namespace: ${{ inputs.namespace }} + k8s_deployment_name: ${{ inputs.k8s_deployment_name }} + changelog_git_paths: ${{ inputs.changelog_git_paths }} + + - name: Check for IP_ALLOWLIST_GROUPS_YAML + shell: bash + id: check-ip-allowlists + run: | + if [[ -n "${{ inputs.helm_allowlist_groups }}" ]]; then + echo "${{ inputs.helm_allowlist_groups }}" | base64 --decode > ./ip-allowlist-groups.yaml + echo "ALLOWLIST_GROUPS=--values ./ip-allowlist-groups.yaml" >> $GITHUB_OUTPUT + fi + + - name: Check for IP_ALLOWLIST_GROUPS_VERSION + shell: bash + id: check-ip-allowlists-version + run: | + if [[ -n "${{ inputs.helm_allowlist_version }}" ]]; then + echo "ALLOWLIST_VERSION=--set generic-service.allowlist_version=${{ inputs.helm_allowlist_version }}" >> $GITHUB_OUTPUT + fi + - name: Write Certificate file + shell: bash + run: | + echo "Decoding the Certificate from inputs shared by inputs" + echo "${{ inputs.certificate }}" | base64 --decode > /app/WebServiceClientCert.pfx + - name: Deploy + shell: bash + run: | + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + brew install helm + yq -i ".appVersion = \"${{ inputs.version }}\"" "${{ inputs.helm_dir }}/${{ github.event.repository.name }}/Chart.yaml" + helm dependency update "${{ inputs.helm_dir }}/${{ github.event.repository.name }}" + exec helm upgrade '${{ github.event.repository.name }}' '${{ inputs.helm_dir }}/${{ github.event.repository.name }}' \ + --atomic \ + --history-max 10 \ + --force \ + --install \ + --reset-values \ + --set 'generic-service.image.tag=${{ inputs.version }}' \ + --set 'version=${{ inputs.version }}' \ + --timeout ${{ inputs.helm_timeout }} \ + --values 'helm_deploy/values-${{ steps.env.outputs.environment }}.yaml' \ + ${{ inputs.helm_additional_args }} \ + ${{ steps.check-ip-allowlists.outputs.ALLOWLIST_GROUPS }} \ + ${{ steps.check-ip-allowlists-version.outputs.ALLOWLIST_VERSION }} \ + --wait diff --git a/.github/workflows/deploy_env.yml b/.github/workflows/deploy_env.yml new file mode 100644 index 0000000..d6f92a1 --- /dev/null +++ b/.github/workflows/deploy_env.yml @@ -0,0 +1,122 @@ +name: Build & push docker image and deploy to environment + +on: + workflow_call: + inputs: + environment: + description: Environment + required: true + type: string + app_version: + description: App version + required: true + type: string + k8s_deployment_name: + description: Kubernetes deployment name + default: "PROJECT_NAME" + required: false + type: string + changelog_git_paths: + description: Changelog git paths + required: false + default: "" + type: string + show_changelog: + description: Show changelog + default: true + required: false + type: boolean + slack_notification: + description: Slack notification + default: true + required: false + type: boolean + helm_additional_args: + description: Helm additional args + default: "" + required: false + type: string + helm_timeout: + description: Helm timeout + default: "5m" + required: false + type: string + helm_dir: + description: Helm dir + default: "helm_deploy" + required: false + type: string + +permissions: + contents: read + +jobs: + + deploy_env: + name: Deploy to ${{ inputs.environment }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + environment: ${{ inputs.environment }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: azure/setup-kubectl@v4 + id: install + with: + version: latest + + - name: Set Slack Channel ID + id: set-slack-channel-id + run: | + if [[ "${{ inputs.environment }}" == "prod" ]]; then + echo "slack_channel_id=${{ vars.PROD_RELEASES_SLACK_CHANNEL }}" | tee -a $GITHUB_OUTPUT + else + echo "slack_channel_id=${{ vars.NONPROD_RELEASES_SLACK_CHANNEL }}" | tee -a $GITHUB_OUTPUT + fi + + - uses: ./.github/actions/build-test-and-deploy/cloud-platform-deploy + id: deploy + with: + environment: ${{ inputs.environment }} + version: ${{ inputs.app_version }} + api: https://${{ secrets.KUBE_CLUSTER }} + cert: ${{ secrets.KUBE_CERT }} + cluster: ${{ secrets.KUBE_CLUSTER }} + namespace: ${{ secrets.KUBE_NAMESPACE }} + token: ${{ secrets.KUBE_TOKEN }} + k8s_deployment_name: ${{ inputs.k8s_deployment_name }} + changelog_git_paths: ${{ inputs.changelog_git_paths }} + show_changelog: ${{ inputs.show_changelog }} + helm_additional_args: ${{ inputs.helm_additional_args }} + helm_timeout: ${{ inputs.helm_timeout }} + helm_dir: ${{ inputs.helm_dir }} + helm_allowlist_groups: ${{ vars.HMPPS_IP_ALLOWLIST_GROUPS_YAML }} + helm_allowlist_version: ${{ vars.HMPPS_IP_ALLOWLIST_GROUPS_VERSION }} + certificate: ${{ secrets.CERTIFICATE }} + + # Notification bit - always send prod releases to dps-releases - CVA3MKDTR + - if: ${{ always() && ( inputs.environment == 'prod' || inputs.environment == 'production' ) }} + id: prod-dps-slack + uses: ministryofjustice/hmpps-github-actions/.github/actions/slack_release_results@v2 # WORKFLOW_VERSION + with: + channel_id: 'CVA3MKDTR' + environment: ${{ inputs.environment }} + app_version: ${{ inputs.app_version }} + deploy_outcome: ${{ steps.deploy.outcome }} + slack_bot_token: ${{ secrets.HMPPS_SRE_SLACK_BOT_TOKEN }} + deployment_changelog: ${{ steps.deploy.outputs.deployment_changelog }} + + + # Optional prod releases slack channel (using PROD_RELEASES_SLACK_CHANNEL variable) + - if: ${{ always() && ( inputs.slack_notification && steps.set-slack-channel-id.outputs.slack_channel_id != '' ) }} + id: send-release-slack + uses: ministryofjustice/hmpps-github-actions/.github/actions/slack_release_results@v2 # WORKFLOW_VERSION + with: + channel_id: ${{ steps.set-slack-channel-id.outputs.slack_channel_id }} + environment: ${{ inputs.environment }} + app_version: ${{ inputs.app_version }} + deploy_outcome: ${{ steps.deploy.outcome }} + slack_bot_token: ${{ secrets.HMPPS_SRE_SLACK_BOT_TOKEN }} + deployment_changelog: ${{ steps.deploy.outputs.deployment_changelog }} diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index 2eae70d..fd0e3ab 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -59,7 +59,7 @@ jobs: needs: - build - helm_lint - uses: ministryofjustice/hmpps-github-actions/.github/workflows/deploy_env.yml@v2 # WORKFLOW_VERSION + uses: ./.github/workflows/deploy_env.yml secrets: inherit with: environment: 'dev'