From c38abf69eada07b12734858d89523b373f769258 Mon Sep 17 00:00:00 2001 From: ThomasSamson Date: Tue, 27 Feb 2024 14:13:32 +0100 Subject: [PATCH] Init CICD --- .github/workflows/build.yml | 33 ++++++++ .github/workflows/cd.yml | 38 +++++++++ .github/workflows/deploy.yml | 158 +++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/cd.yml create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..4b69ef0 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,33 @@ +name: Build + +on: + workflow_call: + +jobs: + build-push-php: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Build/Push + uses: coopTilleuls/action-docker-build-push@v10 + with: + IMAGE_NAME: plateformcoop-ebs-php + BUILD_CONTEXT: . + BUILD_TARGET: app_php + REGISTRY_JSON_KEY: ${{ secrets.GITHUB_TOKEN }} + IMAGE_REPOSITORY: ghcr.io/Apes-HDF + + build-push-caddy: + # Same Dockerfile as php, with a build target which is after + needs: [build-push-php] + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Build/Push + uses: coopTilleuls/action-docker-build-push@v10 + with: + IMAGE_NAME: plateformcoop-ebs-caddy + BUILD_CONTEXT: . + BUILD_TARGET: app_caddy + REGISTRY_JSON_KEY: ${{ secrets.GITHUB_TOKEN }} + IMAGE_REPOSITORY: ghcr.io/Apes-HDF diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..b40ed43 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,38 @@ +name: CD + + +on: + push: + branches: + - main + +jobs: + # remove-deploy-label: + # name: Remove deploy label + # if: github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy') + # runs-on: ubuntu-latest + # steps: + # - uses: mondeja/remove-labels-gh-action@v1 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # labels: | + # deploy + + build: + name: Build + uses: ./.github/workflows/build.yml + + deploy: + name: Deploy + needs: [ build ] + uses: ./.github/workflows/deploy.yml + concurrency: ${{ github.ref }}-deploy + secrets: + domain: ${{ secrets.DOMAIN }} + payum-apikey: ${{ secrets.PAYUM_APIKEY }} + mailer-dsn: '${{ secrets.MAILER_DSN }}' + storage-key: ${{ secrets.STORAGE_KEY }} + storage-secret-key: ${{ secrets.STORAGE_SECRET_KEY}} + project-id: ${{ secrets.PROJECT_ID }} + workload-identity-provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }} + database-url: ${{ secrets.DATABASE_URL }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..828344e --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,158 @@ +name: Deploy + +on: + workflow_call: + secrets: + kubeconfig: + description: kubeconfig stored as a base64 encrypted secret + required: true + domain: + description: Main project deploy domain used in URLs + required: true + payum-apikey: + description: Payum API Key + required: true + sms-dsn: + description: SMS DSN + required: true + mailer-dsn: + description: MAILER DSN + storage-key: + description: storage key + required: true + storage-secret-key: + description: storage secret key + required: true + project-id: + description: GCP project ID + required: true + workload-identity-provider: + description: GCP workload identity provider + required: true + database-url: + description: Database URL + required: true + + +jobs: + meta: + name: Meta + runs-on: ubuntu-latest + outputs: + context: ${{ steps.meta.outputs.context }} + environment: ${{ steps.meta.outputs.environment }} + image_tag: ${{ steps.meta.outputs.image_tag }} + release_name: ${{ steps.meta.outputs.release_name }} + url: ${{ steps.meta.outputs.url }} + project: ${{ steps.meta.outputs.project }} + namespace: ${{ steps.meta.outputs.namespace }} + storage_name: ${{ steps.meta.outputs.storage_name }} + steps: + - name: Generate metadata + id: meta + run: | + set -xo pipefail + PROJECT=plateformcoop-ebs + if [[ "${{ github.ref }}" == *"tag"* ]]; then + # Tags are deployed in prod + CONTEXT=prod + ENVIRONMENT=prod + IMAGE_TAG=${{ github.ref_name }} + RELEASE_NAME=prod + URL=${{ vars.DOMAIN }} + STORAGE_NAME=${{ vars.STORAGE_BUCKET }} + echo "context=${CONTEXT}" >> $GITHUB_OUTPUT + echo "environment=${ENVIRONMENT}" >> $GITHUB_OUTPUT + echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT + echo "release_name=${RELEASE_NAME}" >> $GITHUB_OUTPUT + echo "namespace=${CONTEXT}-${PROJECT}" >> $GITHUB_OUTPUT + echo "url=${URL}" >> $GITHUB_OUTPUT + echo "storage_name=${STORAGE_NAME}" >> $GITHUB_OUTPUT + + deploy: + name: Deploy + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: 'read' + id-token: 'write' + pull-requests: 'write' + environment: + name: ${{ needs.meta.outputs.environment }} + needs: ["meta"] + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: GKE Auth + uses: 'google-github-actions/auth@v2' + with: + project_id: '${{ secrets.project-id }}' + workload_identity_provider: '${{ secrets.workload-identity-provider }}' + + - name: Setup gcloud + uses: google-github-actions/setup-gcloud@v1 + with: + project_id: ${{ secrets.project-id }} + + - name: Connect cluster + run: | + gcloud components install gke-gcloud-auth-plugin + gcloud auth login --cred-file=$CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE + gcloud container clusters get-credentials ${{ vars.CLUSTER_NAME }} --region europe-west1 --project ${{ secrets.project-id }} + kubectl config view + + # https://github.com/helm/helm/issues/8036 + - name: Build helm dependencies + run: | + set -o pipefail + # add all repos + if [ -f "./helm/chart/Chart.lock" ]; then + yq --indent 0 '.dependencies | map(["helm", "repo", "add", .name, .repository] | join(" ")) | .[]' "./helm/chart/Chart.lock" | sh --; + fi + helm dependency build ./helm/chart + + - name: Deploy on namespace + id: deploy + shell: bash + run: | + set -o pipefail + if ! helm upgrade --install ${{ needs.meta.outputs.release_name }} ./helm/chart \ + --atomic \ + --debug \ + --namespace ${{ needs.meta.outputs.namespace }} \ + --set=php.image.tag=${{ needs.meta.outputs.image_tag }} \ + --set=caddy.image.tag=${{ needs.meta.outputs.image_tag }} \ + --set=ingress.hosts[0].host=${{ needs.meta.outputs.url }} \ + --set=ingress.tls[0].secretName=${{ needs.meta.outputs.release_name }}-tls \ + --set=ingress.tls[0].hosts[0]=${{ needs.meta.outputs.url }} \ + --set=postgresql.url="${{ secrets.database-url }}" \ + --set=payum.apikey="${{ secrets.payum-apikey }}" \ + --set=php.storage.bucket="${{ needs.meta.outputs.storage_name }}" \ + --set=php.storage.endpoint="https://storage.googleapis.com" \ + --set=php.storage.region="eu-west-1" \ + --set=php.storage.usePathStyleEndpoint=true \ + --set=php.storage.key="${{ secrets.storage-key }}" \ + --set=php.storage.secret="${{ secrets.storage-secret-key }}" \ + --values ./helm/chart/values-${{ needs.meta.outputs.context }}.yml \ + | sed --unbuffered '/USER-SUPPLIED VALUES/,$d' ; then + echo "Deployment has failed!" + echo "Here are the last events to help diagnose the problem:" + kubectl get events --namespace ${{ needs.meta.outputs.namespace }} --sort-by .metadata.creationTimestamp + exit 1 + fi + + - name: Output deployment URL + uses: actions/github-script@v6 + if: github.event_name == 'pull_request' + env: + URL: ${{ needs.meta.outputs.url }} + with: + script: | + const { URL } = process.env + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `Chart has been deployed with this url:\n\`\`\`\n${URL}\n\`\`\`` + })