From d32e47ba6dd740eb828812d92709a86ad0e9cf07 Mon Sep 17 00:00:00 2001 From: Yekta Yazar Date: Fri, 13 Mar 2026 09:50:42 -0700 Subject: [PATCH 1/3] 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 --- .github/workflows/build-and-deploy-dev.yml | 67 ++++++++++++++++++++++ .github/workflows/build-release.yml | 45 +++++++++++++++ .github/workflows/deploy-prod.yml | 28 +++++++++ .github/workflows/deploy.yml | 31 ++++++++++ config.yaml | 31 ++++++++++ docker/Dockerfile.prod | 43 ++++++++++++++ 6 files changed, 245 insertions(+) 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 .github/workflows/deploy.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..8de7434 --- /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 }} + deployment_type: container + docker_network: squirrel-net + migration_command: alembic upgrade head + health_check_path: /docs + 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..8239a2f --- /dev/null +++ b/.github/workflows/deploy-prod.yml @@ -0,0 +1,28 @@ +name: Deploy to Production + +on: + workflow_dispatch: + inputs: + image_tag: + description: 'Release tag to deploy (e.g., v1.2.0)' + required: true + type: string + +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 }} + deployment_type: container + docker_network: squirrel-net + migration_command: alembic upgrade head + health_check_path: /docs + secrets: + database_url: ${{ secrets.PROD_DATABASE_URL }} + redis_url: ${{ secrets.PROD_REDIS_URL }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..336f303 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -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/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..c03b9a7 --- /dev/null +++ b/docker/Dockerfile.prod @@ -0,0 +1,43 @@ +# 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 requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# --- 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 . + +# 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"] From aba67509dcd96ca39be5f7b8e3a71d1e3ad90857 Mon Sep 17 00:00:00 2001 From: Yekta Yazar Date: Tue, 31 Mar 2026 16:12:22 -0700 Subject: [PATCH 2/3] rebased and made changes based on review comments --- docker/Dockerfile.prod | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile.prod b/docker/Dockerfile.prod index c03b9a7..0a77951 100644 --- a/docker/Dockerfile.prod +++ b/docker/Dockerfile.prod @@ -12,8 +12,8 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* # Install Python dependencies -COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +COPY pyproject.toml . +RUN pip install --no-cache-dir . # --- Production stage --- FROM python:3.11-slim @@ -33,6 +33,7 @@ COPY --from=builder /usr/local/bin /usr/local/bin 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 From 9f19cbabd4d90af618ffd65de0adda6ec000f866 Mon Sep 17 00:00:00 2001 From: Yekta Yazar Date: Tue, 31 Mar 2026 16:17:44 -0700 Subject: [PATCH 3/3] RM: deploy.yml, deprecated code --- .github/workflows/deploy.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 336f303..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,31 +0,0 @@ -# [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: