-
Notifications
You must be signed in to change notification settings - Fork 0
Gemma4 guardrails #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1110729
38195db
62296bc
4736b15
8b1a678
c75c01d
6a42eec
800a036
6c29d73
6c73edb
dca191e
3c49a1e
b3baf58
94393f6
563a558
9069b6c
6b6fef5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| --- | ||
| name: screening-azure-ops | ||
| description: Operating the Screening service's Azure infrastructure without accidentally starting a GPU. Rules for Container Apps revisions, scale-to-zero, checking what is billing, and the traps that have cost real money on this subscription. Use before ANY az containerapp command, before deploying, and whenever asked whether something is running or costing money. | ||
| --- | ||
|
|
||
| # Screening — Azure operations | ||
|
|
||
| The GPU app (`screening-gemma`) runs an A100 at **~€2.16/hour**. Every rule here exists | ||
| because it was broken once and billed for it. | ||
|
|
||
| ## Rule 0 — Name the subscription explicitly in every command | ||
|
|
||
| Without `--subscription`, every command below runs against whatever the CLI's default | ||
| happens to be. A preflight check can then report on one subscription while the GPU is | ||
| billing on another, which makes "nothing is running" a false negative rather than an answer. | ||
|
|
||
| ```bash | ||
| export AZURE_SUBSCRIPTION_ID=<id> # once per session | ||
| ``` | ||
|
|
||
| Append `--subscription "$AZURE_SUBSCRIPTION_ID"` to every `az containerapp` command in this | ||
| file, and use the same id in the `az rest` URL. The id is not written here — this file is in | ||
| a public repository. | ||
|
|
||
| ## Rule 1 — Check what is running BEFORE starting work, not only after | ||
|
|
||
| Two separate incidents cost money because a session began without checking state: an A100 | ||
| left running for 1h38m (~€3.50), and an app left at `minReplicas: 1` overnight. | ||
|
|
||
| ```bash | ||
| for a in screening-app screening-gemma; do | ||
| echo "$a: replicas=$(az containerapp revision list -n $a -g screening-rg --subscription "$AZURE_SUBSCRIPTION_ID" --query 'sum([].properties.replicas)' -o tsv)" | ||
| echo " app-template min=$(az containerapp show -n $a -g screening-rg --subscription "$AZURE_SUBSCRIPTION_ID" --query 'properties.template.scale.minReplicas' -o tsv)" | ||
| done | ||
| ``` | ||
|
|
||
| Both lines matter — see Rule 3. | ||
|
|
||
| ## Rule 2 — PURGE revisions before updating, never deactivate after | ||
|
|
||
| `az containerapp update` **reactivates deactivated revisions**. A revision that was born with | ||
| `minReplicas: 1` immediately starts a replica when reactivated. This has happened five times. | ||
|
|
||
| Wrong: | ||
| ```bash | ||
| az containerapp update ... # resurrects old revisions | ||
| az containerapp revision deactivate ... # clean up after noticing | ||
| ``` | ||
|
|
||
| Right: | ||
| ```bash | ||
| # 1. find every revision carrying min>0 | ||
| az containerapp revision list -n <app> -g screening-rg \ | ||
| --query "[].{rev:name, active:properties.active, min:properties.template.scale.minReplicas}" -o table | ||
| # 2. deactivate those FIRST | ||
| az containerapp revision deactivate -n <app> -g screening-rg --revision <NAME> | ||
| # 3. then update | ||
| # 4. then verify replicas again | ||
| ``` | ||
|
Comment on lines
+39
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- candidate file ---'
sed -n '1,130p' .claude/skills/screening-azure-ops/SKILL.md
printf '%s\n' '--- Azure CLI references in repository ---'
rg -n -C 3 'containerapp (update|revision|deactivate)|minReplicas|subscription|PURGE|reactivat' .claude README.md .github 2>/dev/null || trueRepository: inesaranab/screening Length of output: 12050 🌐 Web query:
💡 Result: In Azure Container Apps, revisions are snapshots of your application [1][2]. You can manage their state—active or inactive—using the Azure CLI, which is the recommended approach for these operations [3][4]. Revision State Management To control revision states, use the following Azure CLI commands: - Deactivate a revision: az containerapp revision deactivate --name <APP_NAME> --resource-group <RG_NAME> --revision <REVISION_NAME> [3][4][5] - Reactivate (activate) a revision: az containerapp revision activate --name <APP_NAME> --resource-group <RG_NAME> --revision <REVISION_NAME> [4][6][5] Revisions do not incur charges while in an inactive state [1][7]. Inactive Revision Limits and Purging Azure Container Apps tracks a limited number of inactive revisions [1][7]. - Default Limit: By default, the system tracks up to 100 inactive revisions [1][7]. Once this limit is exceeded, the oldest revisions are automatically purged [1][7]. - Customizing the Limit: You can adjust the number of tracked inactive revisions by using the --max-inactive-revisions parameter with the az containerapp create or az containerapp update commands [1][7]. Note that the Azure CLI extension for container apps may require preview features enabled to use this parameter [1]. Scaling and minReplicas The minReplicas setting is part of the scaling configuration of your container app [2]. If you set minReplicas to 0, your application will scale to zero when there is no traffic, which is a common way to manage resources effectively without manually deactivating revisions [2]. If ingress is disabled and you do not define a minReplicas value or a custom scale rule, the app may scale to zero with no way to start back up [2]. To ensure your application remains operational, ensure minReplicas is set to at least 1 or configure appropriate scaling rules [2]. For comprehensive management, you can list all revisions, including inactive ones, by using the --all flag: az containerapp revision list --name <APP_NAME> --resource-group <RG_NAME> --all [4] Citations:
🌐 Web query:
💡 Result: In the context of Azure Container Apps, you can manage the state of revisions by activating and deactivating them when operating in multiple revision mode [1][2]. To reactivate a previously deactivated revision, you can use the activate command available in the Azure CLI. For example, in Bash, you can execute: az containerapp revision activate --revision <REVISION_NAME> --resource-group <RESOURCE_GROUP_NAME> Similarly, to deactivate a revision, which stops all its running replicas, you use the following command: az containerapp revision deactivate --revision <REVISION_NAME> --resource-group <RESOURCE_GROUP_NAME> When you update your application with revision-scope changes, a new revision is automatically created [1][2]. If you need to revert to a previous state or apply changes based on a specific revision, you can update your container app to use that revision [2]. Note that Azure Container Apps imposes a limit on the total number of available revisions, and revisions exceeding this count are purged [1]. Citations:
🌐 Web query:
💡 Result: To manage inactive revisions in Azure Container Apps using the Azure CLI, you should use the revision-specific commands rather than a general update command. There is no single "reactivate" command; instead, you activate a revision using the following command: az containerapp revision activate -g <RESOURCE_GROUP> -n <CONTAINER_APP_NAME> --revision <REVISION_NAME> [1] Conversely, if you need to deactivate a revision, use the corresponding command: az containerapp revision deactivate -g <RESOURCE_GROUP> -n <CONTAINER_APP_NAME> --revision <REVISION_NAME> [1] Note that the az containerapp update command is primarily used to modify configuration settings (such as image, environment variables, or scale rules) of the container app itself [1], and it does not serve as a mechanism to change the lifecycle state (active/inactive) of an existing revision. If you need to create a new revision based on a previous one, you can use the az containerapp revision copy command [1][2]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- deployment and revision settings ---'
sed -n '1,100p' .github/workflows/deploy.yml
printf '%s\n' '--- revision-related documentation and commands in the repository ---'
rg -n -C 5 'revision (list|activate|deactivate)|max-inactive-revisions|revisionMode|activeRevisionsMode|targetPort|scale' --glob '!**/node_modules/**' .Repository: inesaranab/screening Length of output: 29731 🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from urllib.request import urlopen
from html import unescape
import re
urls = [
"https://learn.microsoft.com/en-us/azure/container-apps/revisions",
"https://learn.microsoft.com/en-us/azure/container-apps/revisions-manage",
"https://raw.githubusercontent.com/Azure/azure-cli/dev/src/azure-cli/azure/cli/command_modules/containerapp/custom.py",
]
for url in urls:
print(f"\n--- {url} ---")
try:
text = urlopen(url, timeout=20).read().decode("utf-8", "replace")
except Exception as exc:
print(f"FETCH_ERROR: {exc}")
continue
text = unescape(re.sub(r"<[^>]+>", " ", text))
text = re.sub(r"\s+", " ", text)
terms = ["reactivat", "deactivat", "purge", "inactive", "az containerapp update", "new revision"]
for term in terms:
hits = [m.start() for m in re.finditer(term, text, re.I)]
for pos in hits[:5]:
print(text[max(0, pos-220):pos+420])
PYRepository: inesaranab/screening Length of output: 883 🌐 Web query:
💡 Result: Using the az containerapp update --yaml command does not inherently "reactivate" a revision; instead, it updates the container app's configuration based on the provided YAML file [1][2]. Whether a new revision is created or an existing one is modified depends on the nature of the changes and the app's revision mode [1][3]. Key points regarding this command and revision behavior: 1. Revision-Scope vs. Application-Scope Changes: If your YAML file includes revision-scope changes (e.g., changes to container images, environment variables, or scale rules), the command will trigger the creation of a new revision [1][3]. Application-scope changes (e.g., certain metadata or label updates) do not create a new revision [3]. 2. Revision Reactivation: The az containerapp update command is not a substitute for explicit revision activation [4][5]. If you need to bring an inactive revision back into service, you should use the explicit command [4]: az containerapp revision activate --name <APP_NAME> --revision <REVISION_NAME> --resource-group <RG_NAME> 3. YAML Usage: The --yaml parameter allows you to supply a full configuration template [2][5]. When using this approach, be aware that the CLI will apply the configuration defined in the file, which may include settings that force a new revision deployment [2]. Ensure your YAML reflects the desired state of the application to avoid unintended deployments or configuration drift [2][6]. 4. Revision Modes: In Single Revision Mode, deploying a new configuration automatically deactivates the previous revision and activates the new one [7]. In Multiple Revision Mode, you can manage active and inactive revisions independently, allowing you to reactivate old revisions or shift traffic weights as needed [1][5]. Citations:
🌐 Web query:
💡 Result: There is no official documentation or specific update confirming that Azure Container Apps automatically reactivates a deactivated revision's minReplicas settings [1][2][3]. In Azure Container Apps, when a revision is deactivated, it is effectively stopped and does not consume resources [1][3]. Deactivation is a state change that stops all running replicas of that specific revision [1]. Scaling behavior, including minReplicas, is revision-specific; if you deactivate a revision, it remains dormant and does not actively scale [3]. If you are observing a situation where a revision appears to "reactivate" or where scaling behavior changes unexpectedly after a deployment or update, it is likely related to one of the following documented behaviors: 1. Deployment and Traffic Shifting: In single-revision mode, when you deploy a new revision, the previous revision is not deactivated until the new revision is fully ready, including meeting its own scaling requirements (e.g., minReplicas) [3]. 2. New Revision Scaling Defaults: When a new revision is created, it initializes based on its own configuration, not the current scale of the previous revision [4]. This can cause the application to start at its defined minReplicas (which might be 1) rather than the high replica count the previous revision may have scaled to under heavy load [4]. This is a common point of confusion that can look like a reset or unexpected behavior [4]. 3. Multiple Revision Mode: If you are using multiple revision mode, traffic weights determine which revisions are active [3]. If you manually reactivate a revision or update traffic weights to point to a previously deactivated one, it will resume operations according to its defined scaling configuration (minReplicas/maxReplicas) [3]. If you believe a revision is reactivating autonomously, verify if there are any automated CI/CD pipelines, Azure Policy, or scripts that might be updating the revision's traffic weights or activation status, as these actions would trigger the revision to resume its scaling profile. Citations:
🏁 Script executed: #!/bin/bash
set -eu
fetch() {
url="$1"
printf '\n--- %s ---\n' "$url"
curl -k -L --silent --show-error --max-time 30 "$url" |
tr '\n' ' ' |
sed 's/<[^>]*>/ /g; s/[[:space:]][[:space:]]*/ /g' |
grep -oEi '.{0,240}(--all|inactive revisions|new revision|deactivat|reactivat|purge).{0,420}' |
head -20 || true
}
fetch 'https://learn.microsoft.com/en-us/azure/container-apps/revisions'
fetch 'https://learn.microsoft.com/en-us/azure/container-apps/revisions-manage'
fetch 'https://raw.githubusercontent.com/Azure/azure-cli/dev/src/azure-cli/azure/cli/command_modules/containerapp/_help.py'Repository: inesaranab/screening Length of output: 15074 Set
🤖 Prompt for AI AgentsSource: MCP tools |
||
|
|
||
| ## Rule 3 — The app template and its revisions are different things | ||
|
|
||
| Deactivating every revision stops everything running. It does **not** change the app | ||
| template. If the template says `minReplicas: 1`, the next revision created from it — by any | ||
| update, for any reason — starts a replica. | ||
|
|
||
| Fixing the template is itself an update, so it starts a GPU. Expect that and plan for it: | ||
| either use the boot for something needed, or deactivate immediately after. | ||
|
|
||
| ## Rule 4 — `replica list` without `--revision` lies | ||
|
|
||
| It reports only the newest revision. It once showed an empty list while an A100 billed for | ||
| two more hours. Always use `revision list` with a `sum()`, or pass `--revision` explicitly. | ||
|
|
||
| ## Rule 5 — An interrupted command may still have run | ||
|
|
||
| A rejected/interrupted tool call reached Azure anyway on 2026-08-10 and started an A100 that | ||
| ran unnoticed for 1h38m. After any interrupted `az` command, **verify state** rather than | ||
| assuming it did not execute. | ||
|
|
||
| ## Rule 6 — A new revision always boots once, even with minReplicas: 0 | ||
|
|
||
| It must prove itself healthy. On the GPU app that is a ~13 minute, ~€0.50 boot. Never create | ||
| a revision on `screening-gemma` casually. | ||
|
|
||
| ## Verifying independently | ||
|
|
||
| When the answer matters, check by a second path: | ||
|
|
||
| ```bash | ||
| # every container app in the whole subscription, not just the ones you remember | ||
| az containerapp list --query "[].{name:name, rg:resourceGroup, min:properties.template.scale.minReplicas}" -o table | ||
|
|
||
| # actual spend, a completely separate data path | ||
| az rest --method post \ | ||
| --url "https://management.azure.com/subscriptions/<SUB>/providers/Microsoft.CostManagement/query?api-version=2023-11-01" \ | ||
| --body '{"type":"ActualCost","timeframe":"MonthToDate","dataset":{"granularity":"Daily","aggregation":{"totalCost":{"name":"Cost","function":"Sum"}},"grouping":[{"type":"Dimension","name":"ServiceName"}]}}' | ||
| ``` | ||
|
|
||
| Idle baseline for this subscription is **~€0.17–0.60/day**. A day above that means something | ||
| ran. | ||
|
|
||
| ## Known costs | ||
|
|
||
| | Thing | Cost | | ||
| |---|---| | ||
| | A100 (`Consumption NC24-A100`) | €2.16/hour, only while a replica runs | | ||
| | Premium file share, 100 GiB @ 135 MiB/s | ~€25/month, always | | ||
| | Everything else idle | ~€5/month | | ||
|
|
||
| Full reasoning and measurements: `infra/gemma/README.md`. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,3 +23,4 @@ wheels/ | |
| .agents/* | ||
|
|
||
| .deepeval/ | ||
| .coverage | ||
Uh oh!
There was an error while loading. Please reload this page.