Skip to content

Commit 66112c0

Browse files
authored
Merge pull request #19 from buildrun-tech/diario/dia-15
infra(day 15): updates ecs desired count to one
2 parents f6e4da8 + 2f2329d commit 66112c0

16 files changed

Lines changed: 259 additions & 21 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Frontend runtime config
2+
description: >
3+
Lê os outputs do Terraform do ambiente e gera dist/config.js
4+
(window.__APP_CONFIG__) para o mesmo dist/ servir dev e prod sem rebuild.
5+
Falha se algum valor obrigatório vier vazio/null: sem config.js no bucket o
6+
CloudFront devolve index.html (custom_error_response) e o app quebra com SyntaxError.
7+
Requer credenciais AWS já configuradas no job e TF_STATE_BUCKET / TF_STATE_REGION no env.
8+
9+
inputs:
10+
environment:
11+
description: dev | prod
12+
required: true
13+
14+
outputs:
15+
frontend_bucket_name:
16+
value: ${{ steps.tf.outputs.frontend_bucket_name }}
17+
cloudfront_distribution_id:
18+
value: ${{ steps.tf.outputs.cloudfront_distribution_id }}
19+
20+
runs:
21+
using: composite
22+
steps:
23+
- name: Read Terraform Outputs
24+
id: tf
25+
uses: ./.github/actions/terraform-outputs
26+
with:
27+
environment: ${{ inputs.environment }}
28+
- name: Generate config.js
29+
shell: bash
30+
env:
31+
API_URL: ${{ steps.tf.outputs.api_url }}
32+
COGNITO_AUTHORITY: ${{ steps.tf.outputs.cognito_authority }}
33+
COGNITO_CLIENT_ID: ${{ steps.tf.outputs.cognito_client_id }}
34+
COGNITO_USER_POOL_ID: ${{ steps.tf.outputs.cognito_user_pool_id }}
35+
CLOUDFRONT_DOMAIN: ${{ steps.tf.outputs.cloudfront_domain }}
36+
FRONTEND_BUCKET_NAME: ${{ steps.tf.outputs.frontend_bucket_name }}
37+
CLOUDFRONT_DISTRIBUTION_ID: ${{ steps.tf.outputs.cloudfront_distribution_id }}
38+
run: |
39+
set -euo pipefail
40+
for key in API_URL COGNITO_AUTHORITY COGNITO_CLIENT_ID COGNITO_USER_POOL_ID CLOUDFRONT_DOMAIN \
41+
FRONTEND_BUCKET_NAME CLOUDFRONT_DISTRIBUTION_ID; do
42+
value="${!key}"
43+
if [ -z "$value" ] || [ "$value" = "null" ]; then
44+
echo "::error::Output do Terraform ausente para $key (ambiente ${{ inputs.environment }})."
45+
exit 1
46+
fi
47+
done
48+
# jq -n escapa os valores como JSON válido (JSON é JS válido)
49+
json=$(jq -n \
50+
--arg apiBaseUrl "$API_URL" \
51+
--arg cognitoAuthority "$COGNITO_AUTHORITY" \
52+
--arg cognitoClientId "$COGNITO_CLIENT_ID" \
53+
--arg cognitoUserPoolId "$COGNITO_USER_POOL_ID" \
54+
--arg cognitoRedirectUri "https://$CLOUDFRONT_DOMAIN/" \
55+
'$ARGS.named')
56+
echo "window.__APP_CONFIG__ = $json" > dist/config.js
57+
cat dist/config.js

‎.github/workflows/frontend.yml‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ name: frontend
55
# push develop = dev: build, guarda dist/ como artifact (`frontend-dist-<sha>`) + deploy S3/CloudFront.
66
# push main = prod: reusa o dist/ do run de develop pro mesmo sha (sem rebuild) + deploy S3/CloudFront.
77
# Bucket/distribuição vêm de `terraform output` (infra/, add-terraform-infra), não de repository variables.
8+
# Config de runtime (Cognito/API) também: deploy gera dist/config.js por ambiente (frontend-runtime-config).
89

