Skip to content

Configure service ConfigMap

TL;DR — Opens a backend K8s service folder in ops-scripts for editing, analyzes the resulting diff, opens a PR, and triggers the post-merge ConfigMap apply Jenkins job for the environments it can safely automate. Not for frontends — frontend env vars use a different flow; see wiki/frontend/frontend-architecture.md → Changing configs per environment.

Overview

This workflow operates on securitize_dev/ops-scripts/k8s/{service-name}/ — the K8s backend side of the deploy system. It does not cover frontends (React/Vue apps deployed to S3 + CloudFront), which follow a different configuration flow documented in the wiki. Editing is permissive — the developer can modify any file under the backend service folder — and the final git diff drives what post-merge action, if any, this workflow can automate.

For the service folder layout, the file-to-env mapping, the production rule, the apply Jenkins job, and the layout exceptions (APAC, Helm, legacy), see the SSOT: wiki/repositories/ops-repos.md → Per-service ConfigMaps. This workflow does not restate those facts — load the wiki page before classifying the diff.

Automation scope: only the subset of post-merge actions that can be driven safely from a diff plus the wiki mapping is handled here. Every change that falls outside that subset (production, non-configmap paths, non-standard environments, unclassified files) is reported to the developer with the handling rule from the wiki, not automated.

Inputs

  • service name (required) — the directory name under ops-scripts/k8s/ (e.g. account-gw).

Steps

Shell-session note — If you run each bash command in a fresh subshell (e.g. one Bash tool call per step), the TEMP_DIR variable from Step 1 does not persist. In any step after Step 1, re-derive it as:

TEMP_DIR=$(ls -dt "$HOME"/.securitize/tmp/ops-scripts-*/ 2>/dev/null | head -1)
TEMP_DIR="${TEMP_DIR%/}"

1. Clone ops-scripts

TEMP_DIR="$HOME/.securitize/tmp/ops-scripts-$(date +%Y%m%d%H%M%S)"
mkdir -p "$HOME/.securitize/tmp"
rm -rf "$TEMP_DIR"
git clone --depth 1 git@bitbucket.org:securitize_dev/ops-scripts.git "$TEMP_DIR"

# Confirm mainline is master — every ops-* repo branches from master, not dev
git -C "$TEMP_DIR" rev-parse --abbrev-ref HEAD   # must print: master

If the clone fails, have the developer verify their SSH key and Bitbucket access, then stop. If the confirm command does not print master, stop — ops-scripts uses master as its mainline; do not proceed on any other branch.

2. Validate the service folder and detect the layout

Check $TEMP_DIR/k8s/{service-name}/:

  • Missing → list the folders under $TEMP_DIR/k8s/ (and $TEMP_DIR/k8s/apac/ if the name is not found at the top level), suggest the closest match, and ask the developer to confirm. Do not proceed until the path is confirmed.
  • Present, contains configmaps/ → modern layout (documented in the wiki). Full workflow support.
  • Present, without configmaps/, or under k8s/apac/ → layout exception listed in the wiki. Inform the developer:

    I detected this service follows a layout exception (documented in the wiki). You can edit it and I'll open the PR, but I can't auto-detect which environments to restart after merge — apply manually.

The canonical layout table and the list of exceptions live in wiki/repositories/ops-repos.md → Per-service ConfigMaps.

3. Open the service folder in the developer's editor

Open the whole service folder (not just configmaps/) so the developer can edit any file: ConfigMap values, yamls/, env/, etc.

TERM_PROGRAM is set by the integrated terminal of VS Code (vscode), Cursor (cursor), Windsurf (windsurf), and Zed (zed). If the developer is running from an external terminal (iTerm2, Terminal.app, etc.), none of the TERM_PROGRAM branches match and the fallback else tries each editor CLI in order.

SERVICE_PATH="$TEMP_DIR/k8s/{service-name}"   # or $TEMP_DIR/k8s/apac/{service-name} when applicable

if [ "$TERM_PROGRAM" = "cursor" ]; then
  cursor "$SERVICE_PATH"
elif [ "$TERM_PROGRAM" = "vscode" ]; then
  code "$SERVICE_PATH"
elif [ "$TERM_PROGRAM" = "windsurf" ]; then
  windsurf "$SERVICE_PATH"
elif [ "$TERM_PROGRAM" = "zed" ]; then
  zed "$SERVICE_PATH"
elif [ "$TERMINAL_EMULATOR" = "JetBrains-JediTerm" ]; then
  webstorm "$SERVICE_PATH" 2>/dev/null || idea "$SERVICE_PATH" 2>/dev/null
else
  code     "$SERVICE_PATH" 2>/dev/null || \
  cursor   "$SERVICE_PATH" 2>/dev/null || \
  windsurf "$SERVICE_PATH" 2>/dev/null || \
  zed      "$SERVICE_PATH" 2>/dev/null || \
  vim      "$SERVICE_PATH"
fi

If no editor can be launched, print $SERVICE_PATH and ask the developer to open it manually.

4. Wait for the developer to finish editing

Do nothing until the developer explicitly confirms they are done (e.g. "done", "listo"). Do not proceed on your own.

5. Show the diff

cd "$TEMP_DIR" && git diff

Show the full output and ask the developer to confirm. If they want further changes, return to Step 3.

6. Analyze the changed files

Before classifying, load the file-to-env mapping from wiki/repositories/ops-repos.md → Per-service ConfigMaps — that page is the canonical source for which properties_*.env file maps to which environment and for the production rule. Do not infer the mapping from memory.

From the clone directory:

cd "$TEMP_DIR" && git diff --name-only HEAD

For each changed path, use the mapping from the wiki to place it in one of these categories (evaluate in order — the first match wins):

  1. Ignored — any file named properties.env or properties_demo.env, whether inside configmaps/ or at the service root (k8s/{service-name}/properties.env). The wiki lists these as not covered by the standard Jenkins apply job. Included in the PR, excluded from post-merge action.
  2. Auto-applyconfigmaps/properties_<env>.env where <env> is dev, rc, or sandbox. These are the only envs this workflow triggers automatically.
  3. Production — any file mapped to prod in the wiki. The prod apply is restricted to Tech Leads (see the production rule in the wiki). Never auto-trigger from this workflow; surface to the developer that the prod apply must be triggered by a TL on their team.
  4. Detected-manual — any other env mapped by the wiki table (e.g. apac, qa). Report the change; the developer applies manually if needed.
  5. Unclassified — any file inside configmaps/ whose name is not listed in the wiki's file-to-env table (for example, a new properties_uat.env the wiki does not describe). Report it and ask the developer to confirm the change is intentional before proceeding.
  6. Out of scope — any other path inside the service folder: yamls/, env/, or any file at the service root that was not matched by rule 1. These require a redeploy, not a ConfigMap apply, and are not handled by this workflow.

Show the developer a summary table grouped by category. If nothing changed, stop — there is nothing to PR.

7. Create the branch (from master) and push

Branch from master, not dev

ops-scripts — like every ops-* repo — uses master as its mainline. Do not substitute dev even if a generic PR procedure suggests it as a default. This workflow's branching base is non-negotiable: the PR destination is master (Step 8) and the source branch must also be cut from master.

BRANCH="feature/config-update-{service-name}-$(date +%Y%m%d%H%M%S)"
cd "$TEMP_DIR"
git checkout -b "$BRANCH" master        # explicit base = master — do not change to dev
git add "k8s/{service-name}"            # or "k8s/apac/{service-name}" when applicable
git commit -m "chore: update config for {service-name}"
git push origin "$BRANCH"

8. Open the Pull Request

Target: securitize_dev/ops-scripts, source = the branch pushed in Step 7, destination = master.

Preferred — open the PR through any Bitbucket-capable MCP you have available. Tool names and parameter shapes vary by server (mcp__bitbucket__*, mcp__atlassian__*, custom servers, etc.); scan your tool list for tools that act on Bitbucket pull requests. Whatever the surface, perform two operations:

  1. Resolve the repo's effective default reviewers for workspace=securitize_dev, repo=ops-scripts. Keep the returned user identifiers (UUIDs / account IDs / whatever the server uses).
  2. Create the pull request with:
  3. source = {BRANCH} (from Step 7)
  4. destination = master
  5. title = chore: update config for {service-name}
  6. description = summary table from Step 6
  7. reviewers = the identifiers from (1)

Fallback — no Bitbucket MCP available. Show the developer the manual URL and stop:

https://bitbucket.org/securitize_dev/ops-scripts/pull-requests/new?source={BRANCH}&dest=master

In either path, show the final PR link to the developer.

9. Clean up the temporary clone

rm -rf "$TEMP_DIR"

Confirm the cleanup to the developer.

10. Post-merge: apply ConfigMaps via Jenkins

Wait for the developer to confirm the PR has been merged, then — if a Bitbucket-capable MCP is available — use it to fetch the PR (workspace securitize_dev, repo ops-scripts, the PR opened in Step 8) and verify the state is MERGED. If it is not, ask the developer to merge first.

Probe Jenkins MCP availability before triggering: call any Jenkins tool such as get_job_info with the job name documented in the wiki. A successful response means the MCP is configured. If the call fails or the tool is not available, skip the automated trigger and point the developer to the job URL from the wiki page so they can run it manually with service_name and environment.

Once merged (Jenkins MCP available):

  • Auto-apply set (from Step 6) — trigger the Jenkins job documented in wiki/repositories/ops-repos.md → Per-service ConfigMaps, sequentially (not in parallel), once per environment. Parameters: { "service_name": "{service-name}", "environment": "{env}" }. Poll get_build_info every 10 seconds until building: false. On SUCCESS, move to the next env. On FAILURE, fetch the last 50 lines via get_build_logs, report, and stop.
  • Detected-manual, Production, Out of scope, Unclassified, Ignored — surface each group to the developer with the handling rule from Step 6. Do not attempt to automate any of them.

Verification

  • The PR is open on securitize_dev/ops-scripts against master, with the summary table in the description.
  • For each env triggered, the Jenkins build result is SUCCESS and the deployment has restarted.
  • For non-modern layouts, the PR is opened and the developer is informed no auto-apply was attempted.

Rollback

The workflow writes no state outside the temporary clone until the PR is merged.

  • Before push (Steps 1-7): rm -rf "$TEMP_DIR" discards everything.
  • After push, before merge: close the PR in Bitbucket; delete the remote branch.
  • After merge, before ConfigMap apply: revert the merge commit on master via a new PR.
  • After ConfigMap apply: revert the merge commit, then re-run this workflow for the affected envs to roll the ConfigMap back.

See also

Tags

workflow #ops-scripts #configmap #k8s