CI/CD Pipelines
NextGenPoll has 5 GitHub Actions workflows covering continuous integration and deployment for all components.
Pipeline Dependency Map
Deployment Flow
The following diagram illustrates how code moves from a developer's machine to the production environment:

Figure 6: Monitoring deployment status in the GitHub Actions dashboard.
Overview
| Workflow | File | Trigger | What it does |
|---|---|---|---|
| Backend CI | backend-ci.yml | PR / push to backend/** | Compile, test (H2), PMD static analysis |
| Backend CD | backend-cd.yml | After Backend CI succeeds on main | Build JAR, run Flyway migrations, deploy to Azure App Service |
| Frontend CI | frontend-ci.yml | PR / push to frontend/**, powerpoint/**, packages/shared/** | Build Office add-in, build Next.js |
| Frontend CD | frontend-cd.yml | After Frontend CI succeeds on main | Build add-in + frontend, deploy to Azure App Service |
| Docs CD | docs-cd.yml | Push to docs/** on main | Build Docusaurus, deploy to Azure Static Web Apps |
Backend CI (backend-ci.yml)
Triggers: PRs and pushes to backend/**
checkout → Java 25 setup → ./mvnw verify -Dflyway.skip=true
- Uses H2 in-memory database via
SPRING_PROFILES_ACTIVE=test— no PostgreSQL needed. - Flyway is skipped (
-Dflyway.skip=true); schema created byddl-auto=create-dropin H2. - PMD static analysis runs but does not fail the build (
-Dpmd.failOnViolation=false). - Dummy Azure OpenAI env vars are set so the Spring context loads without real credentials.
Required secrets: None (uses dummy values for CI).
Backend CD (backend-cd.yml)
Triggers:
- Automatically when
Backend CIcompletes successfully onmain - Manually via
workflow_dispatch
checkout → Java 25 setup → Build JAR → Flyway migrate (Azure DB) → Deploy JAR to App Service
Key steps:
- Build JAR —
./mvnw package -DskipTests -Dflyway.skip=true - Run migrations —
./mvnw flyway:repair flyway:migrateagainst Azure PostgreSQL using DB secrets - Rename JAR —
app.jar(required by App Service startup command) - Deploy —
azure/webapps-deploy@v3usingAZURE_BACKEND_PUBLISH_PROFILE
Required secrets:
AZURE_BACKEND_PUBLISH_PROFILEAZURE_DB_URL,AZURE_DB_USERNAME,AZURE_DB_PASSWORD
Flyway migrations run before the new JAR is deployed. This ensures the schema is ready before the new code starts. Never swap this order.
Frontend CI (frontend-ci.yml)
Triggers: PRs and pushes to frontend/**, powerpoint/**, packages/shared/**, package.json, package-lock.json
checkout → Node 24 setup → npm ci → Build Office add-in → Copy add-in to frontend/public/addin/ → Build frontend
- The Office add-in must be built before the Next.js build because the frontend serves add-in assets from
/public/addin/. - No deployment; validates that the build succeeds.
Required secrets: None.
Frontend CD (frontend-cd.yml)
Triggers:
- Automatically when
Frontend CIcompletes successfully onmain - Manually via
workflow_dispatch
Uses a concurrency group (azure-app-nextgenpoll-web) to prevent simultaneous deploys.
checkout → Node 24 setup → npm ci → Build add-in → Build frontend → Package standalone → Deploy to App Service
Key steps:
- Build add-in —
npm run buildinpowerpoint/ - Build frontend — copies
powerpoint/dist/*intofrontend/public/addin/, thennpm run build - Package standalone — copies
static/andpublic/into.next/standalone(required foroutput: "standalone") - Deploy —
azure/webapps-deploy@v3deploys the.next/standalonedirectory
Required secrets:
AZURE_FRONTEND_PUBLISH_PROFILE- All
NEXT_PUBLIC_*andAZURE_TENANT_IDbuild-time secrets
Docs CD (docs-cd.yml)
Triggers:
- Push to
docs/**onmain - Manually via
workflow_dispatch
checkout → Node 24 setup → npm ci → Build Docusaurus → Deploy to Static Web Apps
- Build —
npm run build --workspace=docsoutputs todocs/build/ - Deploy —
Azure/static-web-apps-deploy@v1usingAZURE_STATIC_WEB_APPS_API_TOKEN_DOCS
Required secrets:
AZURE_STATIC_WEB_APPS_API_TOKEN_DOCS
Adding a New Workflow
- Create
.github/workflows/{name}.yml. - Follow the naming convention:
{component}-{ci|cd}.yml. - For CD workflows, gate with
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}to prevent deploys from failed builds. - Document required secrets in Environment Variables.
Re-running a Failed Deployment
- Go to GitHub → Actions → find the failed workflow run.
- Click Re-run failed jobs (not "Re-run all jobs") to avoid re-running steps that already succeeded.
- If a DB migration failed, check Flyway's output in the logs and run
flyway:repairlocally against the production DB before re-deploying.