Skip to content

📝 Add agent architecture guidance #43

📝 Add agent architecture guidance

📝 Add agent architecture guidance #43

Workflow file for this run

name: Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install dependencies
run: npm install
- name: Build
run: npm run build
env:
NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
NOTION_CLIMBS_DB_ID: ${{ secrets.NOTION_CLIMBS_DB_ID }}
NOTION_PEAKS_DB_ID: ${{ secrets.NOTION_PEAKS_DB_ID }}
NOTION_GEAR_DB_ID: ${{ secrets.NOTION_GEAR_DB_ID }}
NOTION_PHOTOS_DB_ID: ${{ secrets.NOTION_PHOTOS_DB_ID }}
# Preview deployment for PRs
- name: Create Preview Deployment
if: github.event_name == 'pull_request'
id: preview-deployment
uses: actions/github-script@v7
with:
script: |
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.payload.pull_request.head.sha,
environment: 'preview',
auto_merge: false,
required_contexts: [],
description: `Preview deployment for PR #${context.payload.pull_request.number}`
});
return deployment.data.id;
result-encoding: string
- name: generate preview name from pr title
if: github.event_name == 'pull_request'
id: slug
run: |
TITLE="${{ github.event.pull_request.title }}"
WORD=$(echo "$TITLE" | sed -E 's/^(fix|feat|chore|docs|refactor|test|ci|style|perf|build|revert|rewrite|add|update|remove|delete)(\([^)]*\))?[\:!]?\s*//i' | awk '{print $1}' | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]//g' | cut -c1-12)
[ -z "$WORD" ] && WORD="pr${{ github.event.pull_request.number }}"
echo "name=climb-log-${WORD}-${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
- name: generate preview config
if: github.event_name == 'pull_request'
run: |
# Astro builds worker output to dist/server/ with static assets in dist/client/
# We need main pointing to the worker entry and assets to the client directory
# NOTE: Secrets are set via `wrangler secret put`, NOT in vars (which are plaintext)
jq --arg name "${{ steps.slug.outputs.name }}" '
.name = $name
| .main = "./dist/server/entry.mjs"
| .assets.directory = "./dist/client"
| .d1_databases[0].database_id = "c0e56b31-fbfd-46f9-992e-af369d9c2cb9"
| .d1_databases[0].database_name = "climb-log-db-preview"
| .vars.NOTION_CLIMBS_DB_ID = "${{ secrets.NOTION_CLIMBS_DB_ID }}"
| .vars.NOTION_PEAKS_DB_ID = "${{ secrets.NOTION_PEAKS_DB_ID }}"
| .vars.NOTION_GEAR_DB_ID = "${{ secrets.NOTION_GEAR_DB_ID }}"
| .vars.NOTION_PHOTOS_DB_ID = "${{ secrets.NOTION_PHOTOS_DB_ID }}"
| del(.env)
' wrangler.jsonc > wrangler-preview.jsonc
- name: Deploy to Preview
if: github.event_name == 'pull_request'
id: deploy-preview
run: |
START_TIME=$(date +%s)
set +e
npx wrangler deploy --config wrangler-preview.jsonc 2>&1
EXIT_CODE=$?
set -e
END_TIME=$(date +%s)
DEPLOY_TIME=$((END_TIME - START_TIME))
echo "deploy_time=${DEPLOY_TIME}s" >> $GITHUB_OUTPUT
echo "preview_url=https://${{ steps.slug.outputs.name }}.kylieski.workers.dev" >> $GITHUB_OUTPUT
exit $EXIT_CODE
- name: Set preview secrets
if: github.event_name == 'pull_request'
run: |
# Set secrets via wrangler secret put (not plaintext vars)
echo "${{ secrets.NOTION_TOKEN }}" | npx wrangler secret put NOTION_TOKEN --config wrangler-preview.jsonc
echo "${{ secrets.CRON_SECRET }}" | npx wrangler secret put CRON_SECRET --config wrangler-preview.jsonc
- name: apply migrations to preview db
if: github.event_name == 'pull_request'
run: |
npx wrangler d1 migrations apply climb-log-db-preview --remote --config wrangler-preview.jsonc
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- name: seed preview db
if: github.event_name == 'pull_request'
run: |
npx tsx db/seed.ts
npx wrangler d1 execute climb-log-db-preview --remote --file=db/seed.sql
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- name: Update Preview Deployment Status
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const deploymentId = ${{ steps.preview-deployment.outputs.result }};
const previewUrl = '${{ steps.deploy-preview.outputs.preview_url }}';
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deploymentId,
state: 'success',
environment_url: previewUrl,
description: 'Preview deployment successful'
});
- name: comment preview url
if: github.event_name == 'pull_request' && !startsWith(github.head_ref, 'blog/') && !startsWith(github.head_ref, 'post/')
uses: actions/github-script@v7
with:
script: |
const marker = '<!-- climb-log-preview-bot -->';
const isNew = context.payload.action === 'opened';
const verb = isNew ? 'deployed' : 'updated';
const emoji = isNew ? '🚀' : '⛰️';
const dbUrl = 'https://dash.cloudflare.com/bb52c0e5f3a93fc72779915d7dc6982b/workers/d1/databases/c0e56b31-fbfd-46f9-992e-af369d9c2cb9';
const previewUrl = '${{ steps.deploy-preview.outputs.preview_url }}';
const deployTime = '${{ steps.deploy-preview.outputs.deploy_time }}';
const commitSha = '${{ github.event.pull_request.head.sha }}'.substring(0, 7);
const body = `${marker}\n${emoji} Preview ${verb}!\n\n| | |\n|------|------|\n| 🔗 Preview | ${previewUrl} |\n| 📊 Database | [climb-log-db-preview](${dbUrl}) |\n| ⏱️ Deploy Time | ${deployTime} |\n| 📝 Commit | \`${commitSha}\` |\n\n_This preview updates automatically with each push._`;
const { data: comments } = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
const existing = comments.find(c => c.body && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
comment_id: existing.id,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
} else {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
}
# Production deployment on push to main
- name: Create Production Deployment
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
id: prod-deployment
uses: actions/github-script@v7
with:
script: |
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.sha,
environment: 'production',
auto_merge: false,
required_contexts: [],
description: 'Production deployment'
});
return deployment.data.id;
result-encoding: string
- name: Deploy to Production
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
id: deploy-prod
run: |
npx wrangler deploy
echo "prod_url=https://climb-log.kylieski.workers.dev" >> $GITHUB_OUTPUT
- name: Update Production Deployment Status
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: actions/github-script@v7
with:
script: |
const deploymentId = ${{ steps.prod-deployment.outputs.result }};
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deploymentId,
state: 'success',
environment_url: 'https://climb-log.kylieski.workers.dev',
description: 'Production deployment successful'
});
- name: Handle Deployment Failure
if: failure()
uses: actions/github-script@v7
with:
script: |
let deploymentId;
if (context.eventName === 'pull_request') {
deploymentId = '${{ steps.preview-deployment.outputs.result }}';
} else {
deploymentId = '${{ steps.prod-deployment.outputs.result }}';
}
if (deploymentId && deploymentId !== '') {
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: parseInt(deploymentId),
state: 'failure',
description: 'Deployment failed'
});
}