grada-run 0.0.1 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/deploy-docs.yml +37 -0
- package/.github/workflows/iac-validation.yml +303 -0
- package/.github/workflows/publish.yml +68 -0
- package/.github/workflows/sync-bedrock-models.yml +57 -0
- package/.github/workflows/test.yml +43 -0
- package/.muserules +31 -0
- package/LICENSE +21 -0
- package/README.md +193 -3
- package/apps/docs/.astro/collections/docs.schema.json +644 -0
- package/apps/docs/.astro/content-assets.mjs +4 -0
- package/apps/docs/.astro/content-modules.mjs +4 -0
- package/apps/docs/.astro/content.d.ts +179 -0
- package/apps/docs/.astro/data-store.json +1 -0
- package/apps/docs/.astro/dev.json +14 -0
- package/apps/docs/.astro/settings.json +5 -0
- package/apps/docs/.astro/types.d.ts +2 -0
- package/apps/docs/astro.config.mjs +97 -0
- package/apps/docs/package.json +17 -0
- package/apps/docs/src/content/docs/adrs/0001-s3-native-state-locking.md +37 -0
- package/apps/docs/src/content/docs/adrs/0002-eject-mechanism-pure-iac.md +39 -0
- package/apps/docs/src/content/docs/adrs/0003-sync-ai-context-strategy.md +48 -0
- package/apps/docs/src/content/docs/adrs/0004-iac-driven-diagnostic-context.md +37 -0
- package/apps/docs/src/content/docs/adrs/0005-ecs-fargate-alb-runtime-target.md +38 -0
- package/apps/docs/src/content/docs/adrs/0006-github-oidc-no-stored-keys.md +37 -0
- package/apps/docs/src/content/docs/adrs/0007-framework-detection-with-fallback.md +37 -0
- package/apps/docs/src/content/docs/adrs/0008-secrets-names-in-git-values-in-aws.md +37 -0
- package/apps/docs/src/content/docs/adrs/0009-regenerate-with-backup-on-rerun.md +37 -0
- package/apps/docs/src/content/docs/adrs/0010-advisory-only-security-scans.md +37 -0
- package/apps/docs/src/content/docs/cli/add.md +84 -0
- package/apps/docs/src/content/docs/cli/apply.md +32 -0
- package/apps/docs/src/content/docs/cli/db.md +200 -0
- package/apps/docs/src/content/docs/cli/destroy.md +31 -0
- package/apps/docs/src/content/docs/cli/diagnose.md +37 -0
- package/apps/docs/src/content/docs/cli/doctor.md +28 -0
- package/apps/docs/src/content/docs/cli/domain.md +57 -0
- package/apps/docs/src/content/docs/cli/drift.md +40 -0
- package/apps/docs/src/content/docs/cli/eject.md +29 -0
- package/apps/docs/src/content/docs/cli/exec.md +49 -0
- package/apps/docs/src/content/docs/cli/gc.md +37 -0
- package/apps/docs/src/content/docs/cli/init.md +72 -0
- package/apps/docs/src/content/docs/cli/logs.md +39 -0
- package/apps/docs/src/content/docs/cli/rollback.md +51 -0
- package/apps/docs/src/content/docs/cli/secrets.md +73 -0
- package/apps/docs/src/content/docs/cli/sleep.md +53 -0
- package/apps/docs/src/content/docs/cli/status.md +34 -0
- package/apps/docs/src/content/docs/cli/sync-ai.md +27 -0
- package/apps/docs/src/content/docs/guides/architecture.md +87 -0
- package/apps/docs/src/content/docs/guides/aws-credentials.md +72 -0
- package/apps/docs/src/content/docs/guides/background-workers.md +45 -0
- package/apps/docs/src/content/docs/guides/cicd-pipeline.md +64 -0
- package/apps/docs/src/content/docs/guides/database-connections.md +64 -0
- package/apps/docs/src/content/docs/guides/docker-compose.md +37 -0
- package/apps/docs/src/content/docs/guides/dockerfiles.md +46 -0
- package/apps/docs/src/content/docs/guides/ephemeral-pr-previews.md +39 -0
- package/apps/docs/src/content/docs/guides/examples.md +50 -0
- package/apps/docs/src/content/docs/guides/frameworks.md +88 -0
- package/apps/docs/src/content/docs/guides/headless.md +75 -0
- package/apps/docs/src/content/docs/guides/quickstart.md +52 -0
- package/apps/docs/src/content/docs/guides/rerun-init.md +43 -0
- package/apps/docs/src/content/docs/guides/secrets-management.md +83 -0
- package/apps/docs/src/content/docs/guides/understanding-your-bill.md +63 -0
- package/apps/docs/src/content/docs/index.mdx +103 -0
- package/apps/docs/src/content/docs/migrations/astro-vercel-to-aws.md +55 -0
- package/apps/docs/src/content/docs/migrations/heroku-procfile-to-aws.md +41 -0
- package/apps/docs/src/content/docs/migrations/nextjs-vercel-to-aws.md +51 -0
- package/apps/docs/src/content/docs/migrations/sveltekit-vercel-to-aws.md +63 -0
- package/apps/docs/src/content/docs/roadmap.md +97 -0
- package/apps/docs/src/content/docs/testing-strategy.md +32 -0
- package/apps/docs/src/content.config.ts +7 -0
- package/apps/docs/src/custom.css +14 -0
- package/apps/docs/tsconfig.json +6 -0
- package/bin/cli.js +140 -0
- package/package.json +105 -6
- package/scripts/sync-bedrock-models.js +22 -0
- package/scripts/test-iac.js +261 -0
- package/specs/add-redis-sqs-bedrock.md +128 -0
- package/specs/add-storage-dynamodb.md +106 -0
- package/specs/bedrock-model-catalog.md +131 -0
- package/specs/ci-pipeline.md +17 -0
- package/specs/cost-transparency.md +115 -0
- package/specs/custom-domains-and-ses.md +153 -0
- package/specs/database-suite-expansion.md +151 -0
- package/specs/db-connect.md +69 -0
- package/specs/db-lifecycle-migrations.md +159 -0
- package/specs/dependency-aware-init.md +176 -0
- package/specs/deploy-stack-to-grada-run-rebrand.md +45 -0
- package/specs/deployment-safety.md +170 -0
- package/specs/diagnose.md +16 -0
- package/specs/docs-hub.md +16 -0
- package/specs/dx-polish.md +46 -0
- package/specs/exec.md +25 -0
- package/specs/finops-cron-drift.md +161 -0
- package/specs/gc.md +26 -0
- package/specs/integration-suite.md +16 -0
- package/specs/logs.md +32 -0
- package/specs/rollback-live-polling.md +40 -0
- package/specs/secrets-pull-audit.md +51 -0
- package/specs/serverless-lambda-target.md +133 -0
- package/specs/status.md +31 -0
- package/specs/telemetry-and-spawn-hardening.md +69 -0
- package/specs/telemetry-hardening.md +35 -0
- package/src/commands/add.js +1111 -0
- package/src/commands/apply.js +214 -0
- package/src/commands/db/backup.js +229 -0
- package/src/commands/db/connect.js +304 -0
- package/src/commands/db/enable-vector.js +344 -0
- package/src/commands/db/import.js +604 -0
- package/src/commands/db/migrate.js +477 -0
- package/src/commands/db/restore.js +361 -0
- package/src/commands/db.js +87 -0
- package/src/commands/destroy.js +217 -0
- package/src/commands/diagnose.js +460 -0
- package/src/commands/doctor.js +109 -0
- package/src/commands/domain.js +685 -0
- package/src/commands/drift.js +243 -0
- package/src/commands/eject.js +127 -0
- package/src/commands/exec.js +222 -0
- package/src/commands/gc.js +250 -0
- package/src/commands/init.js +649 -0
- package/src/commands/logs.js +256 -0
- package/src/commands/rollback.js +323 -0
- package/src/commands/secrets.js +485 -0
- package/src/commands/sleep.js +347 -0
- package/src/commands/status.js +309 -0
- package/src/commands/sync-ai.js +115 -0
- package/src/commands/wake.js +337 -0
- package/src/core/parser.js +126 -0
- package/src/core/telemetry.js +244 -0
- package/src/data/bedrock-models.json +896 -0
- package/src/utils/addons.js +126 -0
- package/src/utils/ai-rules.js +59 -0
- package/src/utils/args.js +91 -0
- package/src/utils/aws.js +178 -0
- package/src/utils/backup.js +69 -0
- package/src/utils/bedrock-catalog.js +511 -0
- package/src/utils/capabilities.js +500 -0
- package/src/utils/command.js +65 -0
- package/src/utils/db-tunnel.js +164 -0
- package/src/utils/detector.js +298 -0
- package/src/utils/dockerCompose.js +65 -0
- package/src/utils/domains.js +73 -0
- package/src/utils/ecs-runner.js +289 -0
- package/src/utils/ecs.js +92 -0
- package/src/utils/frameworks.js +55 -0
- package/src/utils/generator.js +527 -0
- package/src/utils/hcl.js +426 -0
- package/src/utils/lambda-ecr.js +185 -0
- package/src/utils/prompts.js +278 -0
- package/src/utils/rds.js +131 -0
- package/src/utils/resolvers.js +174 -0
- package/src/utils/sleep-state.js +140 -0
- package/src/utils/sleep-targets.js +139 -0
- package/src/utils/system.js +42 -0
- package/src/utils/terraform.js +70 -0
- package/src/utils/visualizer.js +381 -0
- package/src/utils/warnings.js +49 -0
- package/templates/README.md +150 -0
- package/templates/docker/django.Dockerfile +40 -0
- package/templates/docker/go.Dockerfile +23 -0
- package/templates/docker/nestjs.Dockerfile +33 -0
- package/templates/docker/nextjs.Dockerfile +55 -0
- package/templates/docker/node.Dockerfile +24 -0
- package/templates/docker/nuxt.Dockerfile +47 -0
- package/templates/docker/python.Dockerfile +38 -0
- package/templates/docker/rails.Dockerfile +59 -0
- package/templates/docker/static.Dockerfile +32 -0
- package/templates/docker/svelte.Dockerfile +52 -0
- package/templates/github/deploy-lambda.yml +120 -0
- package/templates/github/deploy.yml +138 -0
- package/templates/github/drift.yml +112 -0
- package/templates/github/preview-lambda.yml +86 -0
- package/templates/github/preview.yml +69 -0
- package/templates/github/teardown.yml +43 -0
- package/templates/terraform/addons/bedrock.tf +34 -0
- package/templates/terraform/addons/cron-lambda.tf +78 -0
- package/templates/terraform/addons/cron.tf +101 -0
- package/templates/terraform/addons/dynamodb.tf +73 -0
- package/templates/terraform/addons/redis.tf +64 -0
- package/templates/terraform/addons/s3.tf +143 -0
- package/templates/terraform/addons/ses.tf +73 -0
- package/templates/terraform/addons/sqs.tf +67 -0
- package/templates/terraform/backend.tf +22 -0
- package/templates/terraform/cloudfront-lambda.tf +80 -0
- package/templates/terraform/cloudfront.tf +80 -0
- package/templates/terraform/database-aurora-postgresql.tf +92 -0
- package/templates/terraform/database-mysql.tf +72 -0
- package/templates/terraform/database.tf +71 -0
- package/templates/terraform/main-lambda.tf +229 -0
- package/templates/terraform/main.tf +296 -0
- package/templates/terraform/network.tf +95 -0
- package/templates/terraform/oidc.tf +64 -0
- package/templates/terraform/secrets.tf +31 -0
- package/templates/terraform/worker.tf +69 -0
- package/tests/__snapshots__/generator.test.js.snap +9633 -0
- package/tests/add.test.js +2037 -0
- package/tests/ai.test.js +94 -0
- package/tests/apply.test.js +488 -0
- package/tests/args.test.js +86 -0
- package/tests/aws.test.js +244 -0
- package/tests/capabilities.test.js +307 -0
- package/tests/cli.test.js +29 -0
- package/tests/command.test.js +100 -0
- package/tests/commands-import.test.js +74 -0
- package/tests/db.test.js +2704 -0
- package/tests/destroy.test.js +391 -0
- package/tests/detector.test.js +79 -0
- package/tests/diagnose.test.js +779 -0
- package/tests/doctor.test.js +202 -0
- package/tests/domain.test.js +899 -0
- package/tests/drift.test.js +243 -0
- package/tests/ecs.test.js +130 -0
- package/tests/eject.test.js +65 -0
- package/tests/exec.test.js +380 -0
- package/tests/gc.test.js +496 -0
- package/tests/generator.test.js +794 -0
- package/tests/headless.test.js +562 -0
- package/tests/lambda-ecr.test.js +185 -0
- package/tests/logs.test.js +447 -0
- package/tests/parser.test.js +160 -0
- package/tests/rds.test.js +244 -0
- package/tests/resolvers.test.js +282 -0
- package/tests/rollback.test.js +692 -0
- package/tests/secrets.test.js +752 -0
- package/tests/sleep-wake.test.js +1016 -0
- package/tests/status.test.js +370 -0
- package/tests/system.test.js +70 -0
- package/tests/telemetry.test.js +520 -0
- package/tests/terraform.test.js +84 -0
- package/tests/visualizer.test.js +496 -0
- package/vitest.config.js +9 -0
- package/index.js +0 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# --- Stage 1: Build ---
|
|
2
|
+
FROM node:22-alpine AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY package*.json ./
|
|
5
|
+
RUN npm ci
|
|
6
|
+
COPY . .
|
|
7
|
+
RUN npm run build
|
|
8
|
+
|
|
9
|
+
# --- Stage 2: Production ---
|
|
10
|
+
FROM node:22-alpine
|
|
11
|
+
|
|
12
|
+
# 1. DevSecOps: Patch Alpine OS
|
|
13
|
+
RUN apk update && apk upgrade --no-cache
|
|
14
|
+
|
|
15
|
+
ENV NODE_ENV=production
|
|
16
|
+
WORKDIR /app
|
|
17
|
+
|
|
18
|
+
# 2. Install ONLY production dependencies
|
|
19
|
+
COPY --chown=node:node package*.json ./
|
|
20
|
+
RUN npm ci --omit=dev && npm cache clean --force
|
|
21
|
+
|
|
22
|
+
# 3. DevSecOps: Nuke all package managers to eliminate base-image CVEs
|
|
23
|
+
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx \
|
|
24
|
+
/opt/yarn-* /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
25
|
+
/usr/local/lib/node_modules/corepack /usr/local/bin/corepack
|
|
26
|
+
|
|
27
|
+
# 4. Copy the compiled application
|
|
28
|
+
COPY --chown=node:node --from=builder /app/dist ./dist
|
|
29
|
+
|
|
30
|
+
USER node
|
|
31
|
+
# Expose the port defined by Terraform
|
|
32
|
+
EXPOSE {{PORT}}
|
|
33
|
+
CMD ["node", "dist/main.js"]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Stage 1: Install dependencies and build the app
|
|
2
|
+
FROM node:22-alpine AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# FIX 1: Upgrade Alpine system packages & upgrade global NPM to patch 'tar' and 'pacote' CVEs
|
|
6
|
+
RUN apk upgrade --no-cache && \
|
|
7
|
+
npm install -g npm@latest
|
|
8
|
+
|
|
9
|
+
# Copy package files and install dependencies
|
|
10
|
+
COPY package.json package-lock.json* ./
|
|
11
|
+
RUN npm ci
|
|
12
|
+
|
|
13
|
+
# Copy the rest of the application code
|
|
14
|
+
COPY . .
|
|
15
|
+
|
|
16
|
+
# Build the Next.js application
|
|
17
|
+
# (This requires output: 'standalone' in next.config.ts)
|
|
18
|
+
RUN npm run build
|
|
19
|
+
|
|
20
|
+
# Stage 2: Production environment
|
|
21
|
+
FROM node:22-alpine AS runner
|
|
22
|
+
WORKDIR /app
|
|
23
|
+
|
|
24
|
+
# FIX 2: Upgrade Alpine packages and absolutely destroy npm, yarn, and corepack
|
|
25
|
+
# to eliminate all remaining Critical/High container vulnerabilities.
|
|
26
|
+
RUN apk upgrade --no-cache && \
|
|
27
|
+
rm -rf /usr/local/lib/node_modules/npm \
|
|
28
|
+
/usr/local/bin/npm \
|
|
29
|
+
/usr/local/bin/npx \
|
|
30
|
+
/opt/yarn-* \
|
|
31
|
+
/usr/local/bin/yarn \
|
|
32
|
+
/usr/local/bin/yarnpkg \
|
|
33
|
+
/usr/local/lib/node_modules/corepack \
|
|
34
|
+
/usr/local/bin/corepack
|
|
35
|
+
|
|
36
|
+
ENV NODE_ENV=production
|
|
37
|
+
ENV PORT={{PORT}}
|
|
38
|
+
ENV HOSTNAME="0.0.0.0"
|
|
39
|
+
|
|
40
|
+
# Create an unprivileged user and group
|
|
41
|
+
RUN addgroup -g 1001 -S nodejs && \
|
|
42
|
+
adduser -S nextjs -u 1001 -G nodejs
|
|
43
|
+
|
|
44
|
+
# Copy the standalone output and assign ownership to the unprivileged user
|
|
45
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
46
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
47
|
+
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
|
48
|
+
|
|
49
|
+
# Switch to the unprivileged user before executing
|
|
50
|
+
USER nextjs
|
|
51
|
+
|
|
52
|
+
EXPOSE {{PORT}}
|
|
53
|
+
|
|
54
|
+
# Start the standalone Node.js server
|
|
55
|
+
CMD ["node", "server.js"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
FROM node:22-alpine
|
|
2
|
+
|
|
3
|
+
# 1. DevSecOps: Patch underlying Alpine OS vulnerabilities and update global npm
|
|
4
|
+
RUN apk update && apk upgrade --no-cache && \
|
|
5
|
+
npm install -g npm@latest
|
|
6
|
+
|
|
7
|
+
# 2. Set production environment (optimizes Node and prevents dev dependencies)
|
|
8
|
+
ENV NODE_ENV=production
|
|
9
|
+
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
|
|
12
|
+
# 3. Copy dependency manifests with non-root ownership
|
|
13
|
+
COPY --chown=node:node package*.json ./
|
|
14
|
+
RUN npm ci --omit=dev
|
|
15
|
+
|
|
16
|
+
# 4. Copy application code with non-root ownership
|
|
17
|
+
COPY --chown=node:node . .
|
|
18
|
+
|
|
19
|
+
# 5. DevSecOps best practice: do not run the container as root
|
|
20
|
+
USER node
|
|
21
|
+
|
|
22
|
+
EXPOSE {{PORT}}
|
|
23
|
+
|
|
24
|
+
CMD ["npm", "start"]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Stage 1: Build the Nuxt Nitro output
|
|
2
|
+
FROM node:22-alpine AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# Install native build tools required to compile C++ Node modules (like better-sqlite3)
|
|
6
|
+
RUN apk update && \
|
|
7
|
+
apk add --no-cache python3 make g++ sqlite-dev
|
|
8
|
+
|
|
9
|
+
COPY package.json package-lock.json* ./
|
|
10
|
+
RUN npm ci
|
|
11
|
+
|
|
12
|
+
# Explicitly install better-sqlite3 to satisfy Nuxt 4 / Nitro dynamic requirements
|
|
13
|
+
RUN npm install better-sqlite3
|
|
14
|
+
|
|
15
|
+
COPY . .
|
|
16
|
+
RUN npm run build
|
|
17
|
+
|
|
18
|
+
# Stage 2: Production runner
|
|
19
|
+
FROM node:22-alpine AS runner
|
|
20
|
+
WORKDIR /app
|
|
21
|
+
|
|
22
|
+
ENV NODE_ENV=production
|
|
23
|
+
ENV PORT={{PORT}}
|
|
24
|
+
ENV HOSTNAME="0.0.0.0"
|
|
25
|
+
|
|
26
|
+
# 1. Upgrade Alpine OS packages to clear OpenSSL/crypto CVEs
|
|
27
|
+
# 2. Vaporize Node package managers (npm, yarn, corepack) to clear ghost CVEs
|
|
28
|
+
RUN apk update && apk upgrade --no-cache && \
|
|
29
|
+
rm -rf /usr/local/lib/node_modules \
|
|
30
|
+
/usr/local/bin/npm \
|
|
31
|
+
/usr/local/bin/npx \
|
|
32
|
+
/usr/local/bin/yarn \
|
|
33
|
+
/usr/local/bin/yarnpkg \
|
|
34
|
+
/usr/local/bin/corepack \
|
|
35
|
+
/opt/yarn-*
|
|
36
|
+
|
|
37
|
+
# Create an unprivileged user and group
|
|
38
|
+
RUN addgroup -g 1001 -S nodejs && \
|
|
39
|
+
adduser -S nuxtjs -u 1001 -G nodejs
|
|
40
|
+
|
|
41
|
+
# Copy the standalone output and assign ownership
|
|
42
|
+
COPY --from=builder --chown=nuxtjs:nodejs /app/.output ./.output
|
|
43
|
+
|
|
44
|
+
USER nuxtjs
|
|
45
|
+
EXPOSE {{PORT}}
|
|
46
|
+
|
|
47
|
+
CMD ["node", ".output/server/index.mjs"]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
FROM python:3.12-alpine
|
|
2
|
+
|
|
3
|
+
# Prevent Python from writing .pyc files and buffer stdout for cleaner logs
|
|
4
|
+
ENV PYTHONDONTWRITEBYTECODE=1
|
|
5
|
+
ENV PYTHONUNBUFFERED=1
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
# Create a non-root user for security compliance (Alpine syntax)
|
|
10
|
+
RUN addgroup -S appuser && \
|
|
11
|
+
adduser -S appuser -G appuser -D -s /bin/sh
|
|
12
|
+
|
|
13
|
+
# Install runtime libraries and temporary build tools
|
|
14
|
+
RUN apk update && apk upgrade --no-cache && \
|
|
15
|
+
apk add --no-cache libpq && \
|
|
16
|
+
apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev
|
|
17
|
+
|
|
18
|
+
COPY requirements.txt .
|
|
19
|
+
|
|
20
|
+
# Upgrade pip, install dependencies, clear caches, and NUKE package managers
|
|
21
|
+
RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
|
|
22
|
+
pip install --no-cache-dir -r requirements.txt && \
|
|
23
|
+
find / -type d -name "ensurepip" -exec rm -rf {} + || true && \
|
|
24
|
+
rm -rf /root/.cache/pip && \
|
|
25
|
+
pip uninstall -y setuptools wheel pip
|
|
26
|
+
|
|
27
|
+
# Remove the build tools to shrink the image and reduce attack surface
|
|
28
|
+
RUN apk del .build-deps
|
|
29
|
+
|
|
30
|
+
# Copy with ownership
|
|
31
|
+
COPY --chown=appuser:appuser . .
|
|
32
|
+
|
|
33
|
+
# Drop root privileges
|
|
34
|
+
USER appuser
|
|
35
|
+
|
|
36
|
+
EXPOSE {{PORT}}
|
|
37
|
+
|
|
38
|
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "{{PORT}}"]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Stage 1: Build the Rails application
|
|
2
|
+
FROM ruby:3.3.5-alpine AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# Install native build tools required to compile C extensions (like pg or nokogiri)
|
|
6
|
+
RUN apk update && \
|
|
7
|
+
apk add --no-cache build-base postgresql-dev tzdata nodejs yarn
|
|
8
|
+
|
|
9
|
+
COPY Gemfile Gemfile.lock* ./
|
|
10
|
+
|
|
11
|
+
# Use ENV to guarantee Bundler skips dev/test gems
|
|
12
|
+
ENV BUNDLE_WITHOUT="development:test"
|
|
13
|
+
|
|
14
|
+
# Install deps and remove cache
|
|
15
|
+
RUN bundle install && \
|
|
16
|
+
rm -rf /usr/local/bundle/cache/*.gem
|
|
17
|
+
|
|
18
|
+
COPY . .
|
|
19
|
+
|
|
20
|
+
# Precompile assets (we use a dummy key since it's just for building)
|
|
21
|
+
RUN SECRET_KEY_BASE=dummy bundle exec rails assets:precompile || true
|
|
22
|
+
|
|
23
|
+
# Stage 2: Production runner
|
|
24
|
+
FROM ruby:3.3.5-alpine AS runner
|
|
25
|
+
WORKDIR /app
|
|
26
|
+
|
|
27
|
+
ENV RAILS_ENV=production \
|
|
28
|
+
RAILS_SERVE_STATIC_FILES=true \
|
|
29
|
+
RAILS_LOG_TO_STDOUT=true \
|
|
30
|
+
BUNDLE_WITHOUT="development:test" \
|
|
31
|
+
PORT={{PORT}}
|
|
32
|
+
|
|
33
|
+
# Upgrade Alpine OS to patch system CVEs and install runtime libs
|
|
34
|
+
# Explicitly patch Ruby's default gems and remove their legacy gemspecs so Trivy ignores them
|
|
35
|
+
RUN apk update && apk upgrade --no-cache && \
|
|
36
|
+
apk add --no-cache postgresql-libs tzdata && \
|
|
37
|
+
apk add --no-cache --virtual .build-deps build-base zlib-dev && \
|
|
38
|
+
gem install erb net-imap resolv rexml uri zlib && \
|
|
39
|
+
rm -f /usr/local/lib/ruby/gems/*/specifications/default/erb-*.gemspec \
|
|
40
|
+
/usr/local/lib/ruby/gems/*/specifications/default/resolv-*.gemspec \
|
|
41
|
+
/usr/local/lib/ruby/gems/*/specifications/default/uri-*.gemspec \
|
|
42
|
+
/usr/local/lib/ruby/gems/*/specifications/default/zlib-*.gemspec \
|
|
43
|
+
/usr/local/lib/ruby/gems/*/specifications/net-imap-0.4.*.gemspec \
|
|
44
|
+
/usr/local/lib/ruby/gems/*/specifications/rexml-3.3.6.gemspec && \
|
|
45
|
+
apk del .build-deps && \
|
|
46
|
+
rm -rf /var/cache/apk/*
|
|
47
|
+
|
|
48
|
+
# Create unprivileged user
|
|
49
|
+
RUN addgroup -g 1001 -S railsgroup && \
|
|
50
|
+
adduser -S railsuser -u 1001 -G railsgroup
|
|
51
|
+
|
|
52
|
+
# Copy built gems and application code
|
|
53
|
+
COPY --from=builder --chown=railsuser:railsgroup /usr/local/bundle /usr/local/bundle
|
|
54
|
+
COPY --from=builder --chown=railsuser:railsgroup /app /app
|
|
55
|
+
|
|
56
|
+
USER railsuser
|
|
57
|
+
EXPOSE {{PORT}}
|
|
58
|
+
|
|
59
|
+
CMD ["bundle", "exec", "puma", "-b", "tcp://0.0.0.0:{{PORT}}"]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# STAGE 1: Build the static assets
|
|
2
|
+
FROM node:22-alpine AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
COPY package*.json ./
|
|
6
|
+
# Use clean install for reliable, reproducible builds
|
|
7
|
+
RUN npm ci
|
|
8
|
+
|
|
9
|
+
COPY . .
|
|
10
|
+
# Runs the standard build script defined in package.json
|
|
11
|
+
RUN npm run build
|
|
12
|
+
|
|
13
|
+
# STAGE 2: Serve with Hardened Nginx
|
|
14
|
+
FROM nginxinc/nginx-unprivileged:alpine
|
|
15
|
+
|
|
16
|
+
# Adjusts BUILD_DIR to match your framework's output folder
|
|
17
|
+
COPY --from=builder /app/{{BUILD_DIR}} /usr/share/nginx/html
|
|
18
|
+
|
|
19
|
+
# Inject custom Nginx configuration for unprivileged ports and SPA routing
|
|
20
|
+
RUN echo "server {" > /etc/nginx/conf.d/default.conf && \
|
|
21
|
+
echo " listen {{PORT}};" >> /etc/nginx/conf.d/default.conf && \
|
|
22
|
+
echo " listen [::]:{{PORT}};" >> /etc/nginx/conf.d/default.conf && \
|
|
23
|
+
echo " server_name localhost;" >> /etc/nginx/conf.d/default.conf && \
|
|
24
|
+
echo " location / {" >> /etc/nginx/conf.d/default.conf && \
|
|
25
|
+
echo " root /usr/share/nginx/html;" >> /etc/nginx/conf.d/default.conf && \
|
|
26
|
+
echo " index index.html index.htm;" >> /etc/nginx/conf.d/default.conf && \
|
|
27
|
+
echo " try_files \$uri \$uri/ /index.html;" >> /etc/nginx/conf.d/default.conf && \
|
|
28
|
+
echo " }" >> /etc/nginx/conf.d/default.conf && \
|
|
29
|
+
echo "}" >> /etc/nginx/conf.d/default.conf
|
|
30
|
+
|
|
31
|
+
EXPOSE {{PORT}}
|
|
32
|
+
CMD ["nginx", "-g", "daemon off;"]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# ==========================================
|
|
2
|
+
# Stage 1: Builder
|
|
3
|
+
# ==========================================
|
|
4
|
+
FROM node:22-alpine AS builder
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
# Install all dependencies (including devDependencies)
|
|
8
|
+
COPY package*.json ./
|
|
9
|
+
RUN npm ci
|
|
10
|
+
|
|
11
|
+
# Copy source code
|
|
12
|
+
COPY . .
|
|
13
|
+
|
|
14
|
+
# ZERO-CLICK MAGIC: Automatically inject adapter-node if the user left adapter-auto in their config.
|
|
15
|
+
# This ensures the build/ directory is always generated without requiring manual code changes.
|
|
16
|
+
RUN npm install -D @sveltejs/adapter-node@latest && \
|
|
17
|
+
sed -i 's/@sveltejs\/adapter-auto/@sveltejs\/adapter-node/g' svelte.config.js 2>/dev/null || true && \
|
|
18
|
+
sed -i 's/@sveltejs\/adapter-auto/@sveltejs\/adapter-node/g' vite.config.ts 2>/dev/null || true && \
|
|
19
|
+
sed -i 's/@sveltejs\/adapter-auto/@sveltejs\/adapter-node/g' vite.config.js 2>/dev/null || true
|
|
20
|
+
|
|
21
|
+
# Inject the bypass flag and compile the SvelteKit application
|
|
22
|
+
RUN GRADA_BYPASS=true npm run build
|
|
23
|
+
|
|
24
|
+
# ==========================================
|
|
25
|
+
# Stage 2: Production (Zero-CVE)
|
|
26
|
+
# ==========================================
|
|
27
|
+
FROM node:22-alpine
|
|
28
|
+
|
|
29
|
+
# 1. DevSecOps: Patch underlying Alpine OS vulnerabilities
|
|
30
|
+
RUN apk update && apk upgrade --no-cache
|
|
31
|
+
|
|
32
|
+
# 2. Set production environment
|
|
33
|
+
ENV NODE_ENV=production
|
|
34
|
+
WORKDIR /app
|
|
35
|
+
|
|
36
|
+
# 3. Copy manifests and install ONLY production dependencies
|
|
37
|
+
COPY --from=builder --chown=node:node /app/package*.json ./
|
|
38
|
+
RUN npm ci --omit=dev && npm cache clean --force
|
|
39
|
+
|
|
40
|
+
# 4. Copy the compiled SvelteKit server from the builder stage
|
|
41
|
+
COPY --from=builder --chown=node:node /app/build/ ./build/
|
|
42
|
+
|
|
43
|
+
# 5. DevSecOps: Nuke all package managers to eliminate base-image CVEs
|
|
44
|
+
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx \
|
|
45
|
+
/opt/yarn-* /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
46
|
+
/usr/local/lib/node_modules/corepack /usr/local/bin/corepack
|
|
47
|
+
|
|
48
|
+
USER node
|
|
49
|
+
EXPOSE {{PORT}}
|
|
50
|
+
|
|
51
|
+
# 6. Execute the raw Node server directly
|
|
52
|
+
CMD ["node", "build/index.js"]
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: Deploy to AWS Lambda
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- {{DEPLOY_BRANCH}}
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: '0 0 * * 0'
|
|
9
|
+
|
|
10
|
+
env:
|
|
11
|
+
AWS_REGION: {{REGION}}
|
|
12
|
+
ECR_REPOSITORY: {{PROJECT_NAME}}-repo
|
|
13
|
+
LAMBDA_FUNCTION: {{PROJECT_NAME}}-fn
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
id-token: write
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
deploy:
|
|
21
|
+
name: Build & Deploy
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- name: Checkout Code
|
|
26
|
+
uses: actions/checkout@v4
|
|
27
|
+
|
|
28
|
+
# --- 1. IaC SECURITY SCAN ---
|
|
29
|
+
- name: Scan Terraform for Misconfigurations
|
|
30
|
+
uses: aquasecurity/trivy-action@master
|
|
31
|
+
with:
|
|
32
|
+
scan-type: 'fs'
|
|
33
|
+
scan-ref: 'terraform/'
|
|
34
|
+
scanners: 'vuln,secret,misconfig'
|
|
35
|
+
format: 'table'
|
|
36
|
+
exit-code: '0' # Informational only, will not break the build
|
|
37
|
+
severity: 'CRITICAL,HIGH'
|
|
38
|
+
output: 'trivy-iac-summary.txt'
|
|
39
|
+
|
|
40
|
+
- name: Publish IaC Summary
|
|
41
|
+
if: always()
|
|
42
|
+
run: |
|
|
43
|
+
if [ -f trivy-iac-summary.txt ]; then
|
|
44
|
+
echo "### 🏗️ Terraform Misconfiguration Scan" >> $GITHUB_STEP_SUMMARY
|
|
45
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
46
|
+
cat trivy-iac-summary.txt >> $GITHUB_STEP_SUMMARY
|
|
47
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# --- 2. INFRASTRUCTURE SYNC (The New Marketplace Action) ---
|
|
51
|
+
- name: Apply Infrastructure Changes
|
|
52
|
+
uses: grada-run/grada-action@v1
|
|
53
|
+
with:
|
|
54
|
+
aws-region: ${{ env.AWS_REGION }}
|
|
55
|
+
role-to-assume: arn:aws:iam::{{AWS_ACCOUNT_ID}}:role/{{PROJECT_NAME}}-github-actions-role
|
|
56
|
+
terraform-dir: 'terraform'
|
|
57
|
+
|
|
58
|
+
# --- 3. BUILD & PUSH ---
|
|
59
|
+
- name: Login to Amazon ECR
|
|
60
|
+
id: login-ecr
|
|
61
|
+
uses: aws-actions/amazon-ecr-login@v2
|
|
62
|
+
|
|
63
|
+
- name: Build Docker image
|
|
64
|
+
id: build-image
|
|
65
|
+
env:
|
|
66
|
+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
|
67
|
+
IMAGE_TAG: latest
|
|
68
|
+
run: |
|
|
69
|
+
SHA_TAG=${GITHUB_SHA::7}
|
|
70
|
+
# The Lambda function runs on x86_64 (see terraform/main.tf), so the
|
|
71
|
+
# image must be built for linux/amd64 even on arm64 runners.
|
|
72
|
+
docker build --platform linux/amd64 -t $ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG .
|
|
73
|
+
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
|
74
|
+
|
|
75
|
+
# --- 4. CONTAINER SECURITY SCAN ---
|
|
76
|
+
- name: Scan Container for Vulnerabilities (SARIF Output)
|
|
77
|
+
uses: aquasecurity/trivy-action@master
|
|
78
|
+
with:
|
|
79
|
+
image-ref: '${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest'
|
|
80
|
+
format: 'table'
|
|
81
|
+
output: 'trivy-container-summary.txt'
|
|
82
|
+
exit-code: '0' # Informational only, will not break the build
|
|
83
|
+
ignore-unfixed: true
|
|
84
|
+
vuln-type: 'os,library'
|
|
85
|
+
severity: 'CRITICAL,HIGH'
|
|
86
|
+
|
|
87
|
+
- name: Publish Container Summary
|
|
88
|
+
if: always()
|
|
89
|
+
run: |
|
|
90
|
+
if [ -f trivy-container-summary.txt ]; then
|
|
91
|
+
echo "### 🛡️ Container Security Scan Results" >> $GITHUB_STEP_SUMMARY
|
|
92
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
93
|
+
cat trivy-container-summary.txt >> $GITHUB_STEP_SUMMARY
|
|
94
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# --- 5. DEPLOY ---
|
|
98
|
+
- name: Push image to Amazon ECR
|
|
99
|
+
env:
|
|
100
|
+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
|
101
|
+
IMAGE_TAG: latest
|
|
102
|
+
run: |
|
|
103
|
+
SHA_TAG=${GITHUB_SHA::7}
|
|
104
|
+
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG
|
|
105
|
+
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
|
106
|
+
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG" >> $GITHUB_OUTPUT
|
|
107
|
+
|
|
108
|
+
# Each code push deploys the immutable SHA-tagged image to the Lambda
|
|
109
|
+
# function, so every ECR tag stays a redeployable rollback point (and
|
|
110
|
+
# `latest` is never the deploy artifact of record).
|
|
111
|
+
- name: Deploy image to AWS Lambda
|
|
112
|
+
run: |
|
|
113
|
+
IMAGE_URI=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${GITHUB_SHA::7}
|
|
114
|
+
aws lambda update-function-code \
|
|
115
|
+
--function-name ${{ env.LAMBDA_FUNCTION }} \
|
|
116
|
+
--image-uri "$IMAGE_URI" \
|
|
117
|
+
--region ${{ env.AWS_REGION }}
|
|
118
|
+
aws lambda wait function-updated \
|
|
119
|
+
--function-name ${{ env.LAMBDA_FUNCTION }} \
|
|
120
|
+
--region ${{ env.AWS_REGION }}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
name: Deploy to AWS ECS
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- {{DEPLOY_BRANCH}}
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: '0 0 * * 0'
|
|
9
|
+
|
|
10
|
+
env:
|
|
11
|
+
AWS_REGION: {{REGION}}
|
|
12
|
+
ECR_REPOSITORY: {{PROJECT_NAME}}-repo
|
|
13
|
+
ECS_CLUSTER: {{PROJECT_NAME}}-cluster
|
|
14
|
+
ECS_SERVICE: {{PROJECT_NAME}}-service
|
|
15
|
+
ECS_TASK_FAMILY: {{PROJECT_NAME}}-task
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
id-token: write
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
deploy:
|
|
23
|
+
name: Build & Deploy
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout Code
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
# --- 1. IaC SECURITY SCAN ---
|
|
31
|
+
- name: Scan Terraform for Misconfigurations
|
|
32
|
+
uses: aquasecurity/trivy-action@master
|
|
33
|
+
with:
|
|
34
|
+
scan-type: 'fs'
|
|
35
|
+
scan-ref: 'terraform/'
|
|
36
|
+
scanners: 'vuln,secret,misconfig'
|
|
37
|
+
format: 'table'
|
|
38
|
+
exit-code: '0' # Informational only, will not break the build
|
|
39
|
+
severity: 'CRITICAL,HIGH'
|
|
40
|
+
output: 'trivy-iac-summary.txt'
|
|
41
|
+
|
|
42
|
+
- name: Publish IaC Summary
|
|
43
|
+
if: always()
|
|
44
|
+
run: |
|
|
45
|
+
if [ -f trivy-iac-summary.txt ]; then
|
|
46
|
+
echo "### 🏗️ Terraform Misconfiguration Scan" >> $GITHUB_STEP_SUMMARY
|
|
47
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
48
|
+
cat trivy-iac-summary.txt >> $GITHUB_STEP_SUMMARY
|
|
49
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# --- 2. INFRASTRUCTURE SYNC (The New Marketplace Action) ---
|
|
53
|
+
- name: Apply Infrastructure Changes
|
|
54
|
+
uses: grada-run/grada-action@v1
|
|
55
|
+
with:
|
|
56
|
+
aws-region: ${{ env.AWS_REGION }}
|
|
57
|
+
role-to-assume: arn:aws:iam::{{AWS_ACCOUNT_ID}}:role/{{PROJECT_NAME}}-github-actions-role
|
|
58
|
+
terraform-dir: 'terraform'
|
|
59
|
+
|
|
60
|
+
# --- 3. BUILD & PUSH ---
|
|
61
|
+
- name: Login to Amazon ECR
|
|
62
|
+
id: login-ecr
|
|
63
|
+
uses: aws-actions/amazon-ecr-login@v2
|
|
64
|
+
|
|
65
|
+
- name: Build Docker image
|
|
66
|
+
id: build-image
|
|
67
|
+
env:
|
|
68
|
+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
|
69
|
+
IMAGE_TAG: latest
|
|
70
|
+
run: |
|
|
71
|
+
SHA_TAG=${GITHUB_SHA::7}
|
|
72
|
+
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG .
|
|
73
|
+
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
|
74
|
+
|
|
75
|
+
# --- 4. CONTAINER SECURITY SCAN ---
|
|
76
|
+
- name: Scan Container for Vulnerabilities (SARIF Output)
|
|
77
|
+
uses: aquasecurity/trivy-action@master
|
|
78
|
+
with:
|
|
79
|
+
image-ref: '${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:latest'
|
|
80
|
+
format: 'table'
|
|
81
|
+
output: 'trivy-container-summary.txt'
|
|
82
|
+
exit-code: '0' # Informational only, will not break the build
|
|
83
|
+
ignore-unfixed: true
|
|
84
|
+
vuln-type: 'os,library'
|
|
85
|
+
severity: 'CRITICAL,HIGH'
|
|
86
|
+
|
|
87
|
+
- name: Publish Container Summary
|
|
88
|
+
if: always()
|
|
89
|
+
run: |
|
|
90
|
+
if [ -f trivy-container-summary.txt ]; then
|
|
91
|
+
echo "### 🛡️ Container Security Scan Results" >> $GITHUB_STEP_SUMMARY
|
|
92
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
93
|
+
cat trivy-container-summary.txt >> $GITHUB_STEP_SUMMARY
|
|
94
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# --- 5. DEPLOY ---
|
|
98
|
+
- name: Push image to Amazon ECR
|
|
99
|
+
env:
|
|
100
|
+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
|
101
|
+
IMAGE_TAG: latest
|
|
102
|
+
run: |
|
|
103
|
+
SHA_TAG=${GITHUB_SHA::7}
|
|
104
|
+
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG
|
|
105
|
+
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
|
106
|
+
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$SHA_TAG" >> $GITHUB_OUTPUT
|
|
107
|
+
|
|
108
|
+
# Each code push registers a new task definition revision pinned to the
|
|
109
|
+
# immutable SHA-tagged image, so `rollback` always has history to
|
|
110
|
+
# return to (and `latest` is never overwritten in place as the deploy
|
|
111
|
+
# artifact of record).
|
|
112
|
+
- name: Register new task definition revision
|
|
113
|
+
id: register-task-def
|
|
114
|
+
run: |
|
|
115
|
+
IMAGE_URI=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${GITHUB_SHA::7}
|
|
116
|
+
TASK_DEF=$(aws ecs describe-task-definition \
|
|
117
|
+
--task-definition ${{ env.ECS_TASK_FAMILY }} \
|
|
118
|
+
--region ${{ env.AWS_REGION }} \
|
|
119
|
+
--query 'taskDefinition' \
|
|
120
|
+
--output json)
|
|
121
|
+
NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
|
|
122
|
+
--arg IMAGE "$IMAGE_URI" \
|
|
123
|
+
'.containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy, .deregisteredAt)')
|
|
124
|
+
NEW_TASK_ARN=$(aws ecs register-task-definition \
|
|
125
|
+
--region ${{ env.AWS_REGION }} \
|
|
126
|
+
--cli-input-json "$NEW_TASK_DEF" \
|
|
127
|
+
--query 'taskDefinition.taskDefinitionArn' \
|
|
128
|
+
--output text)
|
|
129
|
+
echo "task-arn=$NEW_TASK_ARN" >> $GITHUB_OUTPUT
|
|
130
|
+
|
|
131
|
+
- name: Force ECS deployment
|
|
132
|
+
run: |
|
|
133
|
+
aws ecs update-service \
|
|
134
|
+
--cluster ${{ env.ECS_CLUSTER }} \
|
|
135
|
+
--service ${{ env.ECS_SERVICE }} \
|
|
136
|
+
--task-definition ${{ steps.register-task-def.outputs.task-arn }} \
|
|
137
|
+
--force-new-deployment \
|
|
138
|
+
--region ${{ env.AWS_REGION }}
|