|
5 | 5 |
|
6 | 6 | How this extension gets "online" — i.e. installable from a marketplace. |
7 | 7 |
|
8 | | -== The one step only a human can do |
9 | | - |
10 | | -Publishing requires an *Azure DevOps Personal Access Token (PAT)* bound to |
11 | | -the `hyperpolymath` Marketplace publisher. This is a credential that must be |
12 | | -generated interactively while signed into the Microsoft/Azure account that |
13 | | -owns the publisher. No automation (CI or otherwise) can create it. This is |
14 | | -the single blocker that has kept issue #1 open. |
15 | | - |
16 | | -=== Create the PAT (5 minutes, once) |
17 | | - |
18 | | -. Sign in at https://dev.azure.com with the account that owns the |
19 | | - `hyperpolymath` Marketplace publisher. |
20 | | -. Top-right avatar → *Personal access tokens* → *New Token*. |
21 | | -. Organization: *All accessible organizations*. |
22 | | -. Scopes: *Custom defined* → expand *Marketplace* → tick *Manage*. |
23 | | -. Create, then *copy the token now* (it is shown only once). |
| 8 | +== Authentication: Entra ID via OIDC (no stored secret) |
| 9 | + |
| 10 | +The VS Code Marketplace publish uses *Microsoft Entra ID* through *GitHub |
| 11 | +OIDC workload identity federation*. No long-lived Personal Access Token is |
| 12 | +stored anywhere: GitHub mints a short-lived token for each workflow run and |
| 13 | +exchanges it for an Entra access token. This removes the leak / theft / |
| 14 | +rotation risk inherent to PATs. |
| 15 | + |
| 16 | +The one-time setup below must be done by a human with admin rights in the |
| 17 | +Entra tenant that owns the `hyperpolymath` publisher. No automation can |
| 18 | +perform it. |
| 19 | + |
| 20 | +=== One-time Entra setup |
| 21 | + |
| 22 | +. *App registration* — in the Entra tenant that owns the publisher, create |
| 23 | + an app registration (service principal). Note its *Application (client) |
| 24 | + ID* and the *Directory (tenant) ID*. |
| 25 | +. *Federated credential* — on that app registration: |
| 26 | + *Certificates & secrets → Federated credentials → Add credential*. |
| 27 | + Scenario: *GitHub Actions deploying Azure resources*. |
| 28 | ++ |
| 29 | +[cols="1,2"] |
| 30 | +|=== |
| 31 | +|Field |Value |
| 32 | + |
| 33 | +|Organization |`hyperpolymath` |
| 34 | +|Repository |`vscode-a2ml` |
| 35 | +|Entity type |`Branch` (e.g. `main`) or `Tag` (e.g. `v*`) or `Environment` |
| 36 | +|Audience |`api://AzureADTokenExchange` (default) |
| 37 | +|=== |
| 38 | +. *Grant publisher rights* — sign in to |
| 39 | + https://marketplace.visualstudio.com/manage/publishers/ as the publisher |
| 40 | + owner and add the service principal as a member of the `hyperpolymath` |
| 41 | + publisher (Manage rights). If the publisher does not exist yet, create it |
| 42 | + there once; the publisher ID must equal the `publisher` field in |
| 43 | + `package.json`. |
| 44 | +. *Expose the IDs to CI* — in GitHub: |
| 45 | + *Settings → Secrets and variables → Actions → Variables → New repository |
| 46 | + variable*: |
| 47 | ++ |
| 48 | +[cols="1,2"] |
| 49 | +|=== |
| 50 | +|Variable |Value |
24 | 51 |
|
25 | | -If the `hyperpolymath` publisher does not yet exist, create it once at |
26 | | -https://marketplace.visualstudio.com/manage/publishers/ (publisher ID must |
27 | | -equal the `publisher` field in `package.json`). |
| 52 | +|`AZURE_CLIENT_ID` |Application (client) ID from step 1 |
| 53 | +|`AZURE_TENANT_ID` |Directory (tenant) ID from step 1 |
| 54 | +|=== |
| 55 | ++ |
| 56 | +These are *variables*, not secrets — they are identifiers, not |
| 57 | +credentials, and confer no access without the federated trust. |
| 58 | +. (Optional, open-source registry) Open VSX has no Entra/OIDC equivalent, |
| 59 | + so it still uses a token. Add secret `OVSX_PAT` from |
| 60 | + https://open-vsx.org → Settings → Access Tokens. Keep it short-expiry |
| 61 | + and rotate routinely; omit it entirely to skip Open VSX. |
28 | 62 |
|
29 | 63 | == Automated path (recommended) |
30 | 64 |
|
31 | | -. In GitHub: *Settings → Secrets and variables → Actions → New repository |
32 | | - secret*. |
33 | | -. Add `VSCE_PAT` = the token from above. |
34 | | -. (Optional, open-source registry) add `OVSX_PAT` from |
35 | | - https://open-vsx.org → Settings → Access Tokens. |
36 | | -. Bump `version` in `package.json`, commit, then tag and push: |
37 | | -+ |
| 65 | +After the one-time setup, publishing is a tag push: |
| 66 | + |
38 | 67 | [source,bash] |
39 | 68 | ---- |
| 69 | +# bump "version" in package.json first, then: |
| 70 | +git commit -am "Release v0.1.0" |
40 | 71 | git tag v0.1.0 |
41 | 72 | git push origin v0.1.0 |
42 | 73 | ---- |
43 | 74 |
|
44 | | -The `Marketplace Publish` workflow packages a `.vsix` and publishes to the |
45 | | -VS Code Marketplace (and Open VSX if `OVSX_PAT` is set). Registries without |
46 | | -a configured token are skipped, not failed. The workflow can also be run |
47 | | -manually via *Actions → Marketplace Publish → Run workflow*. |
| 75 | +The `Marketplace Publish` workflow packages a `.vsix`, authenticates to the |
| 76 | +VS Code Marketplace via Entra OIDC, and publishes (plus Open VSX if |
| 77 | +`OVSX_PAT` is set). Registries without configured credentials are skipped, |
| 78 | +not failed. The workflow can also be run manually via |
| 79 | +*Actions → Marketplace Publish → Run workflow*. |
48 | 80 |
|
49 | 81 | == Manual one-off path (no CI) |
50 | 82 |
|
51 | | -Requires Deno (the repo's standard toolchain; npm/bun are blocked). |
| 83 | +OIDC federation only works from GitHub Actions. For a local one-off publish |
| 84 | +you must use an Azure DevOps PAT. Treat this as a fallback, not the norm: |
| 85 | +scope it to *Marketplace → Manage* only, set a short expiry, and never |
| 86 | +commit or persist it. |
52 | 87 |
|
53 | 88 | [source,bash] |
54 | 89 | ---- |
55 | | -export VSCE_PAT=... # the Azure DevOps PAT |
| 90 | +# Create at https://dev.azure.com -> Personal access tokens |
| 91 | +# Organization: All accessible | Scope: Marketplace > Manage |
| 92 | +export VSCE_PAT=... |
56 | 93 | deno run -A --node-modules-dir=auto npm:@vscode/vsce@3.2.1 package |
57 | 94 | deno run -A --node-modules-dir=auto npm:@vscode/vsce@3.2.1 \ |
58 | 95 | publish --packagePath ./*.vsix --pat "$VSCE_PAT" |
59 | 96 | ---- |
60 | 97 |
|
| 98 | +Alternatively, if you have the Azure CLI logged in to the publisher's |
| 99 | +tenant (`az login`), you can skip the PAT locally too: |
| 100 | + |
| 101 | +[source,bash] |
| 102 | +---- |
| 103 | +deno run -A --node-modules-dir=auto npm:@vscode/vsce@3.2.1 \ |
| 104 | + publish --azure-credential --packagePath ./*.vsix |
| 105 | +---- |
| 106 | + |
61 | 107 | == Verifying it is online |
62 | 108 |
|
63 | 109 | * VS Code Marketplace: |
|
0 commit comments