mirror of
https://github.com/Sea-Haven-Industries/engineering-handbook.git
synced 2026-09-30 05:43:15 +00:00
Add repo provisioning script
Automates the new-repo checklist: GitHub repo creation, OIDC deploy role, repo secret, security features, CI/CD workflow stubs, and pre-push hook installation. Supports both SAM and CDK stack types.
This commit is contained in:
parent
2b5fe0f712
commit
e109101326
2 changed files with 233 additions and 0 deletions
|
|
@ -15,6 +15,7 @@ Engineering conventions and best practices for Sea Haven Industries.
|
|||
- [Secrets and Configuration](secrets-and-config.md) -- Secrets Manager vs SSM Parameter Store
|
||||
- [CI/CD Pipelines](cicd.md) -- every deployable repo gets a pipeline, no manual deploys
|
||||
- [Git Hooks](hooks/) -- recommended pre-push and pre-commit hooks
|
||||
- [Scripts](scripts/) -- repo provisioning, automation tooling
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
|
|||
232
scripts/provision-repo.sh
Executable file
232
scripts/provision-repo.sh
Executable file
|
|
@ -0,0 +1,232 @@
|
|||
#!/usr/bin/env bash
|
||||
# Provision a new Sea Haven Industries repo with all required infrastructure.
|
||||
# Usage: ./provision-repo.sh <repo-name> [sam|cdk]
|
||||
#
|
||||
# Creates: GitHub repo, OIDC deploy role, repo secret, security features,
|
||||
# CI/CD workflow stubs, and pre-push hook.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_NAME="${1:?Usage: provision-repo.sh <repo-name> [sam|cdk]}"
|
||||
STACK_TYPE="${2:-sam}"
|
||||
ORG="Sea-Haven-Industries"
|
||||
ACCOUNT_ID="328440206208"
|
||||
REGION="us-east-1"
|
||||
OIDC_PROVIDER="arn:aws:iam::${ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com"
|
||||
ROLE_NAME="githubdeploy-${REPO_NAME}"
|
||||
|
||||
if [[ ! "$REPO_NAME" =~ ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ ]]; then
|
||||
echo "Error: repo name must be kebab-case (lowercase, hyphens only, no leading/trailing hyphens)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Provisioning ${ORG}/${REPO_NAME} (${STACK_TYPE}) ==="
|
||||
|
||||
# 1. Create GitHub repo
|
||||
echo ""
|
||||
echo "[1/6] Creating GitHub repo..."
|
||||
if gh repo view "${ORG}/${REPO_NAME}" &>/dev/null; then
|
||||
echo " Repo already exists — skipping."
|
||||
else
|
||||
gh repo create "${ORG}/${REPO_NAME}" \
|
||||
--private \
|
||||
--description "${REPO_NAME} — Sea Haven Industries" \
|
||||
--clone=false
|
||||
echo " Created ${ORG}/${REPO_NAME}"
|
||||
fi
|
||||
|
||||
# 2. Create OIDC deploy role
|
||||
echo ""
|
||||
echo "[2/6] Creating IAM deploy role: ${ROLE_NAME}..."
|
||||
TRUST_POLICY=$(cat <<POLICY
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"Federated": "${OIDC_PROVIDER}"},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
|
||||
},
|
||||
"StringLike": {
|
||||
"token.actions.githubusercontent.com:sub": "repo:${ORG}/${REPO_NAME}:ref:refs/heads/main"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
POLICY
|
||||
)
|
||||
|
||||
if aws iam get-role --role-name "${ROLE_NAME}" &>/dev/null; then
|
||||
echo " Role already exists — skipping."
|
||||
else
|
||||
aws iam create-role \
|
||||
--role-name "${ROLE_NAME}" \
|
||||
--assume-role-policy-document "${TRUST_POLICY}" \
|
||||
--tags "Key=Project,Value=${REPO_NAME}" "Key=ManagedBy,Value=provision-script" \
|
||||
--query 'Role.Arn' --output text
|
||||
|
||||
if [[ "$STACK_TYPE" == "cdk" ]]; then
|
||||
DEPLOY_POLICY=$(cat <<DPOLICY
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [{
|
||||
"Effect": "Allow",
|
||||
"Action": "sts:AssumeRole",
|
||||
"Resource": "arn:aws:iam::${ACCOUNT_ID}:role/cdk-hnb659fds-*"
|
||||
}]
|
||||
}
|
||||
DPOLICY
|
||||
)
|
||||
else
|
||||
DEPLOY_POLICY=$(cat <<DPOLICY
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "sts:AssumeRole",
|
||||
"Resource": "arn:aws:iam::${ACCOUNT_ID}:role/cdk-hnb659fds-*"
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "cloudformation:*",
|
||||
"Resource": "arn:aws:cloudformation:${REGION}:${ACCOUNT_ID}:stack/${REPO_NAME}/*"
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "iam:PassRole",
|
||||
"Resource": "arn:aws:iam::${ACCOUNT_ID}:role/${REPO_NAME}-*"
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "s3:*",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::aws-sam-cli-managed-default-samclisourcebucket-*",
|
||||
"arn:aws:s3:::aws-sam-cli-managed-default-samclisourcebucket-*/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
DPOLICY
|
||||
)
|
||||
fi
|
||||
|
||||
aws iam put-role-policy \
|
||||
--role-name "${ROLE_NAME}" \
|
||||
--policy-name "deploy" \
|
||||
--policy-document "${DEPLOY_POLICY}"
|
||||
echo " Created role with deploy policy."
|
||||
fi
|
||||
|
||||
ROLE_ARN="arn:aws:iam::${ACCOUNT_ID}:role/${ROLE_NAME}"
|
||||
|
||||
# 3. Set repo secret
|
||||
echo ""
|
||||
echo "[3/6] Setting AWS_DEPLOY_ROLE_ARN secret..."
|
||||
gh secret set AWS_DEPLOY_ROLE_ARN \
|
||||
--repo "${ORG}/${REPO_NAME}" \
|
||||
--body "${ROLE_ARN}"
|
||||
echo " Secret set."
|
||||
|
||||
# 4. Enable security features
|
||||
echo ""
|
||||
echo "[4/6] Enabling security features..."
|
||||
gh api "repos/${ORG}/${REPO_NAME}/vulnerability-alerts" -X PUT 2>/dev/null || true
|
||||
gh api "repos/${ORG}/${REPO_NAME}" -X PATCH \
|
||||
-f security_and_analysis.dependabot_security_updates.status=enabled \
|
||||
-f security_and_analysis.secret_scanning.status=enabled \
|
||||
--silent 2>/dev/null || true
|
||||
echo " Dependabot alerts, security updates, and secret scanning enabled."
|
||||
|
||||
# 5. Create CI/CD workflow stubs
|
||||
echo ""
|
||||
echo "[5/6] Creating CI/CD workflow files..."
|
||||
|
||||
REPO_DIR="${HOME}/Documents/repositories/${REPO_NAME}"
|
||||
if [[ ! -d "${REPO_DIR}" ]]; then
|
||||
echo " Repo not cloned locally — skipping workflow file creation."
|
||||
echo " Clone it and re-run, or create .github/workflows/ manually."
|
||||
else
|
||||
mkdir -p "${REPO_DIR}/.github/workflows"
|
||||
|
||||
if [[ "$STACK_TYPE" == "cdk" ]]; then
|
||||
cat > "${REPO_DIR}/.github/workflows/ci.yaml" <<'CIEOF'
|
||||
name: CI
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
jobs:
|
||||
ci:
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/ci-typescript-cdk.yaml@main
|
||||
with:
|
||||
node-version: "24"
|
||||
CIEOF
|
||||
|
||||
cat > "${REPO_DIR}/.github/workflows/deploy.yaml" <<'CDEOF'
|
||||
name: Deploy
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
jobs:
|
||||
deploy:
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@main
|
||||
with:
|
||||
node-version: "24"
|
||||
secrets:
|
||||
deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
||||
CDEOF
|
||||
else
|
||||
cat > "${REPO_DIR}/.github/workflows/ci.yaml" <<'CIEOF'
|
||||
name: CI
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
jobs:
|
||||
ci:
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/ci-python-sam.yaml@main
|
||||
CIEOF
|
||||
|
||||
cat > "${REPO_DIR}/.github/workflows/deploy.yaml" <<'CDEOF'
|
||||
name: Deploy
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
jobs:
|
||||
deploy:
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/cd-sam.yaml@main
|
||||
with:
|
||||
stack-name: "REPO_PLACEHOLDER"
|
||||
secrets:
|
||||
cfn-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
||||
CDEOF
|
||||
sed -i '' "s/REPO_PLACEHOLDER/${REPO_NAME}/" "${REPO_DIR}/.github/workflows/deploy.yaml"
|
||||
fi
|
||||
echo " Created ci.yaml and deploy.yaml"
|
||||
fi
|
||||
|
||||
# 6. Install pre-push hook
|
||||
echo ""
|
||||
echo "[6/6] Installing pre-push hook..."
|
||||
if [[ -d "${REPO_DIR}/.git" ]]; then
|
||||
HOOK_SRC="${HOME}/Documents/repositories/engineering-handbook/hooks/pre-push"
|
||||
if [[ -f "$HOOK_SRC" ]]; then
|
||||
cp "$HOOK_SRC" "${REPO_DIR}/.git/hooks/pre-push"
|
||||
chmod +x "${REPO_DIR}/.git/hooks/pre-push"
|
||||
echo " Installed pre-push hook."
|
||||
else
|
||||
echo " Hook source not found — skipping."
|
||||
fi
|
||||
else
|
||||
echo " No local .git — skipping."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Provisioning complete ==="
|
||||
echo ""
|
||||
echo "Remaining manual steps:"
|
||||
echo " 1. Create any Secrets Manager secrets needed (${REPO_NAME}/secret-name)"
|
||||
echo " 2. Commit and push the workflow files"
|
||||
echo " 3. Verify CI passes on first PR"
|
||||
echo " 4. Create a project memory entry"
|
||||
Loading…
Add table
Reference in a new issue