Skip to content

Commit 1e72bb9

Browse files
committed
init
0 parents  commit 1e72bb9

32 files changed

Lines changed: 3299 additions & 0 deletions

.env.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Database Configuration
2+
POSTGRES_USER=financeuser
3+
POSTGRES_PASSWORD=financepass
4+
POSTGRES_DB=financedb
5+
6+
# Application Configuration
7+
STORAGE=postgres
8+
DATABASE_URL=postgres://financeuser:financepass@postgres:5432/financedb?sslmode=disable
9+
HTTP_ADDR=:8080

.github/PIPELINE_SETUP.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# 🚀 Pipeline CI/CD - Configuração
2+
3+
## Pré-requisitos na EC2
4+
5+
### 1. Preparar diretório da aplicação
6+
```bash
7+
sudo mkdir -p /opt/finance-tracker
8+
sudo chown ec2-user:ec2-user /opt/finance-tracker
9+
mv ~/finance-tracker /opt/finance-tracker/
10+
mv ~/finance-app.env /opt/finance-tracker/
11+
chmod 600 /opt/finance-tracker/finance-app.env
12+
```
13+
14+
### 2. Atualizar serviço systemd
15+
```bash
16+
sudo nano /etc/systemd/system/finance-tracker.service
17+
```
18+
19+
Conteúdo:
20+
```ini
21+
[Unit]
22+
Description=Finance Tracker API
23+
After=network.target
24+
25+
[Service]
26+
Type=simple
27+
User=ec2-user
28+
WorkingDirectory=/opt/finance-tracker
29+
EnvironmentFile=/opt/finance-tracker/finance-app.env
30+
ExecStart=/opt/finance-tracker/finance-tracker
31+
Restart=on-failure
32+
RestartSec=5
33+
StandardOutput=append:/opt/finance-tracker/finance-tracker.log
34+
StandardError=append:/opt/finance-tracker/finance-tracker.log
35+
36+
[Install]
37+
WantedBy=multi-user.target
38+
```
39+
40+
```bash
41+
sudo systemctl daemon-reload
42+
sudo systemctl restart finance-tracker
43+
sudo systemctl enable finance-tracker
44+
```
45+
46+
---
47+
48+
## Configurar Chaves SSH
49+
50+
### 1. Gerar chave SSH (no seu computador)
51+
```bash
52+
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/finance-tracker-deploy
53+
```
54+
55+
### 2. Adicionar chave pública na EC2
56+
```bash
57+
# Ver chave pública
58+
cat ~/.ssh/finance-tracker-deploy.pub
59+
60+
# Conectar na EC2 e adicionar
61+
ssh -i sua-chave.pem ec2-user@SEU-IP-EC2
62+
nano ~/.ssh/authorized_keys
63+
# Cole a chave pública no final
64+
# Salve: Ctrl+O, Enter, Ctrl+X
65+
66+
chmod 600 ~/.ssh/authorized_keys
67+
```
68+
69+
### 3. Testar conexão
70+
```bash
71+
ssh -i ~/.ssh/finance-tracker-deploy ec2-user@SEU-IP-EC2
72+
```
73+
74+
---
75+
76+
## Configurar GitHub Secrets
77+
78+
GitHub → Repositório → Settings → Secrets and variables → Actions → New repository secret
79+
80+
Adicione:
81+
82+
| Name | Value |
83+
|------|-------|
84+
| **EC2_HOST** | IP ou DNS da EC2 (ex: `3.85.123.45`) |
85+
| **EC2_USER** | `ec2-user` |
86+
| **EC2_SSH_KEY** | Conteúdo completo de `~/.ssh/finance-tracker-deploy` |
87+
88+
Para copiar a chave privada:
89+
```bash
90+
cat ~/.ssh/finance-tracker-deploy
91+
# Copie TUDO (incluindo BEGIN e END)
92+
```
93+
94+
---
95+
96+
## Como usar o Pipeline
97+
98+
### Deploy Automático
99+
- Faça push para a branch `main`
100+
- O pipeline será executado automaticamente
101+
- Acompanhe em: GitHub → Actions
102+
103+
### Deploy Manual
104+
- GitHub → Actions → Deploy to EC2
105+
- Clique em "Run workflow"
106+
- Selecione a branch → "Run workflow"
107+
108+
---
109+
110+
## Fluxo do Pipeline
111+
112+
1. ✅ Checkout do código
113+
2. ✅ Setup Go 1.22
114+
3. ✅ Executar testes (`go test ./...`)
115+
4. ✅ Build do binário Linux AMD64
116+
5. ✅ Upload via SCP para EC2
117+
6. ✅ Parar serviço
118+
7. ✅ Backup da versão anterior
119+
8. ✅ Instalar nova versão
120+
9. ✅ Iniciar serviço
121+
10. ✅ Health check (`/health`)
122+
11. ✅ Rollback automático se falhar
123+
124+
---
125+
126+
## Troubleshooting
127+
128+
### Ver logs da aplicação na EC2
129+
```bash
130+
sudo journalctl -u finance-tracker -f
131+
tail -f /opt/finance-tracker/finance-tracker.log
132+
```
133+
134+
### Ver status do serviço
135+
```bash
136+
sudo systemctl status finance-tracker
137+
```
138+
139+
### Fazer rollback manual
140+
```bash
141+
sudo systemctl stop finance-tracker
142+
sudo mv /opt/finance-tracker/finance-tracker.backup /opt/finance-tracker/finance-tracker
143+
sudo systemctl start finance-tracker
144+
```
145+
146+
### Testar conexão SSH do GitHub
147+
```bash
148+
ssh -i ~/.ssh/finance-tracker-deploy ec2-user@SEU-IP-EC2 "echo 'Conexão OK!'"
149+
```
150+
151+
---
152+
153+
## Melhorias Futuras
154+
155+
- [ ] Notificações no Slack/Discord
156+
- [ ] Deploy com Blue-Green
157+
- [ ] Testes de integração
158+
- [ ] Versionamento de releases
159+
- [ ] Deploy em múltiplas instâncias
160+
- [ ] Métricas e monitoramento

.github/workflows/deploy-asg.yml

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
name: Deploy to Auto Scaling Group
2+
3+
on:
4+
push:
5+
branches:
6+
- feature/configuracao
7+
workflow_dispatch:
8+
9+
permissions:
10+
id-token: write # Necessário para OIDC
11+
contents: read
12+
13+
env:
14+
AWS_REGION: us-east-1
15+
S3_BUCKET: finance-tracker-releases # Criar este bucket
16+
APP_NAME: finance-tracker
17+
ASG_NAME: finance-tracker-asg
18+
LAUNCH_TEMPLATE_NAME: finance-tracker-launch-template
19+
20+
jobs:
21+
deploy:
22+
name: Build and Deploy to ASG
23+
runs-on: ubuntu-latest
24+
25+
steps:
26+
# 1. Checkout do código
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
30+
# 2. Configurar AWS credentials via OIDC
31+
- name: Configure AWS credentials
32+
uses: aws-actions/configure-aws-credentials@v4
33+
with:
34+
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
35+
aws-region: ${{ env.AWS_REGION }}
36+
37+
# 3. Setup Go
38+
- name: Setup Go
39+
uses: actions/setup-go@v5
40+
with:
41+
go-version: '1.25.3'
42+
43+
# 4. Executar testes
44+
- name: Run tests
45+
run: |
46+
go mod download
47+
go test ./... -v
48+
49+
# 5. Build do binário para Linux AMD64
50+
- name: Build binary
51+
run: |
52+
GOOS=linux GOARCH=amd64 go build -o finance-tracker ./cmd/api
53+
54+
# 6. Gerar versão única (hash do commit)
55+
- name: Generate version
56+
id: version
57+
run: |
58+
VERSION="${GITHUB_SHA:0:7}"
59+
echo "version=$VERSION" >> $GITHUB_OUTPUT
60+
echo "📦 Version: $VERSION"
61+
62+
# 7. Upload binário para S3
63+
- name: Upload binary to S3
64+
run: |
65+
aws s3 cp finance-tracker \
66+
s3://${{ env.S3_BUCKET }}/releases/${{ steps.version.outputs.version }}/finance-tracker \
67+
--region ${{ env.AWS_REGION }}
68+
69+
echo "✅ Binário enviado para S3"
70+
71+
# 8. Preparar User Data Script
72+
- name: Prepare User Data
73+
run: |
74+
# Substituir placeholders no user-data.sh
75+
sed -i "s|BUCKET_NAME|${{ env.S3_BUCKET }}|g" infra/user-data.sh
76+
sed -i "s|APP_VERSION|${{ steps.version.outputs.version }}|g" infra/user-data.sh
77+
sed -i "s|DATABASE_URL_PLACEHOLDER|${{ secrets.DATABASE_URL }}|g" infra/user-data.sh
78+
79+
# Codificar em base64
80+
USER_DATA=$(cat infra/user-data.sh | base64 -w 0)
81+
echo "USER_DATA=$USER_DATA" >> $GITHUB_ENV
82+
83+
# 9. Criar nova versão do Launch Template
84+
- name: Create Launch Template version
85+
id: lt_version
86+
run: |
87+
NEW_VERSION=$(aws ec2 create-launch-template-version \
88+
--launch-template-name ${{ env.LAUNCH_TEMPLATE_NAME }} \
89+
--source-version '$Latest' \
90+
--launch-template-data "{
91+
\"UserData\": \"$USER_DATA\",
92+
\"TagSpecifications\": [{
93+
\"ResourceType\": \"instance\",
94+
\"Tags\": [
95+
{\"Key\": \"Name\", \"Value\": \"finance-tracker-${{ steps.version.outputs.version }}\"},
96+
{\"Key\": \"Version\", \"Value\": \"${{ steps.version.outputs.version }}\"},
97+
{\"Key\": \"DeployedBy\", \"Value\": \"GitHub-Actions\"},
98+
{\"Key\": \"CommitSHA\", \"Value\": \"${{ github.sha }}\"}
99+
]
100+
}]
101+
}" \
102+
--query 'LaunchTemplateVersion.VersionNumber' \
103+
--output text)
104+
105+
echo "lt_version=$NEW_VERSION" >> $GITHUB_OUTPUT
106+
echo "🚀 Launch Template versão $NEW_VERSION criada"
107+
108+
# 10. Atualizar Auto Scaling Group
109+
- name: Update Auto Scaling Group
110+
run: |
111+
aws autoscaling update-auto-scaling-group \
112+
--auto-scaling-group-name ${{ env.ASG_NAME }} \
113+
--launch-template "LaunchTemplateName=${{ env.LAUNCH_TEMPLATE_NAME }},Version=${{ steps.lt_version.outputs.lt_version }}"
114+
115+
echo "✅ Auto Scaling Group atualizado"
116+
117+
# 11. Iniciar Instance Refresh (Rolling Update)
118+
- name: Start Instance Refresh
119+
id: refresh
120+
run: |
121+
REFRESH_ID=$(aws autoscaling start-instance-refresh \
122+
--auto-scaling-group-name ${{ env.ASG_NAME }} \
123+
--preferences '{
124+
"MinHealthyPercentage": 50,
125+
"InstanceWarmup": 60,
126+
"CheckpointPercentages": [50, 100],
127+
"CheckpointDelay": 30
128+
}' \
129+
--query 'InstanceRefreshId' \
130+
--output text)
131+
132+
echo "refresh_id=$REFRESH_ID" >> $GITHUB_OUTPUT
133+
echo "🔄 Instance Refresh iniciado: $REFRESH_ID"
134+
135+
# 12. Aguardar conclusão do Instance Refresh
136+
- name: Wait for Instance Refresh
137+
run: |
138+
echo "⏳ Aguardando Instance Refresh concluir..."
139+
140+
while true; do
141+
STATUS=$(aws autoscaling describe-instance-refreshes \
142+
--auto-scaling-group-name ${{ env.ASG_NAME }} \
143+
--instance-refresh-ids ${{ steps.refresh.outputs.refresh_id }} \
144+
--query 'InstanceRefreshes[0].Status' \
145+
--output text)
146+
147+
echo "Status atual: $STATUS"
148+
149+
if [ "$STATUS" == "Successful" ]; then
150+
echo "✅ Instance Refresh concluído com sucesso!"
151+
break
152+
elif [ "$STATUS" == "Failed" ] || [ "$STATUS" == "Cancelled" ]; then
153+
echo "❌ Instance Refresh falhou!"
154+
exit 1
155+
fi
156+
157+
sleep 30
158+
done
159+
160+
# 13. Verificar saúde do Target Group
161+
- name: Check Target Group Health
162+
run: |
163+
TARGET_GROUP_ARN=$(aws autoscaling describe-auto-scaling-groups \
164+
--auto-scaling-group-names ${{ env.ASG_NAME }} \
165+
--query 'AutoScalingGroups[0].TargetGroupARNs[0]' \
166+
--output text)
167+
168+
echo "🏥 Verificando saúde do Target Group..."
169+
170+
HEALTHY_COUNT=$(aws elbv2 describe-target-health \
171+
--target-group-arn $TARGET_GROUP_ARN \
172+
--query "length(TargetHealthDescriptions[?TargetHealth.State=='healthy'])" \
173+
--output text)
174+
175+
echo "✅ Instâncias saudáveis: $HEALTHY_COUNT"
176+
177+
if [ "$HEALTHY_COUNT" -lt 1 ]; then
178+
echo "❌ Nenhuma instância saudável encontrada!"
179+
exit 1
180+
fi
181+
182+
# 14. Notificação de sucesso
183+
- name: Deployment Summary
184+
if: success()
185+
run: |
186+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
187+
echo "✅ DEPLOY CONCLUÍDO COM SUCESSO!"
188+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
189+
echo "📦 Versão: ${{ steps.version.outputs.version }}"
190+
echo "🚀 Launch Template: v${{ steps.lt_version.outputs.lt_version }}"
191+
echo "🔄 Instance Refresh: ${{ steps.refresh.outputs.refresh_id }}"
192+
echo "⏰ Timestamp: $(date -u +"%Y-%m-%d %H:%M:%S UTC")"
193+
echo "👤 Deployed by: ${{ github.actor }}"
194+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
195+
196+
# 15. Rollback em caso de falha
197+
- name: Rollback on failure
198+
if: failure()
199+
run: |
200+
echo "❌ Deploy falhou! Iniciando rollback..."
201+
202+
# Cancelar instance refresh
203+
aws autoscaling cancel-instance-refresh \
204+
--auto-scaling-group-name ${{ env.ASG_NAME }} || true
205+
206+
# Voltar para versão anterior do Launch Template
207+
PREVIOUS_VERSION=$(( ${{ steps.lt_version.outputs.lt_version }} - 1 ))
208+
209+
if [ "$PREVIOUS_VERSION" -gt 0 ]; then
210+
aws ec2 modify-launch-template \
211+
--launch-template-name ${{ env.LAUNCH_TEMPLATE_NAME }} \
212+
--default-version $PREVIOUS_VERSION
213+
214+
echo "🔙 Rollback para Launch Template v$PREVIOUS_VERSION"
215+
fi

0 commit comments

Comments
 (0)