Skip to content

Latest commit

 

History

History
130 lines (82 loc) · 8.93 KB

File metadata and controls

130 lines (82 loc) · 8.93 KB

EMU Setup — bridge-engineer guide

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.

⚠️ Read emu-preflight.md FIRST — 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.


What's different about EMU

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.com repos — gh repo fork DevExpGbb/... is impossible
  • EMU orgs cannot have public visibility — only internal (visible across the enterprise) or private
  • EMU runners may have a restricted GitHub Actions allowlist; actions/checkout@v4 and 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.


Prerequisites

Two PATs on the bridge machine

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.

Enterprise Actions policy

Your enterprise admin must allow at least the following GitHub-owned actions (typical defaults — confirm with your platform team before booking the workshop):

  • actions/checkout
  • actions/setup-node
  • actions/upload-artifact
  • actions/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.

Network egress

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).


What the script does (in a nutshell)

bootstrap-emu.sh is idempotent and dry-run-friendly. In order, it performs five things — nothing else:

  1. Verifies both tokens. Resolves the user behind each PAT, confirms GH_TOKEN_SOURCE can read DevExpGbb/zava-agent-config, confirms GH_TOKEN_TARGET has admin:org on the target EMU org. Fails fast if anything is off.
  2. Mirrors four repos into the target org. For each of zava-agent-config, zava-storefront, zava-skills-workshop-template, poisoned-tracing-skill: mirror-clones from DevExpGbb/* with the source token, creates the target repo at --visibility=internal with 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.
  3. Rewrites org references in mirrored content. Replaces DevExpGbb/ → YOUR_ORG/ across *.yml, *.yaml, *.md, *.json in each mirrored repo. Commits and pushes the rewrite. If the apm CLI is present, regenerates apm.lock.yaml against the new org's content (otherwise warns and continues).
  4. Creates the org's .github repo and writes apm-policy.yml. Templates templates/apm-policy.yml with the target org name and commits it. Any pre-existing apm-policy.yml is backed up (*.bak.YYYYMMDD-HHMMSS) before being overwritten — unless --force is passed, in which case it's overwritten in place.
  5. Re-pushes the latest release tag of zava-agent-config. git push --mirror brings tags over but suppresses workflow events; without this step, the marketplace publish never fires. The re-push triggers release.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.md items 1–4).
  • Does not create, modify, or store PATs anywhere on disk.
  • Does not set the org-level COPILOT_GITHUB_TOKEN secret (emu-preflight.md item 5 — admin runs gh secret set manually).
  • 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.


Run

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

--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).

Tear down

GH_TOKEN_TARGET=$GH_TOKEN_TARGET ./bin/teardown-emu.sh --target-org=YOUR_EMU_ORG --yes

EMU-specific gotchas

  1. Mirror push suppresses workflow events. git push --mirror brings tags over but does NOT fire release.yml. The bootstrap re-pushes the latest tag explicitly to trigger publication. If release.yml doesn'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"
  2. Marketplace.json contains https://github.com/DevExpGbb/... raw URLs. The bootstrap rewrites DevExpGbb/ → $TARGET_ORG/ (org slug only — the host stays github.com for both EMU and public). Verify after bootstrap by gh api repos/$TARGET_ORG/zava-agent-config/contents/marketplace.json.

  3. COPILOT_GITHUB_TOKEN must be a fine-grained PAT issued by an EMU member account. Per the upstream gh aw auth reference: resource owner = user account (not org), single permission Account → 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. See docs/emu-preflight.md for the full checklist.

  4. Actions policy is enterprise-level, not org-level. The bootstrap's actions/permissions PUT only enables Actions at the repo level; the enterprise-level allowlist is unchanged. Confirm with your platform team before the workshop.

  5. teardown-emu.sh requires delete_repo scope on GH_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

Verification status

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.

When to use this vs. the manual mirror path

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.