910
on:
1011
workflow_call:
@@ -91,13 +92,18 @@ jobs:
9192
with:
9293
role-to-assume: ${{ env.AWS_ROLE_ARN }}
9394
aws-region: ${{ env.AWS_REGION }}
94-
- name: Read Terraform Outputs
95+
- name: Generate Runtime Config
9596
id: tf
96-
uses: ./.github/actions/terraform-outputs
97+
uses: ./.github/actions/frontend-runtime-config
9798
with:
9899
environment: dev
100+
# config.js fora do sync: --exclude também protege de --delete, sem janela sem config
99101
- name: Sync to S3
100-
run: aws s3 sync dist "s3://${{ steps.tf.outputs.frontend_bucket_name }}" --delete
102+
run: aws s3 sync dist "s3://${{ steps.tf.outputs.frontend_bucket_name }}" --delete --exclude config.js
103+
- name: Upload Runtime Config (no-cache)
104+
run: |
105+
aws s3 cp dist/config.js "s3://${{ steps.tf.outputs.frontend_bucket_name }}/config.js" \
106+
--cache-control no-cache --content-type application/javascript
101107
- name: Invalidate CloudFront Cache
102108
run: |
103109
aws cloudfront create-invalidation \
@@ -152,13 +158,18 @@ jobs:
152158
with:
153159
role-to-assume: ${{ env.AWS_ROLE_ARN }}
154160
aws-region: ${{ env.AWS_REGION }}
155-
- name: Read Terraform Outputs
161+
- name: Generate Runtime Config
156162
id: tf
157-
uses: ./.github/actions/terraform-outputs
163+
uses: ./.github/actions/frontend-runtime-config
158164
with:
159165
environment: prod
166+
# config.js fora do sync: --exclude também protege de --delete, sem janela sem config
160167
- name: Sync to S3
161-
run: aws s3 sync dist "s3://${{ steps.tf.outputs.frontend_bucket_name }}" --delete
168+
run: aws s3 sync dist "s3://${{ steps.tf.outputs.frontend_bucket_name }}" --delete --exclude config.js
169+
- name: Upload Runtime Config (no-cache)
170+
run: |
171+
aws s3 cp dist/config.js "s3://${{ steps.tf.outputs.frontend_bucket_name }}/config.js" \
172+
--cache-control no-cache --content-type application/javascript
162173
- name: Invalidate CloudFront Cache
163174
run: |
164175
aws cloudfront create-invalidation \

‎.github/workflows/pipeline.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
- '.github/workflows/frontend.yml'
5252
- '.github/workflows/pipeline.yml'
5353
- '.github/actions/terraform-outputs/**'
54+
- '.github/actions/frontend-runtime-config/**'
5455
5556
infra:
5657
name: infra

‎app/frontend/index.html‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
})()
1616
</script>
1717
<div id="root"></div>
18+
<script src="/config.js"></script>
1819
<script type="module" src="/src/main.tsx"></script>
1920
</body>
2021
</html>

‎app/frontend/src/api/client.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { config } from '../config'
12
import type { ApiErrorBody } from './types'
23

3-
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL
4+
const API_BASE_URL = config.apiBaseUrl
45

