This is the EMU (Enterprise Managed Users) deployment path. Use this if you're standing the workshop up inside a GitHub Enterprise Cloud org with EMU enabled (typical for regulated banks, healthcare, and large enterprises).
If your target org is a regular github.com org (free, Team, or Enterprise without EMU), use bin/bootstrap.sh instead.
⚠️ Reademu-preflight.mdFIRST — it lists five enterprise-level settings (PAT issuance policy, Copilot seat, Actions allowlist, runner egress, org-secret visibility) that an enterprise admin must verify 5–7 days before the workshop. Items 1–4 cannot be fixed by this bootstrap script; they require enterprise-admin UI access. Discovering them on workshop morning will block delivery.
EMU enterprises live on github.com but are identity-isolated:
- EMU users have suffixed handles (e.g.
daniel-meppiel_acme) - EMU users cannot see public
github.comrepos —gh repo fork DevExpGbb/...is impossible - EMU orgs cannot have
publicvisibility — onlyinternal(visible across the enterprise) orprivate - EMU runners may have a restricted GitHub Actions allowlist;
actions/checkout@v4and other GitHub-owned actions must be on it
The fix is the bridge engineer model: one engineer holds two PATs on the same github.com host — a personal/source identity that can read DevExpGbb, and an EMU identity that can write to the target org. The bootstrap mirror-clones with the source token and git push --mirrors with the target token.
| Token | Identity | Required scopes | Used for |
|---|---|---|---|
GH_TOKEN_SOURCE |
Personal github.com (e.g. danielmeppiel) |
repo (read) |
Mirror-cloning DevExpGbb/* |
GH_TOKEN_TARGET |
EMU identity (e.g. daniel-meppiel_acme) |
repo, workflow, admin:org, delete_repo |
Creating, pushing, configuring the EMU org |
Generate each one in its own browser session (or incognito), since both live on github.com but require different logins.
Your enterprise admin must allow at least the following GitHub-owned actions (typical defaults — confirm with your platform team before booking the workshop):
actions/checkoutactions/setup-nodeactions/upload-artifactactions/github-script
If your enterprise uses selected_actions mode, the bootstrap's call to enable repo-level Actions will succeed but workflows will fail at runtime. Either widen the allowlist temporarily or add specific actions for the workshop window.
The bridge machine needs egress to github.com (it's the same host for both source and target — only the auth token changes per call).
bootstrap-emu.sh is idempotent and dry-run-friendly. In order, it performs five things — nothing else:
- Verifies both tokens. Resolves the user behind each PAT, confirms
GH_TOKEN_SOURCEcan readDevExpGbb/zava-agent-config, confirmsGH_TOKEN_TARGEThasadmin:orgon the target EMU org. Fails fast if anything is off. - Mirrors four repos into the target org. For each of
zava-agent-config,zava-storefront,zava-skills-workshop-template,poisoned-tracing-skill: mirror-clones fromDevExpGbb/*with the source token, creates the target repo at--visibility=internalwith the target token,git push --mirrors the full history + branches + tags, then best-effort enables Actions at the repo level. Already-existing target repos are skipped. - Rewrites org references in mirrored content. Replaces
DevExpGbb/→YOUR_ORG/across*.yml,*.yaml,*.md,*.jsonin each mirrored repo. Commits and pushes the rewrite. If theapmCLI is present, regeneratesapm.lock.yamlagainst the new org's content (otherwise warns and continues). - Creates the org's
.githubrepo and writesapm-policy.yml. Templatestemplates/apm-policy.ymlwith the target org name and commits it. Any pre-existingapm-policy.ymlis backed up (*.bak.YYYYMMDD-HHMMSS) before being overwritten — unless--forceis passed, in which case it's overwritten in place. - Re-pushes the latest release tag of
zava-agent-config.git push --mirrorbrings tags over but suppresses workflow events; without this step, the marketplace publish never fires. The re-push triggersrelease.yml.
What it does NOT do (relevant for the security review):
- Does not touch any enterprise-level policy (PAT issuance, Actions allowlist, Copilot seats — all owned by
emu-preflight.mditems 1–4). - Does not create, modify, or store PATs anywhere on disk.
- Does not set the org-level
COPILOT_GITHUB_TOKENsecret (emu-preflight.mditem 5 — admin runsgh secret setmanually). - Does not delete anything. Tear-down is a separate script (
teardown-emu.sh) the admin runs deliberately. - Does not run any code from the mirrored repos. Mirror-clone is a pure git operation; no
npm install, no workflow execution, no script sourcing.
Dry-run is exact. --dry-run prints every API call and git operation without modifying state. Run it first on every new EMU org — the output is the audit trail your security team can review before you run for real.
export GH_TOKEN_SOURCE=ghp_personal_xxx
export GH_TOKEN_TARGET=ghp_emu_xxx
# Always dry-run first
./bin/bootstrap-emu.sh --target-org=YOUR_EMU_ORG --dry-run
# Real run (defaults to --visibility=internal)
./bin/bootstrap-emu.sh --target-org=YOUR_EMU_ORG
# After bootstrap, smoke-test (requires GH_TOKEN scoped to target)
GH_TOKEN=$GH_TOKEN_TARGET ./bin/smoke.sh --org=YOUR_EMU_ORG--visibility=internal (default) makes the workshop repos visible to all EMU enterprise members — best for shared workshop content. Use --visibility=private for stricter isolation (only org members + explicit collaborators).
GH_TOKEN_TARGET=$GH_TOKEN_TARGET ./bin/teardown-emu.sh --target-org=YOUR_EMU_ORG --yes-
Mirror push suppresses workflow events.
git push --mirrorbrings tags over but does NOT firerelease.yml. The bootstrap re-pushes the latest tag explicitly to trigger publication. Ifrelease.ymldoesn't fire within ~30s of bootstrap completing, push the tag manually:git push --force "https://x-access-token:$GH_TOKEN_TARGET@github.com/$TARGET_ORG/zava-agent-config.git" \ "refs/tags/v5.0.1:refs/tags/v5.0.1"
-
Marketplace.json contains
https://github.com/DevExpGbb/...raw URLs. The bootstrap rewritesDevExpGbb/→$TARGET_ORG/(org slug only — the host staysgithub.comfor both EMU and public). Verify after bootstrap bygh api repos/$TARGET_ORG/zava-agent-config/contents/marketplace.json. -
COPILOT_GITHUB_TOKENmust be a fine-grained PAT issued by an EMU member account. Per the upstreamgh awauth reference: resource owner = user account (not org), single permissionAccount → Copilot Requests: Read, token owner has an active Copilot seat. Classic PATs and org-owned PATs do not work. On EMU enterprises, fine-grained PAT issuance is often disabled at the enterprise level by default — check Enterprise → Policies → Personal access tokens before the workshop and allow the EMU group that will own this token. Seedocs/emu-preflight.mdfor the full checklist. -
Actions policy is enterprise-level, not org-level. The bootstrap's
actions/permissionsPUT only enables Actions at the repo level; the enterprise-level allowlist is unchanged. Confirm with your platform team before the workshop. -
teardown-emu.shrequiresdelete_reposcope onGH_TOKEN_TARGET. Add it via:gh auth refresh -h github.com -s delete_repo # if using gh auth # or regenerate the PAT with delete_repo selected
This script is structurally tested (shellcheck clean, dry-run validates flow) but has not been end-to-end verified against a real EMU enterprise (the author does not have EMU access). The public-org bootstrap.sh is fully E2E-verified and shares 80% of the post-clone logic. Report any issues at DevExpGbb/zava-workshop-kit/issues.
If you're delivering a scheduled, customer-facing onsite workshop, read live-workshop-runbook.md first. The recommended pattern is to pre-stage the platform org 5–7 days before the workshop using this script, smoke-test it, and treat workshop morning as a "no new infrastructure" window. If this script fails during pre-staging, fall back to manual-mirror-cheatsheet.md — the same operations done by hand in ~30 minutes.