L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Déploiement et opérations · SKILL.md

website-infra

website-infra

Deploys AWS CloudFormation infrastructure stacks for the website (S3, CloudFront, Route 53, ACM, and optionally contact form API).

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: website-infra description: Deploys AWS CloudFormation infrastructure stacks for the website (S3, CloudFront, Route 53, ACM, and optionally contact form API). allowed-tools: Bash, Read, Write, Edit, Glob

Website Infrastructure Skill

You are running the /grc-portfolio:infra skill. Your job is to deploy the AWS infrastructure needed to host the website using CloudFormation.

Step 1: Locate and Validate Config

Find site-config.json:

  • Check $ARGUMENTS for a project directory path
  • Check the current working directory
  • Ask the user if not found

Read it and validate that status.preflightComplete === true. If not, tell the user to run /grc-portfolio:preflight first.

Step 2: Choose Template

Based on features.customDomain:

  • With custom domain: Use $TOOLKIT_DIR/cloudformation/website-infrastructure.yaml
  • Without custom domain: Use $TOOLKIT_DIR/cloudformation/website-infrastructure-no-domain.yaml

Step 3: Validate Template

Run the validation script:

$TOOLKIT_DIR/scripts/validate-stack.sh <template-path> <aws.profile>

If validation fails, report the error and stop.

Step 4: Deploy Main Stack

Use aws cloudformation deploy — it is idempotent (creates the stack on first run, applies a change-set on subsequent runs) and waits for completion inline, so the user doesn't need a separate wait step.

With custom domain:

aws cloudformation deploy \
  --stack-name <aws.stackName> \
  --template-file <template-path> \
  --parameter-overrides \
    ProjectName=<projectName> \
    DomainName=<aws.domain> \
    HostedZoneId=<aws.hostedZoneId> \
    CertificateArn=<aws.certArn> \
  --profile <aws.profile> \
  --region us-east-1 \
  --no-fail-on-empty-changeset

Without custom domain:

aws cloudformation deploy \
  --stack-name <aws.stackName> \
  --template-file <template-path> \
  --parameter-overrides ProjectName=<projectName> \
  --profile <aws.profile> \
  --region us-east-1 \
  --no-fail-on-empty-changeset

Note: Check the actual template parameters first by reading the template file, as parameter names may differ from the examples above. Use the actual parameter names from the template.

The deploy command can take 5-15 minutes (especially with CloudFront distribution creation). Tell the user it's in progress and approximately how long it might take.

If the deploy fails, retrieve the failure reason:

aws cloudformation describe-stack-events \
  --stack-name <aws.stackName> \
  --profile <aws.profile> \
  --region us-east-1 \
  --query "StackEvents[?ResourceStatus=='CREATE_FAILED' || ResourceStatus=='UPDATE_FAILED'].[LogicalResourceId,ResourceStatusReason]" \
  --output table

Step 6: Retrieve Stack Outputs

aws cloudformation describe-stacks \
  --stack-name <aws.stackName> \
  --profile <aws.profile> \
  --region us-east-1 \
  --query "Stacks[0].Outputs"

Extract and save to site-config.json:

  • aws.bucketName -- the S3 bucket name
  • aws.distributionId -- the CloudFront distribution ID
  • aws.cloudFrontUrl -- the CloudFront domain name (e.g., d123abc.cloudfront.net)

Step 7: Deploy Contact Form API (if enabled)

If features.contactForm is true:

  1. Ask the user for two SES-verified email addresses (no defaults — the stack will refuse to deploy without them):

    • SESFromEmail: verified sender identity
    • SESToEmail: recipient inbox for submissions

    If either is not yet verified in SES, stop and instruct the user to verify them in the AWS Console (SES → Verified identities → Create identity) before continuing. Save both to aws.sesFromEmail and aws.sesToEmail in site-config.json.

  2. Deploy the contact form stack:

aws cloudformation deploy \
  --template-file $TOOLKIT_DIR/cloudformation/contact-form-api.yaml \
  --stack-name <projectName>-contact-form-api \
  --parameter-overrides "SESFromEmail=<aws.sesFromEmail>" "SESToEmail=<aws.sesToEmail>" \
  --capabilities CAPABILITY_IAM \
  --profile <aws.profile> \
  --region us-east-1 \
  --no-fail-on-empty-changeset
  1. Retrieve the API endpoint:
aws cloudformation describe-stacks \
  --stack-name <projectName>-contact-form-api \
  --profile <aws.profile> \
  --region us-east-1 \
  --query "Stacks[0].Outputs[?OutputKey=='ApiEndpoint'].OutputValue" \
  --output text
  1. Save to aws.contactApiEndpoint in config.

  2. Package and deploy the Lambda function code (reference $TOOLKIT_DIR/scripts/deploy-contact-api.sh for the pattern -- create temp dir, copy handler, install @aws-sdk/client-ses, zip, update function code). The function name is <projectName>-contact-form-api-handler (derived from the stack name in the template).

Step 8: Domain Instructions (if custom domain)

If using a custom domain, tell the user:

  • The nameservers they need to set at their domain registrar
  • How to verify DNS propagation: dig NS <domain>
  • That DNS propagation can take up to 48 hours (usually much faster)

Get the nameservers:

aws route53 get-hosted-zone --id <aws.hostedZoneId> --profile <aws.profile> --query "DelegationSet.NameServers"

Step 9: Update Config

Update site-config.json:

  • Set aws.bucketName, aws.distributionId, aws.cloudFrontUrl
  • Set aws.contactApiEndpoint (if contact form)
  • Set status.infraDeployed = true

Step 10: Summary

Tell the user:

  • Infrastructure deployed successfully
  • CloudFront URL where the site will be accessible
  • Contact form API endpoint (if applicable)
  • DNS instructions (if custom domain)
  • Suggest running /grc-portfolio:deploy next to push the built site to AWS

Variables

  • $TOOLKIT_DIR = read from site-config.json toolkitDir field
  • $ARGUMENTS = arguments passed after /infra (expected: project directory path)
Skills enregistrées