Skip to content

Commit 7554b9a

Browse files
committed
FE: Implement Login Page UI & Core Logic (#8)
1 parent 52eb2c7 commit 7554b9a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+5343
-27
lines changed

.github/workflows/deploy-aws.yml

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
name: Deploy to AWS (Terraform + Ansible)
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
resource_prefix:
7+
description: 'Prefix for AWS resources (e.g., niko-, gemini-). Default is branch name or dev-.'
8+
required: false
9+
default: ''
10+
enable_frontend:
11+
description: 'Deploy Frontend to EC2'
12+
required: true
13+
type: boolean
14+
default: true
15+
enable_backend:
16+
description: 'Deploy Backend to EC2'
17+
required: true
18+
type: boolean
19+
default: true
20+
branch_ref:
21+
description: 'Branch to deploy (default: current branch)'
22+
required: false
23+
default: ''
24+
push:
25+
branches:
26+
- main # Production deployment
27+
- 'feature/**' # For feature branches, can be dev deployments
28+
- 'dev/**'
29+
pull_request:
30+
branches:
31+
- main
32+
33+
env:
34+
AWS_REGION: us-west-2
35+
TF_VERSION: "1.5.7" # Match installed version or use latest stable
36+
ANSIBLE_VERSION: "6.0.0" # Or your preferred version
37+
PYTHON_VERSION: '3.9'
38+
# Default enable flags, can be overridden by inputs
39+
ENABLE_FRONTEND: true
40+
ENABLE_BACKEND: true
41+
42+
jobs:
43+
determine_params:
44+
name: Determine Deployment Parameters
45+
runs-on: ubuntu-latest
46+
outputs:
47+
resource_prefix: ${{ steps.params.outputs.resource_prefix }}
48+
tf_action: ${{ steps.params.outputs.tf_action }}
49+
branch_name: ${{ steps.params.outputs.branch_name }}
50+
is_main_branch: ${{ steps.params.outputs.is_main_branch }}
51+
enable_frontend: ${{ steps.params.outputs.enable_frontend }}
52+
enable_backend: ${{ steps.params.outputs.enable_backend }}
53+
54+
steps:
55+
- name: Set Parameters
56+
id: params
57+
run: |
58+
BRANCH_NAME="${{ github.event.inputs.branch_ref || github.ref_name }}"
59+
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
60+
61+
IS_MAIN_BRANCH=$(echo "$BRANCH_NAME" == "main" || echo "$BRANCH_NAME" == "refs/heads/main")
62+
echo "is_main_branch=$IS_MAIN_BRANCH" >> $GITHUB_OUTPUT
63+
64+
# Determine resource_prefix
65+
if [[ "$IS_MAIN_BRANCH" == "true" ]]; then
66+
RESOURCE_PREFIX="prod-"
67+
elif [[ -n "${{ github.event.inputs.resource_prefix }}" ]]; then
68+
RESOURCE_PREFIX="${{ github.event.inputs.resource_prefix }}-"
69+
elif [[ -n "$BRANCH_NAME" ]]; then
70+
SANITIZED_BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9-]/-/g' | sed 's/^-*//;s/-*$//' | tr '[:upper:]' '[:lower:]')
71+
RESOURCE_PREFIX="${SANITIZED_BRANCH_NAME:0:10}-" # Max 10 chars from branch + hyphen
72+
else
73+
RESOURCE_PREFIX="dev-"
74+
fi
75+
echo "resource_prefix=$RESOURCE_PREFIX" >> $GITHUB_OUTPUT
76+
77+
# Determine Terraform action (plan for PRs, apply for push/dispatch)
78+
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
79+
TF_ACTION="plan"
80+
else
81+
TF_ACTION="apply"
82+
fi
83+
echo "tf_action=$TF_ACTION" >> $GITHUB_OUTPUT
84+
85+
# Determine frontend/backend deployment based on inputs or defaults
86+
if [[ "$IS_MAIN_BRANCH" == "true" ]]; then
87+
CURRENT_ENABLE_FRONTEND=true
88+
CURRENT_ENABLE_BACKEND=true
89+
else
90+
# Use workflow input if provided, otherwise use env var default
91+
if [[ -n "${{ github.event.inputs.enable_frontend }}" ]]; then
92+
CURRENT_ENABLE_FRONTEND=${{ github.event.inputs.enable_frontend }}
93+
else
94+
CURRENT_ENABLE_FRONTEND=${{ env.ENABLE_FRONTEND }}
95+
fi
96+
if [[ -n "${{ github.event.inputs.enable_backend }}" ]]; then
97+
CURRENT_ENABLE_BACKEND=${{ github.event.inputs.enable_backend }}
98+
else
99+
CURRENT_ENABLE_BACKEND=${{ env.ENABLE_BACKEND }}
100+
fi
101+
fi
102+
echo "enable_frontend=$CURRENT_ENABLE_FRONTEND" >> $GITHUB_OUTPUT
103+
echo "enable_backend=$CURRENT_ENABLE_BACKEND" >> $GITHUB_OUTPUT
104+
105+
terraform:
106+
name: Terraform Infrastructure
107+
runs-on: ubuntu-latest
108+
needs: determine_params
109+
environment: ${{ needs.determine_params.outputs.is_main_branch == 'true' && 'production' || 'development' }}
110+
outputs:
111+
load_balancer_dns: ${{ steps.apply_terraform.outputs.load_balancer_dns }}
112+
db_endpoint: ${{ steps.apply_terraform.outputs.db_endpoint }}
113+
114+
steps:
115+
- name: Checkout code
116+
uses: actions/checkout@v4
117+
with:
118+
ref: ${{ needs.determine_params.outputs.branch_name }}
119+
120+
- name: Configure AWS credentials
121+
uses: aws-actions/configure-aws-credentials@v4
122+
with:
123+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
124+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
125+
aws-region: ${{ env.AWS_REGION }}
126+
127+
- name: Setup Terraform
128+
uses: hashicorp/setup-terraform@v3
129+
with:
130+
terraform_version: ${{ env.TF_VERSION }}
131+
132+
- name: Terraform Init
133+
id: init
134+
working-directory: ./terraform
135+
run: terraform init
136+
137+
- name: Terraform Plan
138+
id: plan
139+
working-directory: ./terraform
140+
run: |
141+
terraform plan \
142+
-var="aws_region=${{ env.AWS_REGION }}" \
143+
-var="resource_prefix=${{ needs.determine_params.outputs.resource_prefix }}" \
144+
-var="key_name=${{ secrets.AWS_KEY_PAIR_NAME }}" \
145+
-var="db_password=${{ secrets.DB_PASSWORD }}" \
146+
-var="enable_frontend=${{ needs.determine_params.outputs.enable_frontend }}" \
147+
-var="enable_backend=${{ needs.determine_params.outputs.enable_backend }}" \
148+
-var="common_tags={Project=\"team-1-hr-app\", Environment=\"${{ needs.determine_params.outputs.is_main_branch == 'true' && 'production' || 'development' }}\", ManagedBy=\"terraform\", Branch=\"${{ needs.determine_params.outputs.branch_name }}\"}" \
149+
-out=tfplan
150+
151+
- name: Terraform Apply
152+
id: apply_terraform
153+
if: needs.determine_params.outputs.tf_action == 'apply' && (needs.determine_params.outputs.is_main_branch == 'true' || github.event_name == 'workflow_dispatch')
154+
working-directory: ./terraform
155+
run: |
156+
terraform apply -auto-approve tfplan
157+
echo "load_balancer_dns=$(terraform output -raw ec2_load_balancer_dns)" >> $GITHUB_OUTPUT
158+
echo "db_endpoint=$(terraform output -raw rds_endpoint)" >> $GITHUB_OUTPUT
159+
160+
ansible_deploy:
161+
name: Deploy Application with Ansible
162+
runs-on: ubuntu-latest
163+
needs: [determine_params, terraform]
164+
if: needs.determine_params.outputs.tf_action == 'apply' && (needs.determine_params.outputs.is_main_branch == 'true' || github.event_name == 'workflow_dispatch')
165+
environment: ${{ needs.determine_params.outputs.is_main_branch == 'true' && 'production' || 'development' }}
166+
167+
steps:
168+
- name: Checkout code
169+
uses: actions/checkout@v4
170+
with:
171+
ref: ${{ needs.determine_params.outputs.branch_name }}
172+
173+
- name: Setup Python
174+
uses: actions/setup-python@v5
175+
with:
176+
python-version: ${{ env.PYTHON_VERSION }}
177+
178+
- name: Install Ansible and dependencies
179+
run: |
180+
pip install ansible==${{ env.ANSIBLE_VERSION }}
181+
pip install boto3 botocore # For EC2 dynamic inventory if used, or AWS modules
182+
183+
- name: Configure AWS credentials (for Ansible AWS modules if needed)
184+
uses: aws-actions/configure-aws-credentials@v4
185+
with:
186+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
187+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
188+
aws-region: ${{ env.AWS_REGION }}
189+
190+
- name: Set up SSH key for Ansible
191+
uses: webfactory/ssh-agent@v0.9.0
192+
with:
193+
ssh-private-key: ${{ secrets.ANSIBLE_SSH_PRIVATE_KEY }} # Store your EC2 key pair's private key
194+
195+
# This step assumes you have an EC2 instance to deploy to.
196+
# The public IP can be an output from Terraform, or use dynamic inventory.
197+
# For simplicity, using Terraform output. This requires instance to be ready.
198+
- name: Create Ansible Inventory
199+
run: |
200+
echo "[ec2_instances]" > inventory.ini
201+
# This needs the public IP of an instance. ALB DNS is for users, not direct SSH.
202+
# Terraform output for individual instance IPs would be needed if not using dynamic inventory.
203+
# For now, this is a placeholder. Ansible usually targets instances in ASG via dynamic inventory or known IPs.
204+
# Let's assume we need to get the IP of an instance from the ASG, which is non-trivial here directly.
205+
# Placeholder: Use ALB DNS for now, though Ansible connects to EC2 IPs.
206+
echo "${{ needs.terraform.outputs.load_balancer_dns }} ansible_user=ec2-user" >> inventory.ini
207+
echo "Warning: Ansible inventory currently uses ALB DNS as a placeholder. Needs actual EC2 IP(s)."
208+
209+
- name: Run Ansible playbook
210+
working-directory: ./ansible # Assuming playbook is in ansible/playbooks
211+
env:
212+
ANSIBLE_HOST_KEY_CHECKING: "False"
213+
run: |
214+
ansible-playbook -i ../inventory.ini playbooks/deploy.yml \
215+
-e "resource_prefix=${{ needs.determine_params.outputs.resource_prefix }}" \
216+
-e "enable_frontend=${{ needs.determine_params.outputs.enable_frontend }}" \
217+
-e "enable_backend=${{ needs.determine_params.outputs.enable_backend }}" \
218+
-e "db_endpoint=${{ needs.terraform.outputs.db_endpoint }}" \
219+
-e "db_password=${{ secrets.DB_PASSWORD }}" \
220+
-e "git_repo_url=https://github.com/${{ github.repository }}.git" \
221+
-e "git_branch=${{ needs.determine_params.outputs.branch_name }}"
222+
# Add other necessary vars for your playbook, like db_user, db_name from secrets/vars
223+
224+
notify_failure:
225+
name: Notify on Failure
226+
runs-on: ubuntu-latest
227+
needs: [terraform, ansible_deploy]
228+
if: failure() && (needs.determine_params.outputs.is_main_branch == 'true' || github.event_name == 'workflow_dispatch')
229+
steps:
230+
- name: Notify deployment failure
231+
run: echo "AWS Deployment for ${{ needs.determine_params.outputs.resource_prefix }} on branch ${{ needs.determine_params.outputs.branch_name }} FAILED!"

0 commit comments

Comments
 (0)