refactor: Break down monolithic API into modular router structure #22
Workflow file for this run
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | name: Beta Release on PR | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| workflow_dispatch: | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| build-and-deploy: | |
| if: github.actor != 'dependabot[bot]' && (github.event.pull_request.draft == false || github.event_name != 'pull_request') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| pull-requests: write | |
| issues: write | |
| deployments: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} | |
| ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} | |
| fetch-depth: 0 | |
| - name: Prepare deployment variables | |
| id: prepare_deployment | |
| run: | | |
| TIMESTAMP=$(date +%Y%m%d-%H%M%S) | |
| if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
| SANITIZED_BRANCH=$(echo "${{ github.head_ref }}" | tr -cs '[:alnum:]' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//') | |
| PR_NUMBER="${{ github.event.number }}" | |
| TAG_SUFFIX="pr-${PR_NUMBER}-${TIMESTAMP}" | |
| else | |
| SANITIZED_BRANCH=$(echo "${{ github.ref_name }}" | tr -cs '[:alnum:]' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//') | |
| TAG_SUFFIX="manual-${SANITIZED_BRANCH}-${TIMESTAMP}" | |
| fi | |
| echo "sanitized_branch=$SANITIZED_BRANCH" >> $GITHUB_OUTPUT | |
| echo "tag_suffix=$TAG_SUFFIX" >> $GITHUB_OUTPUT | |
| echo "pr_number=${{ github.event.number }}" >> $GITHUB_OUTPUT | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=raw,value=${{ steps.prepare_deployment.outputs.tag_suffix }} | |
| type=raw,value=beta-{{date 'YYYYMMDD-HHmmss'}} | |
| type=sha,prefix=sha- | |
| labels: | | |
| org.opencontainers.image.title=BioAnalyzer Beta | |
| org.opencontainers.image.description=BioAnalyzer Beta Release for PR Testing | |
| org.opencontainers.image.version=1.0.0-beta | |
| org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} | |
| org.opencontainers.image.revision=${{ github.sha }} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Generate deployment URL | |
| id: url | |
| run: | | |
| PR_NUMBER=${{ github.event.number }} | |
| BETA_URL="https://bioanalyzer-beta-$PR_NUMBER.vercel.app" | |
| echo "beta_url=$BETA_URL" >> $GITHUB_OUTPUT | |
| - name: Create deployment comment | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prNumber = ${{ github.event.number }}; | |
| const betaUrl = '${{ steps.url.outputs.beta_url }}'; | |
| const comment = "🚀 **Beta Release Ready for Testing**\n\n" + | |
| "🔗 [Live Demo](" + betaUrl + ")"; | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| }); | |
| const existingComment = comments.data.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('🚀 **Beta Release Ready for Testing**') | |
| ); | |
| if (existingComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existingComment.id, | |
| body: comment | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: comment | |
| }); | |
| } | |
| - name: Create deployment | |
| id: 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: 'beta', | |
| description: 'Beta release deployment', | |
| auto_merge: false, | |
| required_contexts: [] // allow deployment without checks | |
| }); | |
| core.setOutput("id", deployment.data.id); | |
| - name: Create deployment status | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const deploymentId = ${{ steps.deployment.outputs.id }}; | |
| await github.rest.repos.createDeploymentStatus({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| deployment_id: deploymentId, | |
| state: 'success', | |
| environment: 'beta', | |
| description: 'Beta release deployed successfully', | |
| environment_url: '${{ steps.url.outputs.beta_url }}' | |
| }); | |
| cleanup: | |
| runs-on: ubuntu-latest | |
| if: github.event.action == 'closed' && github.actor != 'dependabot[bot]' | |
| permissions: | |
| packages: write | |
| pull-requests: write | |
| deployments: write | |
| steps: | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Clean up beta images | |
| run: | | |
| PR_NUMBER=${{ github.event.number }} | |
| echo "Cleaning up beta images for PR #$PR_NUMBER" | |
| docker images --format "table {{.Repository}}:{{.Tag}}" | grep "pr-${PR_NUMBER}" || echo "No PR-specific images found" | |
| echo "Cleanup completed for PR #$PR_NUMBER" | |
| - name: Update PR comment | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prNumber = ${{ github.event.number }}; | |
| const comment = "🧹 **Beta Release Cleaned Up**\n\n" + | |
| "PR #" + prNumber + " beta release has been cleaned up."; | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| }); | |
| const existingComment = comments.data.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('Beta Release Cleaned Up') | |
| ); | |
| if (existingComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existingComment.id, | |
| body: comment | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: comment | |
| }); | |
| } |