-
Notifications
You must be signed in to change notification settings - Fork 261
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #727 from 0xPolygon/SPEC-170-dev-deployment-update…
…-for-review Deployment fix for dev deployment through hosted/<branch> PRs
- Loading branch information
Showing
6 changed files
with
306 additions
and
3 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
on: | ||
workflow_call: | ||
inputs: | ||
environment: | ||
required: false | ||
type: string | ||
default: "dev" | ||
core_app: | ||
required: false | ||
type: string | ||
description: "Core app name" | ||
default: "docs" | ||
account_number: | ||
required: false | ||
type: string | ||
description: "AWS Account number for deployment" | ||
default: "058264511034" | ||
region: | ||
required: false | ||
type: string | ||
description: "AWS region for deployment" | ||
default: "eu-west-1" | ||
task_definition: | ||
required: false | ||
type: string | ||
description: "Task Definition path for deployment" | ||
default: ".github/assets/dev-taskdef.json" | ||
cluster_name: | ||
required: false | ||
type: string | ||
description: "Cluster name for deployment" | ||
default: "frontend-dev-ecs-cluster" | ||
|
||
jobs: | ||
build_site_data: | ||
name: ${{ inputs.environment }} deployment | ||
runs-on: ubuntu-latest | ||
environment: ${{ inputs.environment }} | ||
permissions: | ||
id-token: write | ||
contents: write | ||
env: | ||
AWS_REGION: ${{ inputs.region }} | ||
ECR_REPOSITORY: ${{ inputs.core_app }}-${{ inputs.environment }}-ecr | ||
ECS_SERVICE: ${{ inputs.core_app }}-${{ inputs.environment }}-ecs-service | ||
ECS_CLUSTER: frontend-${{ inputs.environment }}-ecs-cluster | ||
ECS_TASK_DEFINITION: ${{ inputs.task_definition }} | ||
APP_NAME: ${{ inputs.core_app }}-${{ inputs.environment }} | ||
steps: | ||
- name: Checkout Code Repository | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: Configure AWS credentials | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
aws-region: ${{ env.AWS_REGION }} | ||
role-to-assume: arn:aws:iam::${{ inputs.account_number }}:role/${{ env.APP_NAME }}-GithubActionsRole | ||
role-session-name: GithubActionsSession | ||
|
||
- uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.11' | ||
|
||
- name: Install pipenv | ||
run: pip install pipenv | ||
|
||
- name: Install GitHub CLI | ||
run: | | ||
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \ | ||
&& sudo mkdir -p -m 755 /etc/apt/keyrings \ | ||
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \ | ||
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ | ||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ | ||
&& sudo apt update \ | ||
&& sudo apt install gh -y | ||
- name: Authenticate GitHub CLI | ||
run: gh auth login --with-token <<< "${{ secrets.GITHUB_TOKEN }}" | ||
|
||
- name: Build Site | ||
run: | | ||
python build_branches.py | ||
- name: Login to Amazon ECR | ||
id: login-ecr | ||
uses: aws-actions/amazon-ecr-login@v1 | ||
|
||
- name: Build, tag, and push image to Amazon ECR | ||
id: build-image | ||
env: | ||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} | ||
IMAGE_TAG: ${{ github.sha }}-${{ github.run_number }} | ||
ECR_REPOSITORY: ${{ env.APP_NAME }}-ecr | ||
run: | | ||
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f Dockerfile.review . | ||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG | ||
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT | ||
- name: Fill in the new image ID in the Amazon ECS task definition | ||
id: task-def | ||
uses: aws-actions/amazon-ecs-render-task-definition@v1 | ||
with: | ||
task-definition: ${{ env.ECS_TASK_DEFINITION }} | ||
container-name: ${{ env.APP_NAME }} | ||
image: ${{ steps.build-image.outputs.image }} | ||
|
||
- name: Deploy Amazon ECS task definition | ||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1 | ||
with: | ||
task-definition: ${{ steps.task-def.outputs.task-definition }} | ||
service: ${{ env.ECS_SERVICE }} | ||
cluster: ${{ env.ECS_CLUSTER }} | ||
wait-for-service-stability: true | ||
|
||
- name: Cloudflare Cache Purge | ||
uses: nathanvaughn/actions-cloudflare-purge@master | ||
with: | ||
cf_zone: ${{ secrets.CLOUDFLARE_ZONE }} | ||
cf_auth: ${{ secrets.CLOUDFLARE_AUTH_KEY }} | ||
hosts: ${{ env.APP_NAME }}.polygon.technology |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
name: hosted branch pr deployment | ||
on: | ||
pull_request: | ||
types: [opened, edited, reopened] | ||
branches: | ||
- hosted/* | ||
push: | ||
branches: | ||
- dev | ||
workflow_dispatch: | ||
|
||
jobs: | ||
deploy: | ||
uses: ./.github/workflows/build_and_deploy.yml | ||
secrets: inherit | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
FROM nginx:alpine | ||
|
||
COPY nginx.conf /etc/nginx/nginx.conf | ||
COPY app /app | ||
|
||
WORKDIR /app | ||
EXPOSE 80 | ||
CMD ["nginx", "-g", "daemon off;"] |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import ast | ||
import os | ||
import shutil | ||
import subprocess | ||
|
||
|
||
def install_mkdocs_with_pipenv(): | ||
""" | ||
Builds a particular branch site. | ||
Having a varying set of requirements can be handled by having each branch | ||
build their dependencies and then running mkdocs build. | ||
""" | ||
folder = os.getcwd() | ||
subprocess.run(["pipenv", "install", "--site-packages"], cwd=folder) | ||
subprocess.run(["pipenv", "install", "-r", "requirements.txt"], cwd=folder) | ||
subprocess.run(["pipenv", "run", "mkdocs", "build"], cwd=folder) | ||
|
||
def copy_folder(source_dir, target_dir): | ||
""" | ||
Copies contents from source directory to target directory | ||
:param source_dir: Source directory from which contents are to be copied | ||
:param target_dir: Target Directory where the contents are copied to. | ||
""" | ||
os.makedirs(target_dir, exist_ok=True) | ||
|
||
for item in os.listdir(source_dir): | ||
source_path = os.path.join(source_dir, item) | ||
target_path = os.path.join(target_dir, item) | ||
|
||
if os.path.isdir(source_path): | ||
shutil.copytree(source_path, target_path, dirs_exist_ok=True) | ||
else: | ||
if os.path.exists(target_path): | ||
os.remove(target_path) | ||
shutil.copy2(source_path, target_path) | ||
|
||
def delete_folders(folder_paths): | ||
""" | ||
Cleans existing folders for app and branches before executing the builds | ||
:param folder_paths: List of folders to be deleted under the current working directory | ||
""" | ||
for folder_path in folder_paths: | ||
try: | ||
shutil.rmtree(folder_path) | ||
print(f"Folder {folder_path} deletion successful.") | ||
except OSError as e: | ||
print(f"Error deleting folder: {e}") | ||
|
||
def clone_data_to_branch_folder(branch_name, remote_url, parent_dir, pr_number=None): | ||
""" | ||
Clones data to branch folder in branch/<PR Number> or branch/dev folder | ||
:param branch_name: Branch to clone and build | ||
:param remote_url: Remote url for the git repository | ||
:param parent_dir: Parent directory to get context of where data is stored | ||
:param pr_number: PR number for the branch to host data into the folder | ||
""" | ||
common_dir = "branch" | ||
target_path = os.path.join(common_dir, pr_number) | ||
os.makedirs(target_path, exist_ok=True) | ||
os.chdir(target_path) | ||
subprocess.run(["git", "init"]) | ||
subprocess.run(["git", "remote", "add", "origin", remote_url]) | ||
print(f"Checking out branch {branch_name}") | ||
subprocess.run(["git", "fetch", "--depth", "1", "origin", branch_name]) | ||
subprocess.run([ | ||
"git", "checkout", "-b", branch_name, "--track", | ||
f"origin/{branch_name}" | ||
]) | ||
install_mkdocs_with_pipenv() | ||
source_dir = os.path.join(os.getcwd(), "site") | ||
copy_folder(source_dir, os.path.join(parent_dir, "app", pr_number)) | ||
os.chdir(parent_dir) | ||
|
||
|
||
def process_branch_folders(): | ||
""" | ||
Clones the branch specific code to hosted/<branch-name> folder. | ||
It then executes the build command and copy the built site to apps folder | ||
under the same branch name | ||
:return: PR numbers in str list where the site data is copied to | ||
""" | ||
delete_folders(["branch", "app"]) | ||
|
||
command = ["gh", "pr", "list", "--json", "number,headRefName"] | ||
command_run_result = subprocess.run(command, capture_output=True, text=True).stdout.strip() | ||
branches_data = ast.literal_eval(command_run_result) | ||
remote_url = subprocess.run(["git", "remote", "get-url", "origin"], | ||
capture_output=True, | ||
text=True).stdout.strip() | ||
parent_dir = os.getcwd() | ||
clone_data_to_branch_folder("dev", remote_url, parent_dir, "dev") | ||
pr_numbers = [] | ||
for branch_data in branches_data: | ||
if not branch_data["headRefName"].startswith("hosted/"): | ||
continue | ||
pr_number = str(branch_data["number"]) | ||
clone_data_to_branch_folder(branch_data["headRefName"], remote_url, parent_dir, pr_number) | ||
pr_numbers.append(pr_number) | ||
|
||
return pr_numbers | ||
|
||
def update_nginx_config(pr_numbers): | ||
""" | ||
Updates nginx.conf file with branches built information to host multiple versions | ||
of software at the same time. | ||
:param pr_numbers: pr numbers a str list of open pr numbers to be hosted | ||
""" | ||
config_file = os.path.join(os.getcwd(), "nginx.conf") | ||
nginx_location_blocks = "" | ||
|
||
for pr_number in pr_numbers: | ||
location_block = f"""location /{pr_number} {{ | ||
alias /app/{pr_number}; | ||
try_files $uri $uri/ /index.html; | ||
error_page 404 /404.html; | ||
}} | ||
""" | ||
nginx_location_blocks += location_block | ||
|
||
with open(config_file, "r+") as f: | ||
content = f.read() | ||
content = content.replace("#REPLACE_APPS", nginx_location_blocks) | ||
f.seek(0) | ||
f.write(content) | ||
f.truncate() | ||
|
||
print("NGINX configuration updated successfully!") | ||
|
||
if __name__ == "__main__": | ||
current_dir = os.getcwd() | ||
pr_numbers = process_branch_folders() | ||
update_nginx_config(pr_numbers) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
worker_processes auto; | ||
|
||
events { | ||
worker_connections 1024; | ||
} | ||
|
||
http { | ||
include mime.types; | ||
default_type application/octet-stream; | ||
|
||
sendfile on; | ||
keepalive_timeout 65; | ||
|
||
server { | ||
listen 80; | ||
|
||
#REPLACE_APPS | ||
location / { | ||
alias /app/dev/; | ||
index index.html; | ||
try_files $uri $uri/ /index.html; | ||
error_page 404 /404.html; | ||
} | ||
} | ||
} |