@marcfargas/skills 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,46 @@
1
+ {
2
+ "version": "1.0",
3
+ "repository": "https://github.com/marcfargas/skills",
4
+ "skills": [
5
+ {
6
+ "name": "azcli",
7
+ "description": "Azure CLI (az). Use when: managing Azure resources, deploying to App Service/Functions/Container Apps/AKS, working with Storage, SQL Database, Cosmos DB, VMs, VNets, NSGs, Key Vault, Entra ID (Azure AD), RBAC, Service Bus, Event Hubs, Container Registry, Azure Monitor, DNS, or any Azure service. Also covers: authentication, subscription management, CI/CD integration (GitHub Actions/Azure DevOps), Bicep/ARM templates, managed identities, and infrastructure automation.",
8
+ "path": "azure/azcli"
9
+ },
10
+ {
11
+ "name": "gcloud",
12
+ "description": "Google Cloud Platform CLI (gcloud, gcloud storage, bq). Use when: managing GCP resources, deploying to Cloud Run/Cloud Functions/GKE/App Engine, working with Cloud Storage, BigQuery, IAM, Compute Engine, Cloud SQL, Pub/Sub, Secret Manager, Artifact Registry, Cloud Build, Cloud Scheduler, Cloud Tasks, Vertex AI, VPC/networking, DNS, logging/monitoring, or any GCP service. Also covers: authentication, project/config management, CI/CD integration, serverless deployments, container registry, docker push to GCP, managing secrets, Workload Identity Federation, and infrastructure automation.",
13
+ "path": "google-cloud/gcloud"
14
+ },
15
+ {
16
+ "name": "pm2",
17
+ "description": "Process management with PM2 — start, stop, restart, monitor long-running processes. Use when: keeping services alive, auto-restart on crash, managing daemon processes, ecosystem configs, log management, startup scripts, process monitoring. Triggers: pm2, process manager, keep alive, daemon, auto-restart, ecosystem config, process monitoring.",
18
+ "path": "process/pm2"
19
+ },
20
+ {
21
+ "name": "pre-release",
22
+ "description": "Pre-release review and changeset generation for npm packages using @changesets/cli. Use when: preparing a release, generating changelogs, pre-release checklist, version bump, writing release notes, reviewing README before publish. Triggers: \"prepare release\", \"pre-release\", \"generate changelog\", \"write changesets\", \"release checklist\".",
23
+ "path": "release/pre-release"
24
+ },
25
+ {
26
+ "name": "repo-hygiene",
27
+ "description": "Periodic repository health check — dependencies, git, CI/CD, code quality, docs, security. Use when: onboarding to a repo, weekly maintenance, after big refactors, before audits, \"is this repo in good shape?\". Triggers: \"repo hygiene\", \"health check\", \"repo health\", \"clean up repo\", \"maintenance check\", \"audit repo\", \"repo audit\".",
28
+ "path": "maintenance/repo-hygiene"
29
+ },
30
+ {
31
+ "name": "sheet-model",
32
+ "description": "Headless spreadsheet engine for financial modeling, data analysis, and scenario comparison. Use when: building financial models with ratios and what-if scenarios, computing derived values from tabular data with formulas, producing .xlsx files with live formulas (not static values) for human review, any task where the agent would otherwise write imperative code to manipulate numbers that a spreadsheet does naturally. Triggers: financial model, scenario analysis, ratio computation, balance sheet, P&L, what-if, sensitivity analysis, banking ratios, spreadsheet model, build a model, projection, forecast. Do NOT use for: simple CSV/Excel read/write (use the xlsx skill), chart-only tasks, or data volumes exceeding ~5000 rows.",
33
+ "path": "sheet-model"
34
+ },
35
+ {
36
+ "name": "vhs",
37
+ "description": "Record terminal sessions as GIF/MP4/WebM using VHS (Charm.sh). Use when: create demo GIF, record terminal, terminal recording, demo video, tape file, animate CLI, screencast terminal, showcase command output, README demo, document CLI tool, generate terminal animation.",
38
+ "path": "terminal/vhs"
39
+ },
40
+ {
41
+ "name": "web-search",
42
+ "description": "Web search and content extraction using ddgs (multi-engine metasearch). No API keys required. Use when: searching documentation, facts, current information, news, fetching web content. Triggers: search the web, look up, find information, web search, news search, fetch page.",
43
+ "path": "search/web-search"
44
+ }
45
+ ]
46
+ }
package/README.md CHANGED
@@ -6,10 +6,13 @@ Reusable skills for AI coding agents. Works with [pi](https://github.com/marioze
6
6
 
7
7
  | Category | Skill | Description |
8
8
  |----------|-------|-------------|
9
+ | ☁️ Azure | [azcli](azure/azcli/) | Azure CLI with agent safety model — hub + reference files |
9
10
  | ☁️ Google Cloud | [gcloud](google-cloud/gcloud/) | GCP CLI with agent safety model — hub + 7 reference files |
11
+ | 🔧 Maintenance | [repo-hygiene](maintenance/repo-hygiene/) | Periodic repo health check — deps, git, CI, code quality, docs, security |
10
12
  | ⚙️ Process | [pm2](process/pm2/) | Process management — keep services alive, auto-restart, monitoring, ecosystem configs |
11
13
  | 🚀 Release | [pre-release](release/pre-release/) | Pre-release checklist + AI-written changesets via @changesets/cli |
12
14
  | 🔍 Search | [web-search](search/web-search/) | Web search + content extraction via [ddgs](https://github.com/deedy5/ddgs) — no API keys |
15
+ | 📊 Modeling | [sheet-model](sheet-model/) | Headless spreadsheet engine for financial modeling, scenario analysis, .xlsx with live formulas |
13
16
  | 🎬 Terminal | [vhs](terminal/vhs/) | Record terminal sessions as GIF/MP4 with [VHS](https://github.com/charmbracelet/vhs) |
14
17
 
15
18
  ## Install
@@ -67,16 +70,21 @@ Skills use a **hub + spoke** architecture. The SKILL.md hub is ~140 lines — ju
67
70
 
68
71
  ## Structure
69
72
 
70
- ```
73
+ ```text
71
74
  skills/
75
+ ├── azure/
76
+ │ └── azcli/ # Azure CLI skill
72
77
  ├── google-cloud/
73
78
  │ └── gcloud/ # 8 files, ~1100 lines total
79
+ ├── maintenance/
80
+ │ └── repo-hygiene/ # 1 file — periodic health check
74
81
  ├── process/
75
82
  │ └── pm2/ # 1 file
76
83
  ├── release/
77
84
  │ └── pre-release/ # 1 file
78
85
  ├── search/
79
86
  │ └── web-search/ # SKILL.md + search.js + content.js
87
+ ├── sheet-model/ # Headless spreadsheet engine
80
88
  ├── terminal/
81
89
  │ └── vhs/ # 1 file
82
90
  └── README.md
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: azcli
3
+ description: >-
4
+ Azure CLI (az). Use when: managing Azure resources, deploying to App Service/Functions/Container Apps/AKS,
5
+ working with Storage, SQL Database, Cosmos DB, VMs, VNets, NSGs, Key Vault,
6
+ Entra ID (Azure AD), RBAC, Service Bus, Event Hubs, Container Registry,
7
+ Azure Monitor, DNS, or any Azure service.
8
+ Also covers: authentication, subscription management, CI/CD integration (GitHub Actions/Azure DevOps),
9
+ Bicep/ARM templates, managed identities, and infrastructure automation.
10
+ ---
11
+
12
+ # azcli — Azure Command-Line Interface
13
+
14
+ Command-line interface for managing Azure resources.
15
+ Covers `az` and its 200+ command groups for all Azure services.
16
+
17
+ Docs: https://learn.microsoft.com/en-us/cli/azure/
18
+
19
+ ## Platform Notes (Windows + Git Bash)
20
+
21
+ - Install: `winget install --exact --id Microsoft.AzureCLI` (preferred) or MSI from https://aka.ms/installazurecliwindows
22
+ - After install/update: **close and reopen terminal** — required for PATH
23
+ - Config: `~/.azure/` (credentials, config, profiles)
24
+ - Secrets: use Key Vault or env vars, **never commit credentials**
25
+ - Extensions: `az extension add --name NAME` (some features require extensions)
26
+ - Version: `az version` (check for updates: `az upgrade`)
27
+
28
+ ### ⚠️ Quoting Gotchas
29
+
30
+ Git Bash, PowerShell, and cmd have different quoting rules for `--query` (JMESPath):
31
+
32
+ ```bash
33
+ # Git Bash — use single quotes for JMESPath
34
+ az vm list --query '[].name' -o tsv
35
+
36
+ # PowerShell — use single quotes or escaped double quotes
37
+ az vm list --query '[].name' -o tsv
38
+
39
+ # Avoid: Git Bash may mangle double-quoted JMESPath
40
+ ```
41
+
42
+ > **⚠️ Cost**: Commands that create resources (VMs, databases, clusters) incur
43
+ > Azure charges. Always confirm subscription and region before creating.
44
+
45
+ ## Agent Safety Model
46
+
47
+ Operations classified by risk. **Follow this model for all az commands.**
48
+
49
+ | Level | Gate | Examples |
50
+ |-------|------|----------|
51
+ | **READ** | Proceed autonomously | `list`, `show`, `get`, `account show`, `monitor log-analytics query` |
52
+ | **WRITE** | Confirm with user; note cost if billable | `create`, `deploy`, `update`, `az storage blob upload` |
53
+ | **DESTRUCTIVE** | Always confirm; show what's affected | `delete`, `purge`, `az group delete`, RBAC removal |
54
+ | **EXPENSIVE** | Confirm + state approximate cost | AKS clusters (~$70+/mo), SQL Database (~$5-2k/mo), VMs (~$5-2k/mo) |
55
+ | **SECURITY** | Confirm + explain impact | NSG rules opening ports, `--allow-unauthenticated`, RBAC owner/contributor grants, Key Vault access policies |
56
+ | **FORBIDDEN** | Refuse; escalate to human | `az ad app credential reset` with plaintext secrets, `az group delete` on production RGs, passwords in CLI args |
57
+
58
+ **Rules**:
59
+
60
+ - **Never combine `--yes` with destructive operations** — it suppresses the only safety gate
61
+ - **Never put passwords/secrets as command-line arguments** — visible in process list & shell history
62
+ - **Always use `-o json`** for machine-parseable output (agents can't reliably parse tables)
63
+ - **When in doubt, treat as DESTRUCTIVE**
64
+
65
+ ## Command Structure
66
+
67
+ ```text
68
+ az [GROUP] [SUBGROUP] COMMAND [ARGS] [FLAGS]
69
+ ```
70
+
71
+ Key global flags: `--subscription`, `--output` (`-o`), `--query`, `--verbose`, `--debug`, `--only-show-errors`, `--yes`
72
+
73
+ ## Service Reference
74
+
75
+ | Service | File | Key Commands |
76
+ |---------|------|-------------|
77
+ | Auth & Config | [auth.md](auth.md) | Login, service principals, managed identities, subscriptions, config |
78
+ | IAM & Resources | [iam.md](iam.md) | Resource groups, RBAC, Entra ID (Azure AD), Key Vault |
79
+ | Compute & Networking | [compute.md](compute.md) | VMs, VNets, NSGs, DNS, load balancers, monitoring |
80
+ | Serverless & Containers | [serverless.md](serverless.md) | App Service, Functions, Container Apps, AKS, Container Registry |
81
+ | Storage | [storage.md](storage.md) | Storage accounts, blobs, file shares, queues, tables |
82
+ | Data | [data.md](data.md) | SQL Database, Cosmos DB, Service Bus, Event Hubs |
83
+ | Automation & CI/CD | [automation.md](automation.md) | Scripting, output formats, JMESPath, Bicep/ARM, GitHub Actions |
84
+
85
+ **Read the per-service file for full command reference.**
86
+
87
+ ## Pre-Flight Checks
88
+
89
+ Before working with any Azure service:
90
+
91
+ ```bash
92
+ # 1. Logged in?
93
+ az account show -o json
94
+
95
+ # 2. Correct subscription?
96
+ az account show --query '{Name:name, Id:id, State:state}' -o json
97
+
98
+ # 3. Change subscription if needed
99
+ az account set --subscription "<name-or-id>"
100
+
101
+ # 4. Default location set?
102
+ az config get defaults.location 2>/dev/null
103
+
104
+ # 5. Set default location (optional)
105
+ az config set defaults.location=westeurope
106
+
107
+ # 6. Resource provider registered? (most are auto-registered)
108
+ az provider show --namespace Microsoft.ContainerApp --query "registrationState" -o tsv
109
+ az provider register --namespace Microsoft.ContainerApp --wait
110
+ ```
111
+
112
+ ## Troubleshooting
113
+
114
+ | Problem | Diagnosis | Fix |
115
+ |---------|-----------|-----|
116
+ | Auth failure | `az account show` | `az login` or check service principal |
117
+ | Permission denied | Check RBAC (see [iam.md](iam.md)) | Grant correct role |
118
+ | Provider not registered | Error says which provider | `az provider register --namespace Microsoft.X` |
119
+ | Quota exceeded | Error message | Request increase in Portal or `az quota` |
120
+ | Wrong subscription | `az account show` | `az account set --subscription X` |
121
+ | Wrong region | Check resource's `location` | Recreate in correct region |
122
+ | Extension missing | `az extension list` | `az extension add --name NAME` |
123
+ | Slow commands | Large result set | Use `--query`, `--top`, or `--output tsv` |
124
+
125
+ ```bash
126
+ # Debug mode
127
+ az vm list --debug 2>&1 | head -50
128
+
129
+ # Full environment info
130
+ az version
131
+ az account show -o json
132
+ ```
133
+
134
+ ## Quick Reference
135
+
136
+ | Task | Command |
137
+ |------|---------|
138
+ | Login | `az login` |
139
+ | Set subscription | `az account set --subscription "NAME_OR_ID"` |
140
+ | Current subscription | `az account show -o json` |
141
+ | List subscriptions | `az account list -o table` |
142
+ | Register provider | `az provider register --namespace Microsoft.X` |
143
+ | List anything | `az RESOURCE list -o json` |
144
+ | Show anything | `az RESOURCE show --name NAME -g RG -o json` |
145
+ | JSON output | `-o json` |
146
+ | TSV (single values) | `-o tsv` |
147
+ | JMESPath query | `--query "expression"` |
148
+ | Suppress prompts ⚠️ | `--yes` — suppresses ALL confirmations |
149
+ | Help | `az RESOURCE --help` or `az find "search term"` |
150
+ | Upgrade CLI | `az upgrade` |
@@ -0,0 +1,160 @@
1
+ # Auth & Configuration
2
+
3
+ ## Authentication Methods
4
+
5
+ | Method | Use Case |
6
+ |--------|----------|
7
+ | Interactive (`az login`) | Local development |
8
+ | Service principal | Scripts, CI/CD |
9
+ | Managed identity | Azure-hosted workloads (VMs, App Service, Functions) |
10
+ | Device code | Headless / remote terminals |
11
+
12
+ ## Interactive Login
13
+
14
+ ```bash
15
+ # Opens browser for sign-in
16
+ az login
17
+
18
+ # Device code flow (headless / SSH sessions)
19
+ az login --use-device-code
20
+
21
+ # Specific tenant
22
+ az login --tenant TENANT_ID
23
+
24
+ # Check who's logged in
25
+ az account show -o json
26
+
27
+ # List all accounts
28
+ az account list -o table
29
+
30
+ # Logout
31
+ az logout
32
+ ```
33
+
34
+ ## Service Principal (CI/CD, Automation)
35
+
36
+ **Prefer managed identities when running on Azure. Use service principals for external CI/CD.**
37
+
38
+ ```bash
39
+ # Create service principal with Contributor role on a subscription
40
+ az ad sp create-for-rbac --name "my-ci-sp" \
41
+ --role Contributor \
42
+ --scopes /subscriptions/SUBSCRIPTION_ID
43
+
44
+ # Output (save securely — shown only once):
45
+ # {
46
+ # "appId": "...",
47
+ # "displayName": "my-ci-sp",
48
+ # "password": "...",
49
+ # "tenant": "..."
50
+ # }
51
+
52
+ # Login with service principal
53
+ az login --service-principal \
54
+ --username APP_ID \
55
+ --password CLIENT_SECRET \
56
+ --tenant TENANT_ID
57
+
58
+ # Login with certificate (more secure — no shared secret)
59
+ az login --service-principal \
60
+ --username APP_ID \
61
+ --certificate /path/to/cert.pem \
62
+ --tenant TENANT_ID
63
+
64
+ # Login with federated credential (GitHub Actions — no secrets at all)
65
+ az login --service-principal \
66
+ --username APP_ID \
67
+ --tenant TENANT_ID \
68
+ --federated-token "$GITHUB_TOKEN"
69
+ ```
70
+
71
+ > ⚠️ **Never commit service principal credentials.** Store in Key Vault,
72
+ > GitHub Secrets, or Azure DevOps variable groups. Rotate regularly.
73
+
74
+ ## Managed Identity (Azure-hosted only)
75
+
76
+ ```bash
77
+ # Login with system-assigned managed identity
78
+ az login --identity
79
+
80
+ # Login with user-assigned managed identity
81
+ az login --identity --username MANAGED_IDENTITY_CLIENT_ID
82
+ ```
83
+
84
+ No credentials to manage — Azure handles token refresh automatically.
85
+
86
+ ## Subscription Management
87
+
88
+ ```bash
89
+ # List all subscriptions
90
+ az account list -o table
91
+
92
+ # Show current subscription
93
+ az account show -o json
94
+
95
+ # Switch subscription
96
+ az account set --subscription "My Subscription Name"
97
+ az account set --subscription "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
98
+
99
+ # Get subscription ID for scripting
100
+ SUB_ID=$(az account show --query id -o tsv)
101
+
102
+ # Per-command subscription override
103
+ az vm list --subscription "Other Sub" -o json
104
+ ```
105
+
106
+ ## Tenant Management
107
+
108
+ ```bash
109
+ # List tenants
110
+ az account tenant list -o json
111
+
112
+ # Switch tenant (requires re-login)
113
+ az login --tenant TENANT_ID
114
+
115
+ # Show current tenant
116
+ az account show --query tenantId -o tsv
117
+ ```
118
+
119
+ ## Access Tokens
120
+
121
+ ```bash
122
+ # Get access token for current subscription
123
+ az account get-access-token -o json
124
+
125
+ # Get token for specific resource
126
+ az account get-access-token --resource https://management.azure.com/ -o json
127
+ az account get-access-token --resource https://vault.azure.net/ -o json
128
+ az account get-access-token --resource https://graph.microsoft.com/ -o json
129
+ ```
130
+
131
+ ## Configuration
132
+
133
+ ```bash
134
+ # Set defaults (reduces repetition in commands)
135
+ az config set defaults.location=westeurope
136
+ az config set defaults.group=my-resource-group
137
+
138
+ # View config
139
+ az config get
140
+
141
+ # Unset
142
+ az config unset defaults.location
143
+
144
+ # Per-command overrides always take precedence
145
+ az vm create --location eastus ... # overrides default
146
+ ```
147
+
148
+ ### Region Consistency
149
+
150
+ Related Azure resources should be in the same region. Before creating any resource:
151
+
152
+ ```bash
153
+ # Check defaults
154
+ az config get defaults.location 2>/dev/null
155
+
156
+ # List available locations
157
+ az account list-locations --query "[].name" -o tsv
158
+ ```
159
+
160
+ Common regions: `westeurope`, `northeurope`, `eastus`, `eastus2`, `westus2`, `centralus`
@@ -0,0 +1,270 @@
1
+ # Automation, Scripting & CI/CD
2
+
3
+ ## Output Formats
4
+
5
+ **Always use `-o json` for agent consumption.** Table output breaks parsing.
6
+
7
+ ```bash
8
+ az vm list -o json # Full JSON
9
+ az vm list -o tsv # Tab-separated values
10
+ az vm list -o table # Human-readable table
11
+ az vm list -o yaml # YAML
12
+ az vm list -o jsonc # Colorized JSON (human)
13
+ az vm list --query "[].name" -o tsv # Single column, one per line
14
+ ```
15
+
16
+ ## JMESPath Queries (`--query`)
17
+
18
+ Azure CLI uses JMESPath (not the `--filter` syntax of gcloud). Queries run **client-side**.
19
+
20
+ ```bash
21
+ # Single field
22
+ az vm show -g my-rg -n my-vm --query "name" -o tsv
23
+
24
+ # Multiple fields (dictionary)
25
+ az vm show -g my-rg -n my-vm --query "{Name:name, Size:hardwareProfile.vmSize}" -o json
26
+
27
+ # Array projection
28
+ az vm list --query "[].{Name:name, RG:resourceGroup, Size:hardwareProfile.vmSize}" -o table
29
+
30
+ # Filter array
31
+ az vm list --query "[?location=='westeurope'].name" -o tsv
32
+
33
+ # Contains (string search)
34
+ az vm list --query "[?contains(name, 'web')].{Name:name, Location:location}" -o table
35
+
36
+ # Nested access
37
+ az vm show -g my-rg -n my-vm --query "osProfile.adminUsername" -o tsv
38
+
39
+ # First item
40
+ az vm list --query "[0].name" -o tsv
41
+
42
+ # Count
43
+ az vm list --query "length([])" -o tsv
44
+
45
+ # Pipe (apply after flattening)
46
+ az vm list --query "[].{Name:name, OS:storageProfile.osDisk.osType} | [?OS=='Linux']" -o table
47
+
48
+ # Sort
49
+ az vm list --query "sort_by([], &name)[].{Name:name, Location:location}" -o table
50
+ ```
51
+
52
+ ### JMESPath Tips for Agents
53
+
54
+ - Always use single quotes around JMESPath in Git Bash
55
+ - `--query "[].field"` returns a flat list
56
+ - `--query "{Alias:field}"` returns a renamed dictionary
57
+ - Combine `--query` + `-o tsv` for scriptable single values
58
+ - JMESPath is case-sensitive
59
+
60
+ ## Idempotent Patterns
61
+
62
+ ```bash
63
+ # Check-before-create
64
+ if ! az group show --name my-rg &>/dev/null; then
65
+ az group create --name my-rg --location westeurope
66
+ else
67
+ echo "Resource group already exists"
68
+ fi
69
+
70
+ # Using `az group exists`
71
+ if [ "$(az group exists --name my-rg)" = "false" ]; then
72
+ az group create --name my-rg --location westeurope
73
+ fi
74
+
75
+ # Delete-if-exists (suppress error)
76
+ az vm delete --name my-vm --resource-group my-rg --yes 2>/dev/null || true
77
+ ```
78
+
79
+ ## Error Handling
80
+
81
+ ```bash
82
+ # Capture and check
83
+ OUTPUT=$(az vm create --resource-group my-rg --name my-vm --image Ubuntu2204 2>&1)
84
+ if [ $? -ne 0 ]; then
85
+ echo "Error: $OUTPUT" >&2
86
+ exit 1
87
+ fi
88
+
89
+ # Retry with backoff
90
+ for i in 1 2 3 4 5; do
91
+ az webapp up --name my-app --resource-group my-rg && break
92
+ echo "Attempt $i failed, retrying in $((i * 5))s..."
93
+ sleep $((i * 5))
94
+ done
95
+ ```
96
+
97
+ ## Waiting for Long-Running Operations
98
+
99
+ Many Azure operations return before completion. Use `--no-wait` + explicit polling.
100
+
101
+ ```bash
102
+ # Option 1: Synchronous (default — blocks until done)
103
+ az vm create --resource-group my-rg --name my-vm --image Ubuntu2204
104
+
105
+ # Option 2: Async + poll
106
+ az vm create --resource-group my-rg --name my-vm --image Ubuntu2204 --no-wait
107
+ az vm wait --name my-vm --resource-group my-rg --created
108
+ az vm wait --name my-vm --resource-group my-rg --custom "powerState=='VM running'"
109
+
110
+ # Wait conditions: --created, --updated, --deleted, --exists, --custom "JMESPath expr"
111
+ ```
112
+
113
+ ## Bicep (Infrastructure as Code)
114
+
115
+ Bicep is Azure's native IaC language (compiles to ARM JSON).
116
+
117
+ ```bash
118
+ # Install/upgrade Bicep
119
+ az bicep install
120
+ az bicep upgrade
121
+
122
+ # Deploy Bicep template
123
+ az deployment group create \
124
+ --resource-group my-rg \
125
+ --template-file main.bicep \
126
+ --parameters @parameters.json
127
+
128
+ # What-if (dry run — shows changes without applying)
129
+ az deployment group what-if \
130
+ --resource-group my-rg \
131
+ --template-file main.bicep \
132
+ --parameters @parameters.json
133
+
134
+ # Subscription-level deployment
135
+ az deployment sub create \
136
+ --location westeurope \
137
+ --template-file main.bicep
138
+
139
+ # List deployments
140
+ az deployment group list --resource-group my-rg -o table
141
+
142
+ # Show deployment details (includes outputs)
143
+ az deployment group show --name my-deployment --resource-group my-rg -o json
144
+
145
+ # Export existing resource as ARM/Bicep
146
+ az group export --name my-rg > exported.json
147
+ az bicep decompile --file exported.json # Convert ARM → Bicep
148
+ ```
149
+
150
+ ## ARM Templates
151
+
152
+ ```bash
153
+ # Deploy ARM template
154
+ az deployment group create \
155
+ --resource-group my-rg \
156
+ --template-file azuredeploy.json \
157
+ --parameters @azuredeploy.parameters.json
158
+
159
+ # Deploy from URI
160
+ az deployment group create \
161
+ --resource-group my-rg \
162
+ --template-uri "https://raw.githubusercontent.com/.../azuredeploy.json"
163
+
164
+ # Validate (dry run)
165
+ az deployment group validate \
166
+ --resource-group my-rg \
167
+ --template-file azuredeploy.json
168
+ ```
169
+
170
+ ## CI/CD: GitHub Actions
171
+
172
+ ### With Federated Credentials (OIDC — preferred, no secrets)
173
+
174
+ ```yaml
175
+ permissions:
176
+ id-token: write
177
+ contents: read
178
+
179
+ steps:
180
+ - uses: azure/login@v2
181
+ with:
182
+ client-id: ${{ secrets.AZURE_CLIENT_ID }}
183
+ tenant-id: ${{ secrets.AZURE_TENANT_ID }}
184
+ subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
185
+
186
+ - run: az webapp deploy --name my-app --resource-group my-rg --src-path app.zip
187
+ ```
188
+
189
+ Setup:
190
+
191
+ ```bash
192
+ # Create app registration + federated credential
193
+ az ad app create --display-name "github-actions-myrepo"
194
+ APP_ID=$(az ad app list --display-name "github-actions-myrepo" --query "[0].appId" -o tsv)
195
+ az ad sp create --id $APP_ID
196
+
197
+ # Add federated credential for GitHub
198
+ az ad app federated-credential create --id $APP_ID --parameters '{
199
+ "name": "github-main",
200
+ "issuer": "https://token.actions.githubusercontent.com",
201
+ "subject": "repo:ORG/REPO:ref:refs/heads/main",
202
+ "audiences": ["api://AzureADTokenExchange"]
203
+ }'
204
+
205
+ # Grant role
206
+ az role assignment create --assignee $APP_ID --role Contributor \
207
+ --scope /subscriptions/SUB_ID/resourceGroups/my-rg
208
+ ```
209
+
210
+ ### With Service Principal Secret (fallback)
211
+
212
+ ```yaml
213
+ steps:
214
+ - uses: azure/login@v2
215
+ with:
216
+ creds: ${{ secrets.AZURE_CREDENTIALS }}
217
+ # JSON: {"clientId":"...","clientSecret":"...","subscriptionId":"...","tenantId":"..."}
218
+
219
+ - run: az webapp deploy --name my-app --resource-group my-rg --src-path app.zip
220
+ ```
221
+
222
+ ## CI/CD: Azure DevOps Pipelines
223
+
224
+ ```yaml
225
+ steps:
226
+ - task: AzureCLI@2
227
+ inputs:
228
+ azureSubscription: 'my-service-connection'
229
+ scriptType: 'bash'
230
+ scriptLocation: 'inlineScript'
231
+ inlineScript: |
232
+ az webapp deploy --name my-app --resource-group my-rg --src-path app.zip
233
+ ```
234
+
235
+ ## Environment Variables
236
+
237
+ ```bash
238
+ # Make scripts portable
239
+ RG="${AZURE_RESOURCE_GROUP:-my-default-rg}"
240
+ LOCATION="${AZURE_LOCATION:-westeurope}"
241
+ SUB="${AZURE_SUBSCRIPTION_ID:-}"
242
+
243
+ if [ -n "$SUB" ]; then
244
+ az account set --subscription "$SUB"
245
+ fi
246
+ ```
247
+
248
+ ## Tags (Resource Organization)
249
+
250
+ ```bash
251
+ # Tag a resource
252
+ az resource tag --tags env=production team=backend \
253
+ --ids "/subscriptions/SUB_ID/resourceGroups/my-rg/providers/Microsoft.Web/sites/my-app"
254
+
255
+ # Tag a resource group
256
+ az group update --name my-rg --tags env=production
257
+
258
+ # Find resources by tag
259
+ az resource list --tag env=production -o table
260
+ ```
261
+
262
+ ## Azure Policy (overview)
263
+
264
+ ```bash
265
+ # List assigned policies
266
+ az policy assignment list --resource-group my-rg -o table
267
+
268
+ # Show non-compliant resources
269
+ az policy state list --resource-group my-rg --filter "complianceState eq 'NonCompliant'" -o table
270
+ ```