nolanpro send deploy EKS 🚀 #118
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: deploy-k8s | |
| run-name: ${{ github.actor }} send deploy EKS 🚀 | |
| on: | |
| pull_request: | |
| types: [opened, reopened, synchronize, edited, closed] | |
| #schedule: | |
| # - cron: '30 2 * * *' # run daily | |
| workflow_dispatch: | |
| inputs: | |
| delete: | |
| description: 'CI Instance ID to delete. If present, all other jobs will be skipped.' | |
| required: false | |
| default: 'false' | |
| workflow_call: | |
| env: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: ${{ secrets.AWS_REGION }} | |
| AWS_URL: ${{ secrets.AWS_URL }} | |
| pull_req_id: ${{github.event.pull_request.number}} | |
| DATE: $(date -d '-1 day' '+%Y-%m-%d'|sed 's/-//g') | |
| CURRENT_DATE: $(date '+%Y-%m-%d %H:%M:%S'|sed 's/-//g') | |
| CI_PACKAGE_BRANCH: ${{ github.event.pull_request.head.ref || github.event.ref || 'develop' }} | |
| CI_PROJECT: ${{github.event.pull_request.head.repo.name || github.event.repository.name || 'processmaker' }} | |
| CI_PR_BODY: ${{ github.event_name == 'schedule' && 'No ci tags needed here' || github.event.pull_request.body }} | |
| IMAGE_TAG: $(echo "$CI_PROJECT-$CI_PACKAGE_BRANCH" | sed "s;/;-;g" | sed "s/refs-heads-//g") | |
| DEPLOY: ${{ secrets.DEPLOY }} | |
| GH_USER: ${{ secrets.GH_USER }} | |
| GH_EMAIL: ${{ secrets.GH_EMAIL }} | |
| DOM_EKS: ${{ secrets.DOM_EKS }} | |
| GITHUB_TOKEN: ${{ secrets.GIT_TOKEN }} | |
| BUILD_BASE: ${{ (contains(github.event.pull_request.body, 'ci:build-base') || github.event_name == 'schedule') && '1' || '0' }} | |
| MULTITENANCY: ${{ (contains(github.event.pull_request.body, 'ci:multitenancy')) && 'true' || 'false' }} | |
| BASE_IMAGE: ${{ secrets.REGISTRY_HOST }}/processmaker/processmaker:base | |
| CUSTOMER_LICENSES_PAT: ${{ secrets.CUSTOMER_LICENSES_PAT }} | |
| # K8S_BRANCH: ${{ contains(github.event.pull_request.body, 'ci:next') && 'next' || 'release-2024-fall' }} | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| imageEKS: | |
| name: build-docker-image-EKS | |
| if: github.event.action != 'closed' && inputs.delete == 'false' | |
| runs-on: ${{ vars.RUNNER }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: processmaker/.github | |
| - name: Common | |
| uses: ./.github/actions/common | |
| with: | |
| token: ${{ secrets.GIT_TOKEN }} | |
| - name: Set image name | |
| run: | | |
| echo "IMAGE=${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:$RESOLVED_IMAGE_TAG" >> $GITHUB_ENV | |
| - name: Generate image EKS | |
| if: ${{ !contains(github.event.pull_request.body, 'ci:skip-build') }} | |
| run: | | |
| cd pm4-k8s-distribution/images | |
| export CI_RELEASE_BRANCH=$RELEASE_BRANCH | |
| branch=$(echo "${{ env.CI_PACKAGE_BRANCH }}" | sed 's/refs-heads-//g') tag=${{env.IMAGE_TAG}} bash build.k8s-cicd.sh | |
| echo "VERSION=${{ env.IMAGE_TAG }}" >> $GITHUB_ENV | |
| - name: List Images | |
| run: | | |
| docker images | |
| # - name: Run Trivy vulnerability scanner | |
| # uses: aquasecurity/trivy-action@master | |
| # with: | |
| # image-ref: processmaker/enterprise:${{ env.VERSION }} | |
| # format: 'table' | |
| # exit-code: '0' | |
| # ignore-unfixed: false | |
| # vuln-type: 'os,library' | |
| # scanners: 'vuln,secret' | |
| # severity: 'MEDIUM,HIGH,CRITICAL' | |
| # env: | |
| # TRIVY_TIMEOUT: 30m | |
| - name: Login to Harbor | |
| uses: docker/login-action@v2 | |
| with: | |
| registry: ${{ secrets.REGISTRY_HOST }} | |
| username: ${{ secrets.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - name: Push Enterprise Image to Harbor | |
| if: ${{ !contains(github.event.pull_request.body, 'ci:skip-build') }} | |
| run: | | |
| docker tag processmaker/enterprise:${{env.IMAGE_TAG}} ${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{env.IMAGE_TAG}} | |
| docker push ${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{env.IMAGE_TAG}} | |
| deployEKS: | |
| name: deploy-EKS | |
| if: contains(github.event.pull_request.body, 'ci:deploy') | |
| needs: imageEKS | |
| runs-on: ${{ vars.RUNNER }} | |
| steps: | |
| - name: Checkout .github repo | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: processmaker/.github | |
| ref: multitenancy | |
| - name: Common | |
| uses: ./.github/actions/common | |
| with: | |
| token: ${{ secrets.GIT_TOKEN }} | |
| - name: Install pm4-tools | |
| run: | | |
| cd pm4-k8s-distribution/images/pm4-tools | |
| composer install --no-interaction | |
| cd .. | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v1 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: ${{ secrets.AWS_REGION }} | |
| - name: Set up kubectl | |
| run: | | |
| curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" | |
| chmod +x kubectl | |
| sudo mv kubectl /usr/local/bin/ | |
| echo ${{ secrets.AWS_ACCESS_KEY_ID }} | md5sum | |
| - name: Authenticate with Amazon EKS | |
| run: aws eks update-kubeconfig --region us-east-1 --name pm4-eng | |
| - name: Deploy instance EKS | |
| env: | |
| IMAGE_TAG: ${{ env.IMAGE_TAG }} | |
| CURRENT_DATE: ${{ env.CURRENT_DATE }} | |
| HELM_REPO: ${{ secrets.HELM_REPO }} | |
| HELM_USERNAME: ${{ secrets.HELM_USERNAME }} | |
| HELM_PASSWORD: ${{ secrets.HELM_PASSWORD }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| OPEN_AI_SECRET: ${{ secrets.OPENAI_API_KEY }} | |
| ANALYTICS_AWS_ACCESS_KEY: ${{ secrets.ANALYTICS_AWS_ACCESS_KEY }} | |
| ANALYTICS_AWS_SECRET_KEY: ${{ secrets.ANALYTICS_AWS_SECRET_KEY }} | |
| REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} | |
| REGISTRY_HOST: ${{ secrets.REGISTRY_HOST }} | |
| REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} | |
| TWILIO_SID: ${{ secrets.TWILIO_SID }} | |
| TWILIO_TOKEN: ${{ secrets.TWILIO_TOKEN }} | |
| versionHelm: ${{ env.versionHelm }} | |
| DOM_EKS: ${{ env.DOM_EKS }} | |
| KEYCLOAK_CLIENT_SECRET: ${{ secrets.KEYCLOAK_CLIENT_SECRET }} | |
| KEYCLOAK_PASSWORD: ${{ secrets.KEYCLOAK_PASSWORD }} | |
| CUSTOMER_LICENSES_PAT: ${{ secrets.CUSTOMER_LICENSES_PAT }} | |
| RDS_ADMIN_USERNAME: ${{ secrets.RDS_ADMIN_USERNAME }} | |
| RDS_ADMIN_PASSWORD: ${{ secrets.RDS_ADMIN_PASSWORD }} | |
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| run: | | |
| instance=$(echo -n ${{env.IMAGE_TAG}} | md5sum | head -c 10) | |
| echo "INSTANCE: $instance" | |
| echo "IMAGE_TAG: $IMAGE_TAG" | |
| sed -i "s#{{INSTANCE}}#$instance#g" .github/scripts/deploy-instance.sh | |
| sed -i "s#{{INSTANCE}}#$instance#g" .github/templates/instance.yaml | |
| sed -i "s#{{INSTANCE}}#$instance#g" .github/templates/db.yaml | |
| sed -i "s#{{IMAGE_TAG}}#$IMAGE_TAG#g" .github/templates/instance.yaml | |
| sed -i "s#{{KEYCLOAK_CLIENT_SECRET}}#$KEYCLOAK_CLIENT_SECRET#g" .github/templates/instance.yaml | |
| sed -i "s#{{KEYCLOAK_PASSWORD}}#$KEYCLOAK_PASSWORD#g" .github/templates/instance.yaml | |
| sed -i "s#{{CUSTOMER_LICENSES_PAT}}#$CUSTOMER_LICENSES_PAT#g" .github/templates/instance.yaml | |
| sed -i "s#{{MYSQL_USER}}#$RDS_ADMIN_USERNAME#g" .github/templates/instance.yaml | |
| sed -i "s#{{MYSQL_PASSWORD}}#$RDS_ADMIN_PASSWORD#g" .github/templates/instance.yaml | |
| sed -i "s#{{MULTITENANCY}}#$MULTITENANCY#g" .github/templates/instance.yaml | |
| sed -i "s#{{MYSQL_USERNAME}}#$RDS_ADMIN_USERNAME#g" .github/templates/db.yaml | |
| sed -i "s#{{MYSQL_PASSWORD}}#$RDS_ADMIN_PASSWORD#g" .github/templates/db.yaml | |
| echo "=== Checking instance.yaml after replacements ===" | |
| cat .github/templates/instance.yaml | |
| echo "=== Checking db.yaml after replacements ===" | |
| cat .github/templates/db.yaml | |
| chmod +x .github/scripts/deploy-instance.sh | |
| bash .github/scripts/deploy-instance.sh | |
| if [ "$MULTITENANCY" = "true" ]; then | |
| export INSTANCE_URL="https://tenant-1.ci-$instance.engk8s.processmaker.net" | |
| else | |
| export INSTANCE_URL="https://ci-$instance.engk8s.processmaker.net" | |
| fi | |
| echo "Instance URL: $INSTANCE_URL" | |
| bash .github/scripts/gh_comment.sh "$CI_PROJECT" "$pull_req_id" | |
| runAPITest: | |
| name: Run API Tests | |
| needs: [deployEKS] | |
| if: contains(github.event.pull_request.body, 'ci:api-test') | |
| runs-on: ${{ vars.RUNNER }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: processmaker/.github | |
| - name: Common | |
| uses: ./.github/actions/common | |
| with: | |
| token: ${{ secrets.GIT_TOKEN }} | |
| - name: Install pm4-tools | |
| run: | | |
| echo "versionHelm=$(grep "version:" "pm4-k8s-distribution/charts/enterprise/Chart.yaml" | awk '{print $2}' | sed 's/\"//g')" >> $GITHUB_ENV | |
| cd pm4-k8s-distribution/images/pm4-tools | |
| composer install --no-interaction | |
| cd .. | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v1 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID1 }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY1 }} | |
| aws-region: ${{ secrets.AWS_REGION }} | |
| - name: Set up kubectl | |
| run: | | |
| curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" | |
| chmod +x kubectl | |
| sudo mv kubectl /usr/local/bin/ | |
| - name: Authenticate with Amazon EKS | |
| run: aws eks update-kubeconfig --region us-east-1 --name pm4-eng | |
| - name: Run the API tests | |
| run: | | |
| INSTANCE=$(echo -n ${{env.IMAGE_TAG}} | md5sum | head -c 10) | |
| namespace="ci-$INSTANCE-ns-pm4" | |
| pr_body=$(jq -r .pull_request.body < "$GITHUB_EVENT_PATH" | base64) | |
| kubectl get pods --namespace=$namespace | |
| pod_names=$(kubectl get pods --namespace=$namespace --field-selector=status.phase=Running -o jsonpath="{.items[*].metadata.name}" | tr ' ' '\n' | grep -E '(-processmaker-scheduler-)') | |
| for pod in $pod_names; do | |
| code=' | |
| has_processmaker=$(ls /opt | grep processmaker) | |
| has_sudo=$(ls /usr/bin | grep sudo) | |
| has_php=$(ls /usr/bin | grep php) | |
| if [ ! -z "$has_processmaker" ] && [ ! -z "$has_sudo" ] && [ ! -z "$has_php" ]; then | |
| echo $pr_body | base64 -d > /tmp/pr_body | |
| cd /opt/processmaker | |
| docker system prune -af | |
| sudo -u nginx php artisan package-api-testing:run --body="$pr_body" | |
| else | |
| exit 1 | |
| fi' | |
| kubectl exec -n $namespace $pod -- /bin/sh -c "pr_body='${pr_body}';${code}" | tee /tmp/comment.md && break || true | |
| done | |
| # Send the content of /tmp/comment.md as a PR comment | |
| MESSAGE=$(cat /tmp/comment.md) | |
| GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY=${{ github.repository }} | |
| PR_NUMBER=$(jq -r .number < "$GITHUB_EVENT_PATH") | |
| if [ -z "$PR_NUMBER" ]; then | |
| echo "The PR number is not available. Make sure this script is executed in a context of Pull Request." | |
| exit 1 | |
| fi | |
| URL="https://api.github.com/repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" | |
| json_payload=$(jq -n --arg message "$MESSAGE" '{"body": $message}') | |
| curl -s \ | |
| -H "Authorization: token ${GITHUB_TOKEN}" \ | |
| -H "Accept: application/vnd.github.v3+json" \ | |
| -d "$json_payload" \ | |
| "${URL}" | |
| deleteEKS: | |
| name: Delete Instance | |
| if: github.event.action == 'closed' || inputs.delete != 'false' | |
| runs-on: self-hosted | |
| steps: | |
| - name: Delete instance EKS | |
| run: | | |
| # If inputs.delete does not equal 'false', set the IMAGE_TAG to the value of inputs.delete | |
| if [ "${{ inputs.delete }}" != "false" ]; then | |
| IMAGE_TAG=${{ inputs.delete }} | |
| else | |
| IMAGE_TAG=${{ env.IMAGE_TAG }} | |
| fi | |
| INSTANCE=$(echo -n $IMAGE_TAG | md5sum | head -c 10) | |
| if kubectl get namespace/ci-$INSTANCE-ns-pm4 ; then | |
| echo "Deleting Instace :: ci-$INSTANCE" | |
| helm delete ci-$INSTANCE | |
| kubectl delete namespace ci-$INSTANCE-ns-pm4 | |
| #Drop database | |
| deploy_db="pm4_ci-${INSTANCE}%" | |
| deploy_ai="\`pm4_ci-$INSTANCE_ai\`" | |
| # check that that string length of $deploy_db is 12 or more as a safety check. If its less than 12, exit now | |
| if [ ${#deploy_db} -lt 12 ]; then | |
| exit 1 | |
| fi | |
| # Drop the main database including any tenant databases | |
| mysql -u${{ secrets.USER_MYSQL_ENG }} -p${{ secrets.PASS_MYSQL_ENG }} -h ${{ secrets.RDS_ENG }} -N -e "SHOW DATABASES LIKE '${deploy_db}'" | xargs -I{} mysql -u${{ secrets.USER_MYSQL_ENG }} -p${{ secrets.PASS_MYSQL_ENG }} -h ${{ secrets.RDS_ENG }} -e "DROP DATABASE IF EXISTS \`{}\`;" | |
| mysql -u${{ secrets.USER_MYSQL_ENG }} -p${{ secrets.PASS_MYSQL_ENG }} -e "DROP DATABASE IF EXISTS $deploy_ai" -h ${{ secrets.RDS_ENG }} | |
| mysql -u${{ secrets.USER_MYSQL_ENG }} -p${{ secrets.PASS_MYSQL_ENG }} -e "DROP USER IF EXISTS 'user_ci-$INSTANCE'@'%'" -h ${{ secrets.RDS_ENG }} | |
| mysql -u${{ secrets.USER_MYSQL_ENG }} -p${{ secrets.PASS_MYSQL_ENG }} -e "DROP USER IF EXISTS 'user_ci-$INSTANCE_ai'@'%'" -h ${{ secrets.RDS_ENG }} | |
| #Drop image Harbor | |
| curl -X DELETE -u ${{ secrets.REGISTRY_USERNAME }}:${{ secrets.REGISTRY_PASSWORD }} "https://${{ secrets.REGISTRY_HOST }}/api/v2.0/projects/processmaker/repositories/enterprise/artifacts/${IMAGE_TAG}" | |
| echo "The instance [https://ci-$INSTANCE.engk8s.processmaker.net] was deleted!!" | |
| else | |
| echo "The pull request does not have an instance on K8s [https://ci-$INSTANCE.engk8s.processmaker.net] not found!!" | |
| fi | |
| runPhpUnit: | |
| name: run-phpunit | |
| if: github.event.action != 'closed' && inputs.delete == 'false' | |
| needs: imageEKS | |
| runs-on: ${{ vars.RUNNER }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: processmaker/.github | |
| - name: Common | |
| uses: ./.github/actions/common | |
| with: | |
| token: ${{ secrets.GIT_TOKEN }} | |
| - name: Export Params | |
| run: | | |
| echo "IMAGE=${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{env.IMAGE_TAG}}" >> $GITHUB_ENV | |
| # - uses: actions/checkout@v2 | |
| # with: | |
| # fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | |
| # - name: Clone repo K8S | |
| # run: | | |
| # echo "IMAGE: ${{ env.IMAGE }}" | |
| # git clone --depth 1 -b "$K8S_BRANCH" "https://[email protected]/ProcessMaker/pm4-k8s-distribution.git" pm4-k8s-distribution | |
| - name: Login to Harbor | |
| uses: docker/login-action@v2 | |
| with: | |
| registry: ${{ secrets.REGISTRY_HOST }} | |
| username: ${{ secrets.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - name: PHPUnits | |
| run: | | |
| cd pm4-k8s-distribution/images/pm4-tools | |
| docker pull $IMAGE | |
| docker compose down -v | |
| docker compose build phpunit | |
| docker compose run phpunit | |
| CONTAINER_ID=$(sudo docker ps -a | grep phpunit | awk '{print $1}') | |
| echo "Copying coverage report from PHP Unit Container: $CONTAINER_ID" | |
| sudo docker cp $CONTAINER_ID:/opt/processmaker/coverage.xml coverage.xml | |
| - name: Archive code coverage | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: code-coverage | |
| path: ./pm4-k8s-distribution/images/pm4-tools/coverage.xml | |
| - name: SonarQube Coverage Report | |
| uses: sonarsource/sonarqube-scan-action@master | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} | |
| with: | |
| args: > | |
| -Dsonar.projectKey=${{ secrets.SONAR_PROJECT_KEY }} | |
| -Dsonar.sources=. | |
| -Dsonar.tests=. | |
| -Dsonar.test.inclusions=**/*Test.php | |
| -Dsonar.php.coverage.reportPaths=./pm4-k8s-distribution/images/pm4-tools/coverage.xml |