4f976b1332
- 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>
101 lines
3.5 KiB
Markdown
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 |
|