The end-to-end development and testing cycle for this repo — branch, PR, merge, then config.yml to push AAP config, then launch the Linux Day 1 - 0 Workflow to prove the change works from AAP. TRIGGER when: the user asks how to test a change, wants to push code to AAP, asks about the dev process, says 'how do we work in this repo', or is about to launch individual job templates after a merge instead of the workflow. SKIP: if the user wants first-time machine setup — that is sales-demos-first-...
Installs into .claude/skills of the current project.
Are you the author of Sales Demos Dev Workflow?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/ericcames-sales-demos-dev-workflow)
---
name: sales-demos-dev-workflow
description: "The end-to-end development and testing cycle for this repo — branch, PR, merge, then config.yml to push AAP config, then launch the Linux Day 1 - 0 Workflow to prove the change works from AAP. TRIGGER when: the user asks how to test a change, wants to push code to AAP, asks about the dev process, says 'how do we work in this repo', or is about to launch individual job templates after a merge instead of the workflow. SKIP: if the user wants first-time machine setup — that is sales-demos-first-time — or EE verification specifically, which is sales-demos-verify-ee."
---
# sales-demos-dev-workflow
Every code change in this repo follows the same three-step cycle. None of the
steps can be skipped, and the order matters.
```
merge to main ──► config.yml --limit <env> ──► Linux Day 1 - 0 Workflow
│ │ │
code lands AAP config updated full pipeline runs
project synced from AAP, in the EE
```
**Why all three?** `scm_update_on_launch` is `false` on the AAP project, so
launching a workflow after a merge runs whatever revision was last synced.
`config.yml` is the sync. Skip it and you are testing old code and wondering
why your change had no effect.
## Step 1 — Branch, PR, merge
1. **Open a GitHub issue first.** Document before fixing. Label it — run
`gh label list --repo ericcames/sales.demos` and apply every label that fits.
2. **Create a worktree** (never branch in the main checkout):
```bash
git worktree add ../sales.demos-<slug> <type>-<issue>-<slug>
cd ../sales.demos-<slug>
# examples: fix-86-preflight-vault-lookup, docs-191-dev-workflow-skill
```
`<type>` is `fix`, `docs`, or the area. `<slug>` is 2–4 words describing the
change, not the file. The issue number links the branch back to the decision.
3. **Make changes, commit, push:**
```bash
git push -u origin <branch>
```
4. **Open a PR.** Include `Closes #N` in the PR body when it resolves an
issue — GitHub auto-closes on merge; without it the issue stays open
silently (#274 left #273 open this way). Eight CI checks are required:
`yamllint`, `ansible-lint`, `secret-guard`, `secrets-example-sync`,
`generated-files`, `skills-frontmatter`, `docs-artifacts-current`,
`renderer-matches-role`.
5. **Merge.** Claude has standing authorization to merge green PRs in this repo
without asking. `main` is protected — a PR is always required, even for the
repo owner.
6. **Clean up the worktree and local branch after merge** (from the main checkout):
```bash
git worktree remove ../sales.demos-<slug>
git pull && git branch -d <branch>
```
The remote branch deletes itself (`delete_branch_on_merge` is enabled).
`-d` checks "pushed to upstream", not "merged" (#179) — after a squash merge
its "not yet merged to HEAD" warning is expected and means nothing.
**If `-d` refuses, the upstream is gone** (a `fetch --prune` ran). It then
falls back to HEAD and refuses every squash-merged branch (#571). Confirm
`gh pr view <n>` says MERGED and the worktree was clean, then `git branch -D`.
## Step 2 — `config.yml`
Pushes AAP configuration (credential types, credentials, job templates,
schedules, execution environments) **and syncs the project** to the latest
`main`. This is the only thing that updates what AAP runs.
```bash
mkdir -p ~/ansible-logs
LOGFILE=~/ansible-logs/config-sandbox-$(date +%F-%H%M).log
ANSIBLE_LOG_PATH="$LOGFILE" ./utilities/run-ansible.sh playbooks/config.yml \
-i inventory --limit sandbox \
-e target_env=sandbox \
--vault-id sales.demos@~/secrets/.vault_pass_sales_demos
echo "Log: $LOGFILE"
```
**Never pipe through `tee`.** In a pipeline the exit status is `tee`'s, not the
playbook's, so a failed run reports success. `ANSIBLE_LOG_PATH` writes the log
without a pipeline.
**`--limit` is mandatory.** Without it the play matches both environments and
fails an assertion. `target_env` is belt-and-suspenders — it verifies the
inventory resolved to the environment you meant.
**Always log output** to `~/ansible-logs/` with a descriptive filename. The log
is the only evidence if something fails — especially credential type errors,
which are hidden by `no_log: true`.
## Step 3 — Launch the Linux Day 1 - 0 Workflow
**Linux Day 1 - 0 Workflow** is the five-node workflow that proves everything
works end-to-end:
```
provision ──► register ──► configure ──► compliance ──► check
```
Launch it from AAP — the UI, or via MCP:
```
mcp__aap-sandbox__workflow_job_templates_launch_create
```
All five nodes are idempotent. A second run converges rather than rebuilding.
### Verify
Do not report success on the workflow recap alone — ask the target:
```
mcp__openshift-<env>__resources_list route.openshift.io/v1 Route
namespace: sales-demos
```
Then curl each Route host:
```bash
curl -sI "https://<route-host>" | head -1
# Expect: HTTP/1.1 200 OK for each Route
```
SSH into the guest and check the MOTD renders with both URLs.
## Gotchas
| Symptom | Cause | Fix |
|---|---|---|
| `config.yml` fails with a censored error on credential types | AAP rejects `inputs` modifications on credential types that have credentials attached | Delete the credential (API DELETE), then the credential type, then re-run `config.yml` — it recreates both. This is a one-time manual step per schema change. |
| Workflow runs but changes have no effect | `scm_update_on_launch: false` — the project is still on the old revision | Run `config.yml` first. It syncs the project. |
| MOTD or job template missing a new variable | Project revision lags — read the project update output (`Repository Version <sha>`), not the project's `scm_revision` field | Confirm the sync completed, then re-launch the workflow |
## What this does NOT replace
This skill documents the **development cycle**, not the operational skills that
do the actual work:
| To do this | Use this skill |
|---|---|
| Set up a bare RHDP environment | `/sales-demos-setup` |
| Provision or rebuild VMs | `/sales-demos-provision` |
| Tear down VMs | `/sales-demos-teardown` |
| Run the demo content standalone | `/sales-demos-ocpvirt-demo` |
| Verify a playbook in the EE | `/sales-demos-verify-ee` |
| First-time machine setup | `/sales-demos-first-time` |