Skip to content

fix(skills): accept .zip and directory inputs for skill update --file#8509

Open
huimiu wants to merge 1 commit into
mainfrom
hui/fix-skills-update
Open

fix(skills): accept .zip and directory inputs for skill update --file#8509
huimiu wants to merge 1 commit into
mainfrom
hui/fix-skills-update

Conversation

@huimiu
Copy link
Copy Markdown
Member

@huimiu huimiu commented Jun 1, 2026

Summary

Fixes #8489. azd ai skill update --file now accepts the same three input shapes as azd ai skill create --file — a single SKILL.md, a .zip archive, or a directory whose root contains SKILL.md — so users no longer have to fall back to the destructive create --force workaround that deletes the skill and every prior version.

Input create --file update --file (before) update --file (this PR)
SKILL.md
.zip archive (SKILL.md at root) ❌ "use create --force" ✅ — appends a new default version
Directory (SKILL.md at root) ❌ "use create --force" ✅ — appends a new default version
Inline --description / --instructions n/a
--set-default-version <ver> n/a

Why this matters

The existing rejection forced authors of multi-file skill bundles (folders or zips) into a destructive flow: create --force deletes the skill and all prior versions before recreating it. The whole point of update is to add a new immutable version while preserving history — and the underlying POST /skills/{name}/versions endpoint is already non-destructive, so this was purely a CLI-side validation gap. CI / GitOps flows that build dist/my-skill/ and publish a new version now have a non-destructive path.

Changes

  • internal/cmd/skill_update.go — Add updateMode enum + selectUpdateMode mirroring selectCreateMode (detects directory before extension; surfaces stat errors for missing no-extension paths). Dispatch Run on the mode: --set-default-version, inline, .md, .zip, and directory each route to a focused helper. runFilePackage and runFileDirectory reuse client.CreateVersionFromZip / skill_api.ArchiveDirectory / skill_api.LocateSkillMdInDir but wrap errors with exterrors.OpUpdateSkill (not OpCreateSkill). New printUpdateResult helper preserves current JSON behavior — emits only the version envelope in outputJSON mode (no human text), so callers piping into jq keep getting valid JSON. Refresh the long help and --file description for the three input shapes; drop the "ZIP packages are not accepted here" sentence and the destructive create --force pointer.
  • internal/cmd/skill_update_test.go — Drop TestUpdateAction_ZipSuggestionMentionsDestructive and TestUpdateAction_DirectoryRejectedWithDestructivePointer (the rejection behavior they asserted is the bug). Add selectUpdateMode routing tests for every shape (.zip upper- and lower-case, directory, .md, inline, set-default alone, set-default + content conflict, inline + file conflict, no input, unsupported extension, missing no-extension path surfaces stat error). Add TestUpdateAction_DirectoryWithoutSkillMdFails, TestUpdateAction_PackageFileMissingFails, and TestUpdateAction_PackageFileIsDirectoryFails calling the run methods with a nil client — the preflight checks fire before any network call, so a nil client is safe and matches the existing TestCreateAction_DirectoryWithoutSkillMdFails pattern.
  • internal/cmd/skill_validate_test.go — Replace TestUpdateAction_RejectsZipFile with TestUpdateAction_AcceptsZipFile asserting both ./pkg.zip and ./PKG.ZIP route to updateModeFilePackage. Extend TestUpdateAction_AcceptsMdFile to also assert routing via selectUpdateMode.
  • README.md — Add .zip and directory examples to the update usage block; replace the "inline-only" paragraph with one that explains update now accepts the same shapes as create non-destructively.
  • AGENTS.md — Refresh the update bullet under "File handling" to reflect the new shapes and the non-destructive append semantics.

What this PR deliberately does NOT change

  • No --force on update — the issue explicitly keeps --force create-only, and update doesn't delete anything, so the safety check create --force needs (SKILL.md name mismatch preflight) doesn't apply here.
  • No version.txt / extension.yaml / CHANGELOG.md bump — per cli/azd/extensions/azure.ai.skills/AGENTS.md line 80, those three files belong to the version-bump PR in the two-PR release convention. A maintainer can pick them up at release prep time.
  • No new SKILL.md name mismatch preflight on updateupdate doesn't delete anything, so a mismatch can't wipe an unrelated skill; the server stores the new version under the positional name regardless. (Out of scope for this fix.)

