From 024da8a06915dbc16473c0441b22a65ddb237d50 Mon Sep 17 00:00:00 2001 From: Yekta Yazar Date: Fri, 13 Mar 2026 09:50:42 -0700 Subject: [PATCH] ENH: Add container deployment workflows with secrets for dev and prod - Add build-and-deploy-dev, build-release, deploy-prod, deploy workflows - Add config.yaml and Dockerfile.prod for software factory onboarding - RM: deploy.yml, deprecated code --- .github/workflows/build-and-deploy-dev.yml | 67 ++++++++++++++++++++++ .github/workflows/build-release.yml | 45 +++++++++++++++ .github/workflows/deploy-prod.yml | 33 +++++++++++ .github/workflows/pre-commit.yml | 6 +- .github/workflows/tests.yml | 2 - config.yaml | 31 ++++++++++ docker/Dockerfile.prod | 44 ++++++++++++++ 7 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/build-and-deploy-dev.yml create mode 100644 .github/workflows/build-release.yml create mode 100644 .github/workflows/deploy-prod.yml create mode 100644 config.yaml create mode 100644 docker/Dockerfile.prod diff --git a/.github/workflows/build-and-deploy-dev.yml b/.github/workflows/build-and-deploy-dev.yml new file mode 100644 index 0000000..33c395d --- /dev/null +++ b/.github/workflows/build-and-deploy-dev.yml @@ -0,0 +1,67 @@ +name: Build and Deploy (Dev) + +on: + push: + branches: [main] + +permissions: + contents: read + packages: write + deployments: write + actions: read + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + outputs: + image_tag: ${{ steps.vars.outputs.image_tag }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set image tag + id: vars + run: echo "image_tag=main-${GITHUB_SHA::7}" >> $GITHUB_OUTPUT + + - name: Log in to GHCR + 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=sha,prefix=main- + type=raw,value=latest + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: docker/Dockerfile.prod + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + deploy: + needs: build-and-push + uses: ad-build-test/build-system-playbooks/.github/workflows/request-deployment.yml@main + with: + deploy_to_container_dev: true + tag: ${{ needs.build-and-push.outputs.image_tag }} + playbook: container_module/container_deploy.yml + docker_network: squirrel-net + migration_command: alembic upgrade head + health_check_path: /health + secrets: + database_url: ${{ secrets.DEV_DATABASE_URL }} + redis_url: ${{ secrets.DEV_REDIS_URL }} diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 0000000..4bc8fcb --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,45 @@ +name: Build Release Image + +on: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Log in to GHCR + 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=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: docker/Dockerfile.prod + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml new file mode 100644 index 0000000..bdba0d3 --- /dev/null +++ b/.github/workflows/deploy-prod.yml @@ -0,0 +1,33 @@ +name: Deploy to Production + +on: + workflow_dispatch: + inputs: + image_tag: + description: 'Release tag to deploy (e.g., v1.2.0)' + required: true + type: string + migration_command: + description: 'Migration command (default: alembic upgrade head). For rollbacks use e.g. alembic downgrade ' + required: false + type: string + default: 'alembic upgrade head' + +permissions: + deployments: write + contents: read + actions: read + +jobs: + deploy: + uses: ad-build-test/build-system-playbooks/.github/workflows/request-deployment.yml@main + with: + deploy_to_container_prod: true + tag: ${{ inputs.image_tag }} + playbook: container_module/container_deploy.yml + docker_network: squirrel-net + migration_command: ${{ inputs.migration_command }} + health_check_path: /health + secrets: + database_url: ${{ secrets.PROD_DATABASE_URL }} + redis_url: ${{ secrets.PROD_REDIS_URL }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 04f86a3..a100dcb 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -9,6 +9,6 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - uses: pre-commit/action@v3.0.0 \ No newline at end of file + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3bf94ea..5910b62 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,11 +4,9 @@ on: pull_request: branches: - main - - master push: branches: - main - - master workflow_dispatch: jobs: diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..336f303 --- /dev/null +++ b/config.yaml @@ -0,0 +1,31 @@ +# [Required] +# Basic component information +repo: react-squirrel-backend +organization: ad-build-test +url: https://github.com/ad-build-test/react-squirrel-backend +description: test react-squirrel-backend + +# [Required] +# Continous integration +approvalRule: all +testingCriteria: all +issueTracker: github +jiraProjectKey: n/a + +# [Required] +# Type of deployment +# Types: [ioc, hla, tools, matlab, pydm, container] +deploymentType: container + +# [Optional] +# Build method for building the component +# Can be a simple command like 'make' +# build: + +# [Optional] +# Environments this app runs on +# environments: + +# [Optional] +# Directories and files needed to run application +# runtimeDependencies: diff --git a/docker/Dockerfile.prod b/docker/Dockerfile.prod new file mode 100644 index 0000000..0a77951 --- /dev/null +++ b/docker/Dockerfile.prod @@ -0,0 +1,44 @@ +# Multi-stage build for production +FROM python:3.11-slim AS builder + +WORKDIR /app + +# Install system build dependencies for PyEPICS and aioca +RUN apt-get update && apt-get install -y \ + libreadline-dev \ + gcc \ + g++ \ + make \ + && rm -rf /var/lib/apt/lists/* + +# Install Python dependencies +COPY pyproject.toml . +RUN pip install --no-cache-dir . + +# --- Production stage --- +FROM python:3.11-slim + +WORKDIR /app + +# Install only runtime dependencies +RUN apt-get update && apt-get install -y \ + libreadline8 \ + && rm -rf /var/lib/apt/lists/* + +# Copy installed packages from builder +COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages +COPY --from=builder /usr/local/bin /usr/local/bin + +# Copy application code +COPY app/ ./app/ +COPY alembic/ ./alembic/ +COPY alembic.ini . +COPY scripts/ ./scripts/ + +# Create non-root user +RUN useradd -m -r appuser && chown -R appuser:appuser /app +USER appuser + +EXPOSE 8000 + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]