Skip to content

Sync eng/common directory with azure-sdk-tools for PR 15278#7083

Open
azure-sdk wants to merge 3 commits intomainfrom
sync-eng/common-add-playground-bundle-template-15278
Open

Sync eng/common directory with azure-sdk-tools for PR 15278#7083
azure-sdk wants to merge 3 commits intomainfrom
sync-eng/common-add-playground-bundle-template-15278

Conversation

@azure-sdk
Copy link
Copy Markdown
Collaborator

Sync eng/common directory with azure-sdk-tools for PR Azure/azure-sdk-tools#15278 See eng/common workflow

JoshLove-msft and others added 3 commits April 24, 2026 00:47
Adds an opt-in capability to the shared TypeSpec emitter pipeline template that bundles an emitter package and uploads it to the typespec playground blob storage. The uploaded <pkgName>/latest.json import map is consumed by in-browser playgrounds (e.g. https://azure.github.io/typespec-azure) via their additionalPlaygroundPackages mechanism.

Self-contained tooling lives in eng/common/playground-bundle/ and mirrors @typespec/bundle-uploader from microsoft/typespec (which is private and cannot be installed from npm).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 24, 2026 00:54
@azure-sdk azure-sdk requested a review from a team as a code owner April 24, 2026 00:54
@azure-sdk azure-sdk requested a review from JoshLove-msft April 24, 2026 00:54
@azure-sdk azure-sdk added EngSys This issue is impacting the engineering system. Central-EngSys This issue is owned by the Engineering System team. labels Apr 24, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Syncs in a self-contained TypeSpec “bundle + upload to playground storage” tool into eng/common, and wires it into the shared archetype-typespec-emitter.yml template so emitters can optionally publish bundles for in-browser playground consumption.

Changes:

  • Added eng/common/playground-bundle/ Node tooling (script + pinned dependencies + docs) to create a TypeSpec bundle and upload it to the typespec storage account.
  • Extended archetype-typespec-emitter.yml with a new UploadPlaygroundBundle parameter and conditional steps to install and run the uploader in internal, non-PR builds.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
eng/common/playground-bundle/upload.mjs New uploader script that bundles an emitter and uploads JS + manifest + latest import map to blob storage.
eng/common/playground-bundle/package.json New package definition with pinned dependencies and Node engine requirement.
eng/common/playground-bundle/package-lock.json Lockfile to make installs reproducible for the uploader tooling.
eng/common/playground-bundle/README.md Documentation for how the uploader is used by the pipeline template.
eng/common/pipelines/templates/archetype-typespec-emitter.yml Adds UploadPlaygroundBundle parameter and conditional install/upload steps in the Build job.
Files not reviewed (1)
  • eng/common/playground-bundle/package-lock.json: Language not supported

Comment on lines +69 to +73
const content = JSON.stringify(manifest);
await blob.upload(content, content.length, {
blobHTTPHeaders: { blobContentType: "application/json; charset=utf-8" },
conditions: { ifNoneMatch: "*" },
});
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BlockBlobClient.upload() expects the content length in bytes, but content.length is a JS string character count. For non-ASCII characters this can send an incorrect contentLength and cause upload failures/corruption. Use Buffer.byteLength(content, 'utf8') for the length, or switch to uploadData(Buffer.from(content, 'utf8'), ...) (which avoids manually providing a length).

Copilot uses AI. Check for mistakes.
async function updatePackageLatest(container, pkgName, index) {
const blob = container.getBlockBlobClient(normalizePath(joinUnix(pkgName, "latest.json")));
const content = JSON.stringify(index);
await blob.upload(content, content.length, {
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as uploadManifest: content.length is character count, not byte count, but upload() needs a byte length. Prefer Buffer.byteLength(...) or uploadData(Buffer.from(content, 'utf8'), ...) to avoid mismatched lengths.

Suggested change
await blob.upload(content, content.length, {
await blob.upload(content, Buffer.byteLength(content, "utf8"), {

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +46
if (arg === "--package-path") {
args.packagePath = argv[++i];
} else if (arg === "--version") {
args.version = argv[++i];
} else {
throw new Error(`Unknown argument: ${arg}`);
}
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseArgs increments the index and assigns the next argv element for --package-path/--version, but it doesn't validate that a value actually exists. If the caller passes --version (or --package-path) as the last argument, this will silently set undefined and lead to a later, less actionable error. Consider explicitly checking for a missing value and throwing a targeted error.

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +184
- script: npm ci
displayName: 'Install playground bundle uploader'
workingDirectory: $(Build.SourcesDirectory)/eng/common/playground-bundle
env:
NPM_CONFIG_USERCONFIG: $(emitterNpmrcPath)

- task: AzureCLI@2
displayName: 'Upload playground bundle'
inputs:
azureSubscription: "TypeSpec Storage"
scriptType: "bash"
scriptLocation: "inlineScript"
workingDirectory: $(Build.SourcesDirectory)
inlineScript: >
node eng/common/playground-bundle/upload.mjs
--package-path ${{ parameters.EmitterPackagePath }}
--version $(initialize.emitterVersion)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stage runs npm ci and then node .../upload.mjs, but the Build job doesn't pin/ensure a Node version (unlike other jobs in this template that use UseNode@1). Since eng/common/playground-bundle/package.json requires Node >= 20.19.0, this can break when the agent image default Node changes. Consider adding a UseNode@1 step (e.g. 22.x) before the npm/node steps here to make the environment deterministic.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Central-EngSys This issue is owned by the Engineering System team. EngSys This issue is impacting the engineering system.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants