Add a validate-only endpoint (POST /api/cli/v1/skills/{namespace}/publish/validate)
that runs the full pre-publish validation chain without persisting anything.
This allows developers to check their package locally before actual publishing.
The validation covers:
- SKILL.md existence and frontmatter parsing (name, description required)
- File extension whitelist and size limits
- Credential leak scanning with line-number precision
- Slug generation and name conflict detection
CLI usage: `skillhub publish <path> --dry-run`
Closes#429
When --agent is provided without --scope, scope was inferred via
root.startsWith(cwd), which mislabels user roots as project when
cwd === home. Use profile.userRoots(home) membership instead, so the
candidate scope reflects the profile's intent rather than path prefix
overlap. The chosen root path itself is unchanged.
- Distinguish user vs project install scope via explicit --scope flag
- Interactive mode prompts for scope when --scope/--agent/--dir not provided
- Non-interactive bare install preserves existing behavior (backward compatible)
- Mutual exclusion: --dir cannot be combined with --scope or --agent
- Symmetric fallback: --scope user falls back to ~/.agents/skills,
--scope project falls back to <cwd>/.agents/skills
- Strict TTY check requires both stdin and stdout TTY plus no --json
- Scope-aware candidate generation avoids root.startsWith(cwd) misjudgement
when cwd === home or paths overlap
- Correct gemini-cli (.gemini/skills) and kiro-cli (.kiro/skills) paths
in install path tables across README and guide docs
- Note CLI fallback uses .agents/skills (with s) in skill protocol doc
Replace $scheme with $http_x_forwarded_proto in proxy headers to correctly
forward the original client protocol when behind a reverse proxy or load
balancer. This fixes OAuth2 authentication issues where redirects would use
the wrong protocol scheme.
When approving a promotion, the new SkillVersion was created without copying
bundleReady and downloadReady from the source version, causing the download
button to be permanently disabled for promoted skills.
Windows ZIP library produces backslashes in file paths while Unix uses forward slashes. Normalize all paths to forward slashes before assertion to ensure tests pass on all platforms.
- Fix Windows test failure by using regex that accepts both / and \ path separators in install-command.test.ts
- Rename contradictory test case in publish-command.test.ts from "surfaces a non-zero exit" to "is handled without crash" to match actual assertion behavior
Migrated 39 test files covering CLI integration and unit testing:
- 6 new integration tests (auth-resolution, concurrency, cross-command, inventory-resilience, multi-registry, version-upgrade-flow)
- Enhanced 7 existing integration tests with comprehensive scenarios
- Updated 2 unit tests with correct exit code expectations
All tests use fake registry approach (no E2E/browser required) and pass lint/build/test checks.
The `status="$(env ... printf | bash ... && echo 0 || echo $?)"` pattern
doesn't correctly capture the script's exit code because the command
substitution and pipe interact poorly. Use direct assignment with
`|| status=$?` instead.
The old approach (breaking origin URL) caused `git pull` to fail
before reaching the push step. Use a git wrapper that only fails
on `push` so the rest of the script runs normally.
Remove test 7 (remote tag race condition) — the scenario is nearly
impossible with the new baseline sync logic and too complex to
reliably simulate. Fix variable naming inconsistencies from the
renumbering.
Old test 7 used `--no-tags` config to prevent fetch from pulling the
remote tag, but that doesn't reflect any real-world scenario. With the
new baseline sync logic, a pre-existing remote tag would be synced
into the local version, eliminating the conflict path the test claimed
to cover.
Replace with a git wrapper that injects the conflicting tag into origin
right before the script's `ls-remote` check, which simulates a real
race between two developers attempting to release the same version.
Tests write stdout.log/stderr.log into the test repo root, which made
`git status --porcelain` non-empty and broke test 3 (non-main branch
abort) by tripping the dirty-tree check first.
Add a .gitignore to the test fixture repo to filter out these files.
publish-npm and create-release now checkout the same ref as
build-and-test (the input tag or push ref), preventing source
mismatch between npm package and GitHub Release artifacts.
1. npm version check: three-state logic (exists/missing/error) to prevent
silent skip on network failures, registry 5xx, or auth issues.
2. workflow_dispatch: checkout the specified tag and validate SHA matches,
preventing builds from wrong ref.
3. Atomic push: use `git push --atomic` and detect unpushed tags via
`git ls-remote` instead of `--no-merged` (catches branch-pushed-but-
tag-failed state).
Add pre-flight check in publish-cli.sh to detect unpushed commits and tags
from previous failed pushes. When detected, the script exits with clear
recovery instructions:
1. Retry push (for transient network failures)
2. Rollback and re-release (for clean restart)
This prevents the baseline sync logic from skipping failed versions when
local tags participate in version calculation after a push failure.
Addresses feedback from dongmucat in PR #422.
1. Update release-cli.yml to make create-release depend on publish-npm with proper skip_npm handling, preventing half-released state where GitHub Release exists but npm package is unavailable.
2. Rewrite publish-cli-test.sh to cover the new publish flow: main branch check, dirty tree detection, tag baseline sync, version bumping, tag conflict detection, user cancellation, and atomic push verification.
Add a third peer tab 'CLI' to LandingQuickStartSection that surfaces the
official install command 'npm i -g @astron-team/skillhub'. Layout uses
grid-cols-1 md:grid-cols-3 so mobile shows tabs stacked and desktop
shows three equal-width columns.
Addresses iflytek/skillhub#419 (homepage Quick Start part only).
- Add release-cli.yml GitHub Actions workflow: build, test, npm publish,
and GitHub Release triggered by cli-v* tags
- Rewrite scripts/publish-cli.sh: local bump + commit + tag + push,
enforces main branch, idempotent tag checks
- Add concurrency group and release idempotency to workflow
- Add make publish-cli / publish-cli-minor / publish-cli-major targets
- Add cli/RELEASE.md documenting the full release process
Gemini review feedback: the previous != PUBLISHED condition was too broad
and could inadvertently overwrite terminal states like REJECTED or YANKED.
Now explicitly check == SCANNING before transitioning status.
Super admin auto-publish flow was skipping security scanning entirely.
Now triggerScan is called regardless of autoPublish flag, while preserving
the PUBLISHED status (scan runs as post-publish audit rather than blocking).
Closes#415
- Handle 502/503 status codes as network errors (EXIT.network = 3)
- Previously these were treated as generic errors (EXIT.generic = 1)
- Fixes integration tests for login and search network failure scenarios
- Bump version to 0.1.4
Resolved conflicts by keeping both sides:
- web/src/api/client.ts: preserve paginated listMembers(slug, {page,size})
and add delete(slug) from main.
- web/src/shared/hooks/use-namespace-queries.ts: keep useUpdateNamespace
and useTransferNamespaceOwnership from this branch, plus useDeleteNamespace
from main.
appendNamespaceMember was being called via setQueriesData across all cached
pages, causing the new member to appear at the end of every page. The
invalidation will refresh the list correctly.
Add namespace edit dialog, transfer ownership dialog, and member list pagination. Update API layer to support pagination (PagedResponse), add useUpdateNamespace and useTransferNamespaceOwnership hooks with pagination-aware optimistic updates. Integrate edit button in NamespaceHeader and transfer button on members page. Add i18n keys for all new features (en + zh).