Validation

cd cli/azd/extensions/azure.ai.skills
go build ./... && go vet ./... && go test ./...
gofmt -l . && golangci-lint run --timeout 5m ./internal/cmd/...

All clean (ok on every package, 0 issues from golangci-lint, no gofmt diff, no cspell issues on the touched files). The new and modified tests in internal/cmd pass.

…--file` (#8489)

`azd ai skill update --file` now accepts the same three input shapes as
`azd ai skill create --file`: a single SKILL.md, a .zip archive, or a
directory whose root contains SKILL.md. Previously update only accepted
.md and rejected .zip / directories with a pointer to `create --force`,
which is destructive (deletes the skill and every prior version).

Updates create a new immutable version via POST /skills/{name}/versions
and promote it to default_version. Prior versions are preserved.

- internal/cmd/skill_update.go: add selectUpdateMode + updateMode enum
  mirroring selectCreateMode; add runFilePackage and runFileDirectory
  on updateAction that wrap errors with OpUpdateSkill; add
  printUpdateResult helper that emits only the version JSON in
  outputJSON mode (no human text on JSON paths); refresh long-help and
  --file description for the three input shapes.
- internal/cmd/skill_update_test.go: drop obsolete .zip / directory
  rejection tests; add selectUpdateMode routing tests for .zip, directory,
  .md, inline, set-default, conflict, missing path; add DirectoryWithoutSkillMd
  and PackageFileMissing preflight tests calling the run methods with a nil
  client (the preflight returns before any network call).
- internal/cmd/skill_validate_test.go: replace RejectsZipFile with
  AcceptsZipFile asserting .zip routes to updateModeFilePackage.
- README.md, AGENTS.md: refresh update file-handling docs.

Fixes #8489
Copilot AI review requested due to automatic review settings June 1, 2026 09:25
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

📋 Prioritization Note

Thanks for the contribution! The linked issue isn't in the current milestone yet.
Review may take a bit longer — reach out to @rajeshkamal5050 or @kristenwomack if you'd like to discuss prioritization.

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

This PR fixes parity between azd ai skill create --file and azd ai skill update --file in the azure.ai.skills extension by allowing update to accept .zip archives and directories (with SKILL.md at the root), making updates non-destructive while preserving version history.

Changes:

  • Added selectUpdateMode + updateMode dispatch in skill update to route inline, .md, .zip, and directory inputs to the appropriate upload path (including directory-to-zip packaging).
  • Updated/expanded unit tests to validate new routing behavior and preflight error handling for zip/directory inputs.
  • Refreshed extension docs/help text to describe the new accepted --file shapes and the non-destructive versioning behavior.

Reviewed changes

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

Show a summary per file
File Description
cli/azd/extensions/azure.ai.skills/README.md Documents update --file examples for .zip and directories and clarifies non-destructive behavior.
cli/azd/extensions/azure.ai.skills/internal/cmd/skill_validate_test.go Updates validation tests to assert .zip/.ZIP inputs are accepted and routed correctly.
cli/azd/extensions/azure.ai.skills/internal/cmd/skill_update.go Implements mode selection + dispatch and adds zip/directory upload support for skill update.
cli/azd/extensions/azure.ai.skills/internal/cmd/skill_update_test.go Adds routing tests and new preflight-only tests for zip/directory update paths.
cli/azd/extensions/azure.ai.skills/AGENTS.md Updates extension-specific guidance to match new update --file supported shapes and semantics.

@github-actions github-actions Bot added the ext-agents azure.ai.{agents,connections,inspector,projects,routines,skills,toolboxes} extensions label Jun 1, 2026
@huimiu huimiu changed the title [azure.ai.skills] Accept .zip and directory inputs for skill update --file (#8489) fix(skills): accept .zip and directory inputs for skill update --file Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext-agents azure.ai.{agents,connections,inspector,projects,routines,skills,toolboxes} extensions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[azure.ai.skills] azd ai skill update --file should accept .zip archives and directories (parity with create)

2 participants