# Jenkins Production Deployment Setup ## What was created | File | Purpose | |---|---| | `Jenkinsfile` | Production pipeline — manual trigger only | | `jenkins/Dockerfile` | Custom image: Jenkins LTS + .NET 8 + Azure CLI + sqlcmd + dotnet-ef | | `.config/dotnet-tools.json` | Tool manifest pinning dotnet-ef 8.0.11 | --- ## One-time setup steps ### 1. Build and run your custom Jenkins image On your Ubuntu Docker host: ```bash cd /path/to/repo docker build -t pcl-jenkins ./jenkins docker run -d -p 8080:8080 -p 50000:50000 \ -v jenkins_home:/var/jenkins_home \ --name pcl-jenkins pcl-jenkins ``` If you already have a Jenkins container running, rebuild the image and recreate the container (volume data is preserved). --- ### 2. Create an Azure Service Principal Run this once from **your machine** (not Jenkins): ```bash az login az ad sp create-for-rbac \ --name "pcl-jenkins-deploy" \ --role contributor \ --scopes /subscriptions//resourceGroups/ ``` Save the output — you need `appId`, `password`, `tenant`, and your subscription ID. --- ### 3. Create a SQL Server deployment login In SSMS or Azure portal query editor, run on your Azure SQL server (as admin): ```sql CREATE LOGIN pcl_deploy WITH PASSWORD = 'ChooseAStrongPassword123!'; USE PowderCoatingDb; CREATE USER pcl_deploy FOR LOGIN pcl_deploy; ALTER ROLE db_owner ADD MEMBER pcl_deploy; -- needs DDL rights for migrations ``` > After migrations are stable you can demote this to `db_datareader`/`db_datawriter` + explicit DDL permissions, but `db_owner` is easiest to start. --- ### 4. Add Jenkins credentials Go to **Jenkins → Manage Jenkins → Credentials → System → Global** and add 10 **Secret Text** credentials with these exact IDs: | Credential ID | Value | |---|---| | `PCL_AZURE_CLIENT_ID` | `appId` from step 2 | | `PCL_AZURE_CLIENT_SECRET` | `password` from step 2 | | `PCL_AZURE_TENANT_ID` | `tenant` from step 2 | | `PCL_AZURE_SUBSCRIPTION_ID` | Your Azure subscription GUID | | `PCL_AZURE_RESOURCE_GROUP` | e.g. `powder-coating-prod` | | `PCL_AZURE_APP_NAME` | Your App Service name (e.g. `pcl-app`) | | `PCL_SQL_SERVER` | e.g. `pcl-sql.database.windows.net` | | `PCL_SQL_DATABASE` | e.g. `PowderCoatingDb` | | `PCL_SQL_USER` | `pcl_deploy` | | `PCL_SQL_PASSWORD` | The password you set in step 3 | --- ### 5. Create the Jenkins Pipeline job 1. **New Item → Pipeline** — name it "PCL Production Deploy" 2. Under **Pipeline**, set **Definition** = `Pipeline script from SCM` 3. SCM = Git, repo URL, branch `*/master`, Script Path = `Jenkinsfile` 4. **Do NOT** check any triggers (no poll SCM, no build periodically, no webhook) 5. Save To deploy: open the job → **Build Now**. That's your "Go!" button. --- ## How each stage works | Stage | What happens | |---|---| | **Checkout** | Pulls `master`, logs the commit SHA | | **Build & Test** | `dotnet restore` → `dotnet build -c Release` → `dotnet test` (results published to Jenkins) | | **Publish** | `dotnet publish -c Release` → `./publish/` | | **Generate Migration Script** | `dotnet ef migrations script --idempotent` — no DB connection needed. Script is **archived as a build artifact** so you can inspect it before or after | | **Apply Migration** | `sqlcmd` runs the idempotent script against Azure SQL. `-b` flag makes it fail-fast on errors | | **Deploy to Azure** | ZIP the publish folder, `az webapp deployment source config-zip` | | **Smoke Test** | `curl` the App Service root URL — expects HTTP 200 or 302 |