Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto Deployment #83

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 48 additions & 7 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,62 @@ on:
services:
description: 'Services to deploy (space seperated)'
required: true
repository_dispatch:
types:
- deploy-trigger

jobs:
validate_environments:
runs-on: ubuntu-latest
outputs:
validate_environments: ${{ steps.validate_environments.outputs.validate_environments }}
steps:
- name: Validate environment
id: validate_environments
run: |
CLIENT_PAYLOAD_ENVIRONMENT='${{ toJson(github.event.client_payload.environment) }}'

# Write the secret to a temporary file
echo '${{ secrets.PERMIT_AUTO_DEPLOY }}' > permit_auto_deploy.json

PERMIT_AUTO_DEPLOY=$(cat permit_auto_deploy.json)

echo "PERMIT_AUTO_DEPLOY: $PERMIT_AUTO_DEPLOY"

# Find common values using jq
VALIDATED_ENVIRONMENTS=$(jq -n --argjson client "$CLIENT_PAYLOAD_ENVIRONMENT" --argjson allow "$PERMIT_AUTO_DEPLOY" \
'[ $client[] | select($allow[] == .) ]' | jq -c '.')

# Setting to dev if no common environment found
if [ "$VALIDATED_ENVIRONMENTS" == "" ]; then
VALIDATED_ENVIRONMENTS='["dev"]'
fi

echo "VALIDATED_ENVIRONMENTS: $VALIDATED_ENVIRONMENTS"

# Export environment variable and write to file
echo "validated_environments=$VALIDATED_ENVIRONMENTS" >> $GITHUB_OUTPUT

deployment:
runs-on: ubuntu-latest
name: Deploy ${{inputs.services}} in ${{inputs.environment}}
needs: validate_environments
strategy:
matrix:
env: ${{ fromJson(needs.validate_environments.outputs.validated_environments) }}
name: Deploy ${{ inputs.services || github.event.client_payload.services }} in ${{inputs.environment || matrix.env }}

steps:
- name: Uppercase environment
run: |
echo "ENV=`echo ${{inputs.environment}} | tr '[:lower:]' '[:upper:]'`" >>${GITHUB_ENV}
echo "ENV=`echo ${{ inputs.environment || matrix.env }} | tr '[:lower:]' '[:upper:]'`" >>${GITHUB_ENV}

- name: Set Default Values to Repository Variable
run: |
echo "ENABLE_FORCE_RECREATE=${{ vars.ENABLE_FORCE_RECREATE || 1 }}" >> ${GITHUB_ENV}
if [ "${{ github.event_name }}" == "repository_dispatch" ]; then
echo "ENABLE_FORCE_RECREATE=0" >> ${GITHUB_ENV}
else
echo "ENABLE_FORCE_RECREATE=${{ vars.ENABLE_FORCE_RECREATE || 1 }}" >> ${GITHUB_ENV}
fi
echo "DISABLE_REMOVE_ORPHANS=${{ vars.DISABLE_REMOVE_ORPHANS || 0 }}" >> ${GITHUB_ENV}
echo "DISABLE_ANSI=${{ vars.DISABLE_ANSI || 1 }}" >> ${GITHUB_ENV}
echo "ENABLE_GIT_PULL=${{ vars.ENABLE_GIT_PULL || 1 }}" >> ${GITHUB_ENV}
Expand All @@ -39,15 +81,14 @@ jobs:
echo "::error::Secret '${{ format('{0}_WEBHOOK_URL',env.ENV) }}' is not set"
exit 1
fi
if [ -z "${{ github.event.inputs.services }}" ]; then
echo "::error::'${{ github.event.inputs.services }}' is empty"
if [ -z "${{ github.event.inputs.services || github.event.client_payload.services }}" ]; then
echo "::error::'${{ github.event.inputs.services || github.event.client_payload.services }}' is empty"
exit 1
fi

encoded_services=$(python3 -c "from urllib.parse import quote; print(quote('${{ github.event.inputs.services }}'))")
encoded_services=$(python3 -c "from urllib.parse import quote; print(quote('${{ github.event.inputs.services || github.event.client_payload.services}}'))")
curl -X POST \
--fail-with-body -sS --no-buffer\
-H "Content-Type: application/json" \
-d '{"secret_token": "${{ secrets[format('{0}_WEBHOOK_PASSWORD',env.ENV)] }}", "ENABLE_FORCE_RECREATE":${{ env.ENABLE_FORCE_RECREATE }}, "DISABLE_REMOVE_ORPHANS":${{ env.DISABLE_REMOVE_ORPHANS }}, "DISABLE_ANSI":${{ env.DISABLE_ANSI }} ,"ENABLE_GIT_PULL":${{ env.ENABLE_GIT_PULL }}}' \
"${{ secrets[format('{0}_WEBHOOK_URL',env.ENV)] }}/hooks/deploy?services=$encoded_services"

16 changes: 15 additions & 1 deletion docs/onboarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,27 @@ Example: [/examples/workflows/build-and-push.yaml](../examples/workflows/build-a
> In case you see 403 error, checkout [this](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#github-actions-access-for-packages-scoped-to-organizations)



Reference:
- For further clarification and detailed instructions, you can refer to the [GitHub documentation](https://docs.github.com/en/actions/publishing-packages/publishing-docker-images#publishing-images-to-github-packages).

### 3. Add a workflow to test your image
Example: [/examples/workflows/docker-test.yaml](../examples/workflows/docker-test.yaml)

### 4. To Auto Deploy Service

#### Assumptions made:
SERVICE_REPO: Repository from which the service is deployed.
DEVOPS_REPO: Repository where deployment is triggered.
#### In SERVICE_REPO
- Allow [access via fine-grained](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization#restricting-access-by-fine-grained-personal-access-tokens) personal access tokens in the organization
- [Configure actions](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#allowing-access-to-components-in-a-private-repository) to be triggered from another repository within the same organization
- Generate a Fine-Grained token (Personal Access Token) permissions required - Actions(Read and Write) and Content(Read and Write)
- Store the PAT as repository secret, set name field as `PAT`
- If devops repository name is not `devops`, set the Repository Secret named `DEVOPS_REPO_NAME` and value as the name of devops repository
- If your repository name in snake_case differs from the service name, set the Repository Secret named `SERVICE_NAME` and value as the name of service name in snake_case
- Create a repository secret named `ENABLE_AUTO_DEPLOY` and set value for targeted auto deployment to run for all environment given here, eg:`["dev", "stage"]`
#### In DEVOPS_REPO
- Create a secret named `PERMIT_AUTO_DEPLOY` and set value as only allowed environments here can be triggered through other repository, eg: `["dev"]`

## Adding your service

Expand Down
18 changes: 17 additions & 1 deletion examples/workflows/build-and-push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
permissions:
contents: read
packages: write
actions: write
steps:

- name: Checkout code
Expand Down Expand Up @@ -54,4 +55,19 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
labels: ${{ steps.meta.outputs.labels }}

- name: Convert repository name to snake case
run: |
REPO_NAME=$(echo "${GITHUB_REPOSITORY}" | awk -F/ '{print $2}')
SNAKE_CASE_REPO_NAME=$(echo "${REPO_NAME}" | sed 's/\(.\)\([A-Z]\)/\1_\2/g' | tr '[:upper:]' '[:lower:]' | sed 's/^_//' | tr -s '_' | tr '[:upper:]' '[:lower:]')
echo "SERVICE=${SNAKE_CASE_REPO_NAME}" >> $GITHUB_ENV

- name: Trigger deployment workflow
if: ${{ success() }}
run: |
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ secrets.PAT }}" \
https://api.github.com/repos/${{ github.repository_owner }}/${{ secrets.DEVOPS_REPO_NAME || 'devops' }}/dispatches \
-d '{"event_type":"deploy-trigger","client_payload":{"services":"${{ secrets.SERVICE_NAME || env.SERVICE }}", "environment":${{ secrets.ENABLE_AUTO_DEPLOY }}}}'