56
export class ApiError extends Error {
67
status: number

‎app/frontend/src/auth/directAuth.ts‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,25 @@ import {
44
CognitoUserPool,
55
CognitoUserSession,
66
} from 'amazon-cognito-identity-js'
7+
import { config } from '../config'
78

89
const SESSION_STORAGE_KEY = 'notebooklm.directAuth.session'
910

1011
// floci não valida o conteúdo do código de confirmação — qualquer valor confirma o usuário
1112
const DUMMY_CONFIRMATION_CODE = '000000'
1213

13-
const userPool = new CognitoUserPool({
14-
UserPoolId: import.meta.env.VITE_COGNITO_USER_POOL_ID,
15-
ClientId: import.meta.env.VITE_COGNITO_CLIENT_ID,
16-
endpoint: import.meta.env.VITE_COGNITO_ENDPOINT,
17-
})
14+
// lazy: construtor lança sem UserPoolId/ClientId — instanciar no import derrubaria o app
15+
// em ambientes sem direct auth (CloudFront/AWS usa só Hosted UI)
16+
let userPool: CognitoUserPool | undefined
17+
18+
function getUserPool(): CognitoUserPool {
19+
userPool ??= new CognitoUserPool({
20+
UserPoolId: config.cognitoUserPoolId,
21+
ClientId: config.cognitoClientId,
22+
endpoint: import.meta.env.VITE_COGNITO_ENDPOINT,
23+
})
24+
return userPool
25+
}
1826

1927
export interface DirectAuthSession {
2028
accessToken: string
@@ -44,7 +52,7 @@ export function clearStoredSession() {
4452
}
4553

4654
export function signIn(email: string, password: string): Promise<DirectAuthSession> {
47-
const cognitoUser = new CognitoUser({ Username: email, Pool: userPool })
55+
const cognitoUser = new CognitoUser({ Username: email, Pool: getUserPool() })
4856
const authDetails = new AuthenticationDetails({ Username: email, Password: password })
4957

5058
return new Promise((resolve, reject) => {
@@ -61,13 +69,13 @@ export function signIn(email: string, password: string): Promise<DirectAuthSessi
6169

6270
export function signUp(email: string, password: string): Promise<void> {
6371
return new Promise((resolve, reject) => {
64-
userPool.signUp(email, password, [], [], (err) => {
72+
getUserPool().signUp(email, password, [], [], (err) => {
6573
if (err) {
6674
reject(err)
6775
return
6876
}
6977

70-
const cognitoUser = new CognitoUser({ Username: email, Pool: userPool })
78+
const cognitoUser = new CognitoUser({ Username: email, Pool: getUserPool() })
7179
cognitoUser.confirmRegistration(DUMMY_CONFIRMATION_CODE, true, (confirmErr) => {
7280
if (confirmErr) {
7381
reject(confirmErr)

‎app/frontend/src/auth/oidcConfig.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { AuthProviderProps } from 'react-oidc-context'
2+
import { config } from '../config'
23

34
export const oidcConfig: AuthProviderProps = {
4-
authority: import.meta.env.VITE_COGNITO_AUTHORITY,
5-
client_id: import.meta.env.VITE_COGNITO_CLIENT_ID,
6-
redirect_uri: import.meta.env.VITE_COGNITO_REDIRECT_URI,
5+
authority: config.cognitoAuthority,
6+
client_id: config.cognitoClientId,
7+
redirect_uri: config.cognitoRedirectUri,
78
response_type: 'code',
89
scope: 'openid email profile',
910
onSigninCallback: () => {

‎app/frontend/src/config.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// window.__APP_CONFIG__ vem de /config.js, gerado no deploy a partir dos outputs do Terraform
2+
// (mesmo dist/ serve dev e prod). Sem ele (dev local, e2e), cai no .env via import.meta.env.
3+
interface AppConfig {
4+
apiBaseUrl: string
5+
cognitoAuthority: string
6+
cognitoClientId: string
7+
cognitoUserPoolId: string
8+
cognitoRedirectUri: string
9+
}
10+
11+
declare global {
12+
interface Window {
13+
__APP_CONFIG__?: Partial<AppConfig>
14+
}
15+
}
16+
17+
const runtime = window.__APP_CONFIG__ ?? {}
18+
19+
export const config: AppConfig = {
20+
apiBaseUrl: runtime.apiBaseUrl ?? import.meta.env.VITE_API_BASE_URL,
21+
cognitoAuthority: runtime.cognitoAuthority ?? import.meta.env.VITE_COGNITO_AUTHORITY,
22+
cognitoClientId: runtime.cognitoClientId ?? import.meta.env.VITE_COGNITO_CLIENT_ID,
23+
cognitoUserPoolId: runtime.cognitoUserPoolId ?? import.meta.env.VITE_COGNITO_USER_POOL_ID,
24+
cognitoRedirectUri: runtime.cognitoRedirectUri ?? import.meta.env.VITE_COGNITO_REDIRECT_URI,
25+
}

‎app/frontend/src/pages/WorkspacePage.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Button from '../components/ui/Button'
1515
import Input from '../components/ui/Input'
1616
import Card from '../components/ui/Card'
1717
import { ApiError } from '../api/client'
18+
import { config } from '../config'
1819
import { IconArrowLeft, IconFile, IconPlus, IconSend, IconSpinner, IconTrash, IconUpload } from '../components/icons'
1920

2021
const PENDING_STATUSES = new Set(['PENDING', 'PROCESSING'])
@@ -24,7 +25,7 @@ interface ChatMessage extends ConversationMessage {
2425
failed?: boolean
2526
}
2627

27-
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL
28+
const API_BASE_URL = config.apiBaseUrl
2829

2930
export default function WorkspacePage() {
3031
const { notebookId } = useParams<{ notebookId: string }>()

‎infra/envs/dev/terraform.tfvars‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ rds_multi_az = false
1010

1111
task_cpu = "512"
1212
task_memory = "1024"
13-
desired_count = 0 # sem imagem publicada no primeiro apply
13+
desired_count = 1 # sem imagem publicada no primeiro apply
1414
container_port = 8080
1515

1616
deletion_protection = false

0 commit comments

Comments
 (0)