Skip to content

Test Terminal Follows Scrolling (#78) #38

Test Terminal Follows Scrolling (#78)

Test Terminal Follows Scrolling (#78) #38

Workflow file for this run

name: Build Runtime Image
on:
workflow_dispatch:
pull_request:
branches: [main, master]
types: [opened, synchronize, reopened]
paths:
- "sandbox/**"
- ".github/workflows/build-runtime.yml"
- "!sandbox/*.md"
push:
branches: [main, master]
paths:
- "sandbox/**"
- ".github/workflows/build-runtime.yml"
- "!sandbox/*.md"
permissions:
pull-requests: write
packages: write
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }}
jobs:
build-runtime-images:
name: Build Runtime Docker Images
permissions:
packages: write
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Convert repository owner to lowercase
id: repo-owner
run: |
echo "lowercase=${GITHUB_REPOSITORY_OWNER@L}" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
if: ${{ github.event_name != 'pull_request' && github.actor != 'dependabot[bot]' && env.DOCKERHUB_USERNAME != '' }}
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
if: ${{ github.event_name != 'pull_request' && github.actor != 'dependabot[bot]' }}
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ steps.repo-owner.outputs.lowercase }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ steps.repo-owner.outputs.lowercase }}/fullstack-web-runtime
${{ env.DOCKERHUB_USERNAME && format('docker.io/{0}/fullstack-web-runtime', env.DOCKERHUB_USERNAME) || '' }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix=sha-
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') || github.ref == format('refs/heads/{0}', 'master') }}
labels: |
org.opencontainers.image.title=FullStack Web Runtime
org.opencontainers.image.description=Full-stack web development runtime with Next.js, shadcn/ui, Claude Code CLI, and container tools
org.opencontainers.image.vendor=${{ steps.repo-owner.outputs.lowercase }}
- name: Build and Push Docker Image
id: docker-build
uses: docker/build-push-action@v6
with:
context: ./sandbox
file: ./sandbox/Dockerfile
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64
tags: ${{ steps.meta.outputs.tags }}
# PR builds: load locally for validation, Push builds: push to registry
push: ${{ github.event_name != 'pull_request' && github.actor != 'dependabot[bot]' }}
load: ${{ github.event_name == 'pull_request' }}
cache-from: type=gha,scope=runtime-amd64
cache-to: type=gha,mode=max,scope=runtime-amd64
- name: Comment on PR
if: github.event_name == 'pull_request' && always()
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
const buildSuccess = '${{ steps.docker-build.outcome }}' === 'success';
const emoji = buildSuccess ? '✅' : '❌';
const status = buildSuccess ? 'Success' : 'Failed';
let body = `## ${emoji} FullStack Web Runtime Build ${status}\n\n`;
body += `### Build Details\n\n`;
body += `| Item | Value |\n`;
body += `|------|-------|\n`;
body += `| Build Status | ${buildSuccess ? '✅ Passed' : '❌ Failed'} |\n`;
body += `| Platforms | linux/amd64 (PR validation) |\n`;
body += `| Push to Registry | ⚠️ No (PR build only) |\n`;
body += `| Base Image | ubuntu:24.04 |\n`;
body += `| Node.js | 22.x LTS |\n`;
body += `| Components | Claude Code CLI, ttyd, Next.js, Prisma, PostgreSQL client, Buildah |\n\n`;
if (buildSuccess) {
body += `### 📦 Runtime image will be published after merge\n\n`;
body += `**Note**: PR builds only verify the Docker build process. `;
body += `Images are pushed to registries only when merged to main.\n\n`;
body += `**Registries**:\n`;
body += `- GitHub Container Registry: \`ghcr.io/${{ steps.repo-owner.outputs.lowercase }}/fullstack-web-runtime\`\n`;
if ('${{ env.DOCKERHUB_USERNAME }}') {
body += `- Docker Hub: \`docker.io/${{ env.DOCKERHUB_USERNAME }}/fullstack-web-runtime\`\n`;
}
body += `\n**Included Tools**:\n`;
body += `- Node.js 22.x + npm, pnpm, yarn\n`;
body += `- Claude Code CLI (@anthropic-ai/claude-code)\n`;
body += `- Next.js with shadcn/ui components\n`;
body += `- PostgreSQL 16 client\n`;
body += `- Container tools (Buildah, Podman, Skopeo)\n`;
body += `- Development tools (Git, GitHub CLI, ripgrep, jq, etc.)\n`;
body += `- ttyd web terminal\n`;
} else {
body += `### ❌ Build Failed\n\n`;
body += `Please check the workflow logs for detailed error information.\n`;
}
body += `\n---\n`;
body += `**Commit**: \`${{ github.sha }}\`\n`;
body += `**Triggered by**: @${{ github.actor }}\n`;
try {
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('FullStack Web Runtime Build')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
} catch (error) {
console.log('Failed to post comment:', error.message);
console.log('This might be expected for PRs from forks');
}
- name: Generate build summary
if: ${{ github.event_name != 'pull_request' && github.actor != 'dependabot[bot]' && always() }}
run: |
echo "## 🚀 Runtime Image Build & Push Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.docker-build.outcome }}" = "success" ]; then
echo "- ✅ Runtime build successful" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Platform: \`linux/amd64\`" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Pushed to GitHub Container Registry: \`ghcr.io/${{ steps.repo-owner.outputs.lowercase }}/fullstack-web-runtime\`" >> $GITHUB_STEP_SUMMARY
if [ -n "${{ env.DOCKERHUB_USERNAME }}" ]; then
echo "- ✅ Pushed to Docker Hub: \`docker.io/${{ env.DOCKERHUB_USERNAME }}/fullstack-web-runtime\`" >> $GITHUB_STEP_SUMMARY
fi
else
echo "- ❌ Build or push failed" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Runtime Image Details" >> $GITHUB_STEP_SUMMARY
echo "- **Base**: Ubuntu 24.04" >> $GITHUB_STEP_SUMMARY
echo "- **Node.js**: 22.x LTS" >> $GITHUB_STEP_SUMMARY
echo "- **PostgreSQL Client**: 16" >> $GITHUB_STEP_SUMMARY
echo "- **Claude Code CLI**: @anthropic-ai/claude-code" >> $GITHUB_STEP_SUMMARY
echo "- **Next.js**: Latest with shadcn/ui components" >> $GITHUB_STEP_SUMMARY
echo "- **Container Tools**: Buildah, Podman, Skopeo" >> $GITHUB_STEP_SUMMARY
echo "- **Terminal**: ttyd web-based terminal" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Build Information" >> $GITHUB_STEP_SUMMARY
echo "- **Commit SHA**: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Branch**: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Triggered by**: @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
echo "- **Event**: \`${{ github.event_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Build time**: $(date '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Image Tags" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Usage Example" >> $GITHUB_STEP_SUMMARY
echo '```bash' >> $GITHUB_STEP_SUMMARY
echo "# Pull the latest image" >> $GITHUB_STEP_SUMMARY
echo "docker pull ghcr.io/${{ steps.repo-owner.outputs.lowercase }}/fullstack-web-runtime:latest" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "# Run with environment variables" >> $GITHUB_STEP_SUMMARY
echo "docker run -d -p 7681:7681 -p 3000:3000 \\" >> $GITHUB_STEP_SUMMARY
echo " -e ANTHROPIC_AUTH_TOKEN=your_token \\" >> $GITHUB_STEP_SUMMARY
echo " -e PROJECT_NAME=my-project \\" >> $GITHUB_STEP_SUMMARY
echo " ghcr.io/${{ steps.repo-owner.outputs.lowercase }}/fullstack-web-runtime:latest" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY