Files
PowderCoatingLogix/CREATE_JENKINS_PROD_DEPLOY.md
spouliot 4f976b1332 Require auth on all work order QR codes and add top view QR
- StatusBump (GET + POST) now requires authentication; routes by job ID
  instead of anonymous ShopAccessCode GUID; records actual user name in
  status history instead of anonymous token string
- WorkOrder action generates a second "View Job" QR in the header linking
  to the authenticated Details page (for verifying specs and seeing catalog
  images on mobile); status bump QR updated to ID-based URL
- WorkOrder view: top QR added to header alongside job number; status bump
  label updated (removed "no login required" copy)
- StatusBump view: updated form routing from asp-route-token to asp-route-id
- HelpKnowledgeBase and Jobs help article updated with two-tier QR docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 13:27:43 -04:00

101 lines
3.5 KiB
Markdown

# 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/<YOUR_SUBSCRIPTION_ID>/resourceGroups/<YOUR_RG>
```
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 |