You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+11Lines changed: 11 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,10 +11,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
12
12
- Virtual subdirectory and raw-file packages now resolve from self-hosted Git services (Gitea, Gogs) via raw URL with API v1/v3 fallback. (#587)
13
13
-`shared/apm.md` gh-aw shared workflow exposes a `target:` import input (default `all`) so consumer workflows can ship slim, single-harness bundles instead of always packing every layout. (#1184)
14
+
-**GitLab host support:**`gitlab.com` and self-managed instances (via `GITLAB_HOST` / `APM_GITLAB_HOSTS`) use GitLab REST **v4** for `marketplace.json` and install-time raw file reads; nested GitLab group paths are disambiguated in dependency references with object-form `git:` + `path:` where shorthand is ambiguous. GitHub, GHES, Azure DevOps, and registry-proxy behavior remain unchanged. (#1149)
15
+
-**`git: parent` monorepo transitive dependency inheritance:** packages in a git monorepo can reference sibling paths via `{ git: parent, path: ... }` without repeating the full `git:` URL; the lockfile stores expanded host, repository, subdirectory path, and resolved ref/commit like other virtual git dependencies (no `parent` sentinel as durable identity). (#1149)
14
16
- If you use the `gh` CLI, APM is now zero-config for private GitHub packages on github.com, `*.ghe.com`, and GHES: APM uses your active `gh auth login` token (`gh auth token --hostname <host>`) before falling back to `git credential fill`. Silently skipped when `gh` is not installed or not logged in for the host. (#630)
15
17
18
+
### Changed
19
+
20
+
-`apm marketplace browse/search/add/update` route through the registry proxy when `PROXY_REGISTRY_URL` is set; `PROXY_REGISTRY_ONLY=1` blocks direct GitHub and GitLab host API fallbacks. (#1149)
21
+
- Registry proxy now warns when `PROXY_REGISTRY_TOKEN` is set and `PROXY_REGISTRY_URL` uses `http://`, since the bearer token would be transmitted in plaintext; set `PROXY_REGISTRY_ALLOW_HTTP=1` to silence the warning for trusted internal proxies. (#1149)
22
+
16
23
### Fixed
17
24
25
+
-`apm marketplace add` accepts GitLab-class hosts (`gitlab.com` and self-managed instances configured via `GITLAB_HOST` / `APM_GITLAB_HOSTS`); unsupported generic hosts now show separate recovery hints for GHES (`GITHUB_HOST`) and self-managed GitLab instead of only `GITHUB_HOST`. (#1149)
26
+
-**GitLab monorepo marketplaces:**`apm install plugin@marketplace` now resolves plugins whose sources live in a subdirectory of the marketplace repository on GitLab-class hosts (`gitlab.com` and self-managed GitLab when classified as GitLab), matching explicit `git:` + `path:` semantics without requiring that hand-written object form. (#1149)
27
+
-`apm install` now rejects unsupported flat-format `dependencies` (e.g. `dependencies: [owner/repo]`) with a clear error and structured-format hint instead of silently ignoring them; the resolver also surfaces `ValueError` from malformed transitive manifests as warnings instead of swallowing them. (#1189)
18
28
-`shared/apm.md` no longer wraps the `target` input in a `|| 'all'` fallback. The defensive expression broke gh-aw's bare-expression substitution regex, causing consumer-supplied `target:` values to be silently dropped; the `import-schema` default already covers the omitted-input case. (#1185)
19
29
-`apm install --target all` no longer enumerates the experimental `copilot-cowork` target, which was crashing project-scope installs with a "requires --global" error and made `gh aw` workflows that pin `target: all` unusable. (#1191)
20
30
- Stabilized `test_install_over_defer_threshold_starts_live_once` on slow CI runners by joining the deferred-start timer thread instead of relying on a 100ms grace window. (#1191)
@@ -24,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
34
-`apm install --update` now falls back from a stale `ADO_APM_PAT` to an `az login` AAD bearer in the preflight auth probe, matching the behavior of `apm install` and every other ADO call site. Previously the preflight raised `AuthenticationError` on 401/403 even when `az login` would have succeeded. The bearer env also pops any pre-existing `GIT_TOKEN` so the JWT flows only via `GIT_CONFIG_VALUE_0`, and the per-host stale-PAT warning dedup is lock-guarded so parallel installs against the same ADO host emit one warning instead of one-per-thread. (#1212)
25
35
-`Unknown target` error suggestions no longer advertise the `agent-skills` meta-target, which `apm targets` intentionally omits from its table. The canonical set still accepts `agent-skills` via `--target` and `apm.yml`, but the recovery path printed on errors now matches what the discovery command actually lists. (#1215)
26
36
-`apm pack` no longer hardcodes `pack.target` into bundles; bundles are target-agnostic and `apm install <bundle>` resolves the consumer target from project context and wires bundle `.mcp.json` servers per target via `MCPIntegrator`. (#1217)
37
+
- Multi-account Git Credential Manager users: APM now selects the right GitHub account automatically per repository (no account-picker prompt) when `credential.useHttpPath = true` is set. Existing single-account setups are unaffected. (#1226)
APM works without tokens for public packages on github.com. Authentication is needed for private repositories, enterprise hosts (`*.ghe.com`, GHES), and Azure DevOps.
7
+
APM works without tokens for public packages on github.com. Authentication is needed for private repositories, enterprise hosts (`*.ghe.com`, GHES), GitLab (private or API access), and Azure DevOps.
8
8
9
9
## How APM resolves authentication
10
10
11
-
APM resolves tokens per `(host, org)` pair. For each dependency, it walks a resolution chain until it finds a token:
11
+
APM resolves tokens per `(host, port, org)` pair. For each dependency, it walks a **host-class-specific** chain until it finds a token:
12
12
13
-
1.**Per-org env var** — `GITHUB_APM_PAT_{ORG}` (GitHub-like hosts — not ADO)
1.**GitHub-class hosts** (`github.com`, `*.ghe.com`, GHES via `GITHUB_HOST`): **Per-org env var**`GITHUB_APM_PAT_{ORG}` (when an org slug applies), then **global**`GITHUB_APM_PAT` -> `GITHUB_TOKEN` -> `GH_TOKEN`, then **GitHub CLI active account** (`gh auth token --hostname <host>`, silently skipped if `gh` is not installed or not logged in for the host), then host-specific **git credential helper**.
14
+
2.**GitLab-class hosts** (`gitlab.com`, or FQDNs listed via `GITLAB_HOST` / `APM_GITLAB_HOSTS`): **only**`GITLAB_APM_PAT` -> `GITLAB_TOKEN`, then host-specific **git credential helper**. GitHub token env vars are **not** used for GitLab (including `GITHUB_APM_PAT`, `GITHUB_TOKEN`, and `GH_TOKEN`, and `GITHUB_APM_PAT_{ORG}` for group/namespace paths).
15
+
3.**Generic hosts** (other FQDNs such as Bitbucket): host-specific **git credential helper** or unauthenticated/public access -- **no** GitHub or GitLab platform env vars.
17
16
18
-
Steps 1 and 2 cover the four token-priority rows in the table below (priorities 1-4). The numbering above collapses the three global env vars (`GITHUB_APM_PAT`, `GITHUB_TOKEN`, `GH_TOKEN`) into a single resolution step.
17
+
Azure DevOps uses its own chain (`ADO_APM_PAT` -> Azure CLI bearer). See [Azure DevOps](#azure-devops).
18
+
If the resolved token fails for the target host, APM retries with git credential helpers on paths that support it. If nothing matches, APM attempts unauthenticated access where the host exposes public repos (not *ghe.com* Data Residency).
19
19
20
-
If the global token doesn't work for the target host, APM next tries the active `gh` CLI account before falling back to git credential helpers. If nothing matches, APM attempts unauthenticated access (works for public repos on github.com).
21
-
22
-
Results are cached per-process — the same `(host, org)` pair is resolved once.
23
-
24
-
All token-bearing requests use HTTPS. Tokens are never sent over unencrypted connections.
25
-
26
-
`apm install <package>` validation walks the same chain as the actual install: an authenticated attempt with the resolved token first, then a credential-helper fallback (plain HTTPS where the system credential helper provides the token). This means `apm install` from the CLI never rejects a package the lockfile-driven install would accept -- useful when an env-var PAT has narrower SSO/EMU access than the token your `gh auth setup-git` / OS keychain has cached.
20
+
Results are cached per-process for each `(host, port, org)` key. All token-bearing requests use HTTPS.
27
21
28
22
## Token lookup
23
+
### GitHub-class hosts (`github.com`, `*.ghe.com`, GHES via `GITHUB_HOST`)
For Azure DevOps, APM resolves credentials in this order: `ADO_APM_PAT` env var, then a Microsoft Entra ID (AAD) bearer token from the Azure CLI (`az`). See [Azure DevOps](#azure-devops) below.
42
+
**GitLab exclusion:** GitHub PAT env vars (`GITHUB_APM_PAT`, `GITHUB_APM_PAT_{ORG}`, `GITHUB_TOKEN`, `GH_TOKEN`) are **never** chosen for GitLab-class hosts — even if set — because they commonly appear in unrelated contexts (for example Actions) and must not be sent to GitLab as `PRIVATE-TOKEN` or HTTPS credentials.
40
43
41
-
For Artifactory registry proxies, use `PROXY_REGISTRY_TOKEN`. See [Registry proxy (Artifactory)](#registry-proxy-artifactory) below.
44
+
### Generic hosts (e.g. Bitbucket, self-hosted SCM that is not GitLab-class)
42
45
43
-
For runtime features (`GITHUB_COPILOT_PAT`), see [Agent Workflows](../../guides/agent-workflows/).
46
+
| Priority | Source | Notes |
47
+
|----------|--------|-------|
48
+
| 1 |`git credential fill`| Configure credentials for that host in git |
49
+
50
+
For Azure DevOps, APM resolves `ADO_APM_PAT`, then an Entra ID (AAD) bearer token from Azure CLI (`az`). See [Azure DevOps](#azure-devops).
51
+
52
+
For Artifactory registry proxies, use `PROXY_REGISTRY_TOKEN`. See [Registry proxy (Artifactory)](#registry-proxy-artifactory).
53
+
54
+
For Copilot/runtime token variables (`GITHUB_COPILOT_PAT`, etc.), see [Agent Workflows](../../guides/agent-workflows/).
44
55
45
56
### Configuration variables
46
57
@@ -66,6 +77,33 @@ The org name comes from the dependency reference — `contoso/my-package` checks
66
77
67
78
Per-org tokens take priority over global tokens. Use this when different orgs require different PATs (e.g., separate SSO authorizations).
68
79
80
+
## Multi-account Git Credential Manager
81
+
82
+
APM forwards the repository path to `git credential fill`, so [Git Credential Manager (GCM)](https://github.com/git-ecosystem/git-credential-manager) can automatically pick the right GitHub account per organization -- no account-picker prompt. Existing single-account setups are unaffected: if `credential.useHttpPath` is not enabled, git credential helpers ignore the `path` attribute and match per host only.
83
+
84
+
To opt in, enable path-aware matching once:
85
+
86
+
```bash
87
+
git config --global credential.useHttpPath true
88
+
```
89
+
90
+
GCM (v2.1+) matches credential URLs by **prefix**, so a single config entry per org typically covers every repo under that org:
With the entries above, fetches against `acme/widgets`, `acme/payments`, and any other `acme/*` repo all resolve to `your-acme-account` without per-repo configuration. Other credential helpers (and older GCM versions) may require an exact path match -- consult your helper's documentation if a per-org entry is not picked up.
98
+
99
+
### Seeing an account picker mid-install?
100
+
101
+
If `apm install` triggers a GCM account-picker dialog while resolving a private repo:
102
+
103
+
1. Confirm `credential.useHttpPath` is set globally: `git config --global --get credential.useHttpPath` should print `true`.
104
+
2. Confirm a per-URL entry exists for the org: `git config --global --get-urlmatch credential https://github.com/<org>` should list the username.
105
+
3. Re-run with `--verbose`; APM logs `trying git credential fill for <host> (path=<owner>/<repo>)` so you can confirm the path APM is sending matches your config entry.
106
+
69
107
## Fine-grained PAT setup
70
108
71
109
Fine-grained PATs (`github_pat_`) are scoped to a **single resource owner** — either a user account or an organization. A user-scoped fine-grained PAT **cannot** access repos owned by an organization, even if you are a member of that org.
@@ -213,14 +251,32 @@ Bearer tokens are short-lived (~60 minutes), acquired on demand, never persisted
213
251
214
252
When authentication fails, APM prints a targeted diagnostic instead of a generic "not accessible or doesn't exist" message. The diagnostic tells you exactly which path failed and what to do next. For `--update` operations, APM verifies auth *before* modifying any files -- if the pre-flight check fails, you will see `No files were modified` and your `apm.yml`, `apm.lock.yaml`, and `apm_modules/` directory remain untouched.
215
253
254
+
## GitLab (SaaS and self-managed)
255
+
256
+
### Host classification
257
+
258
+
APM must classify a host as GitLab to use **GitLab REST v4** (for example `marketplace.json` fetches and install-time single-file reads). Configuration mirrors GHES-style host overrides:
259
+
260
+
| Variable | Purpose |
261
+
|----------|---------|
262
+
| `GITLAB_HOST` | One self-managed GitLab FQDN (e.g. `git.company.com`) |
263
+
| `APM_GITLAB_HOSTS` | Several self-managed GitLab FQDNs, comma-separated |
264
+
265
+
`gitlab.com` is detected automatically. For GitLab-class hosts, resolved credentials follow **`GITLAB_APM_PAT` → `GITLAB_TOKEN`** and then **`git credential fill`** (see [GitLab-class hosts](#gitlab-class-hosts-gitlabcom-gitlab_host-apm_gitlab_hosts) under [Token lookup](#token-lookup)). GitHub PAT env vars are not used on GitLab. Use a GitLab personal or project access token with API read access where your policy requires it.
266
+
267
+
### REST headers (GitLab vs GitHub)
268
+
269
+
For GitHub and GHES, APM sends repository API requests with `Authorization: token <PAT>` (or equivalent). For **GitLab REST v4**, PATs are sent with the **`PRIVATE-TOKEN`** header (GitLab’s convention). OAuth-style access tokens can use `Authorization: Bearer` when applicable. APM does not log token values.
| `org/repo` (bare) | `default_host()` | Global env vars → `gh auth token` → credential fill | Unauth for public repos |
221
-
| `github.com/org/repo` | github.com | Global env vars → `gh auth token` → credential fill | Unauth for public repos |
222
-
| `contoso.ghe.com/org/repo` | *.ghe.com | Global env vars → `gh auth token` → credential fill | Auth-only (no public repos) |
223
-
| GHES via `GITHUB_HOST` | ghes.company.com | Global env vars → `gh auth token` → credential fill | Unauth for public repos |
275
+
| `org/repo` (bare) | `default_host()` | Global env vars -> `gh auth token` -> credential fill | Unauth for public repos |
276
+
| `github.com/org/repo` | github.com | Global env vars -> `gh auth token` -> credential fill | Unauth for public repos |
277
+
| `contoso.ghe.com/org/repo` | *.ghe.com | Global env vars -> `gh auth token` -> credential fill | Auth-only (no public repos) |
278
+
| GHES via `GITHUB_HOST` | ghes.company.com | Global env vars -> `gh auth token` -> credential fill | Unauth for public repos |
279
+
| GitLab (`gitlab.com` or host listed in `GITLAB_HOST` / `APM_GITLAB_HOSTS`) | gitlab.com or self-managed | `GITLAB_APM_PAT` -> `GITLAB_TOKEN` -> credential helper; REST uses `PRIVATE-TOKEN`; GitHub env vars excluded | Unauth where the instance allows it |
@@ -306,27 +362,35 @@ Run with `--verbose` to see the full resolution chain:
306
362
apm install --verbose your-org/package
307
363
```
308
364
309
-
The output shows which env var matched (or `none`), the detected token type (`fine-grained`, `classic`, `oauth`, `github-app`), and the host classification (`github`, `ghe_cloud`, `ghes`, `ado`, `generic`).
365
+
The output shows which env var matched (or `none`), the detected token type (`fine-grained`, `classic`, `oauth`, `github-app`), and the host classification (`github`, `ghe_cloud`, `ghes`, `ado`, `gitlab`, `generic`).
310
366
311
-
The full resolution and fallback flow:
367
+
The full resolution and fallback flow (simplified):
312
368
313
369
```mermaid
314
370
flowchart TD
315
-
A[Dependency Reference] --> B{Per-org env var?}
371
+
A[Dependency Reference] --> HC{Host class?}
372
+
373
+
HC -->|GitHub / GHE Cloud / GHES| B{Per-org env var?}
316
374
B -->|GITHUB_APM_PAT_ORG| C[Use per-org token]
317
375
B -->|Not set| D{Global env var?}
318
376
D -->|GITHUB_APM_PAT / GITHUB_TOKEN / GH_TOKEN| E[Use global token]
319
-
D -->|Not set| F{gh auth token?<br/>GitHub-like hosts only}
320
-
F -->|Found| G[Use gh token]
321
-
F -->|Not found| H{Git credential fill?}
322
-
H -->|Found| J[Use credential]
323
-
H -->|Not found| K[No token]
377
+
D -->|Not set| GH{gh auth token?<br/>GitHub-like hosts only}
0 commit comments