-
Notifications
You must be signed in to change notification settings - Fork 0
chore: add tag-driven release workflow and community health files #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: Bug report | ||
| description: Something in the CLI behaves incorrectly | ||
| labels: [bug] | ||
| body: | ||
| - type: input | ||
| id: version | ||
| attributes: | ||
| label: CLI version | ||
| description: Output of `yuque --version` | ||
| placeholder: 1.1.0 | ||
| validations: | ||
| required: true | ||
| - type: input | ||
| id: environment | ||
| attributes: | ||
| label: Environment | ||
| description: OS and Node.js version (`node --version`) | ||
| placeholder: macOS 15 / Node 22.11.0 | ||
| validations: | ||
| required: true | ||
| - type: textarea | ||
| id: command | ||
| attributes: | ||
| label: Command and behavior | ||
| description: >- | ||
| The exact command you ran (redact tokens and private doc slugs), what | ||
| happened, and what you expected. Include the exit code (`echo $?`) | ||
| and output β `--json` output is especially helpful. | ||
| placeholder: | | ||
| $ yuque doc get team/handbook onboarding | ||
| exit code: 4 | ||
| ... | ||
| validations: | ||
| required: true | ||
| - type: textarea | ||
| id: context | ||
| attributes: | ||
| label: Additional context | ||
| description: >- | ||
| Anything else relevant β custom `--host` / space host, whether a team | ||
| token or personal token is used, proxy setup, etc. | ||
| validations: | ||
| required: false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| blank_issues_enabled: true | ||
| contact_links: | ||
| - name: Security vulnerability | ||
| url: https://github.com/yuque/yuque-open-cli/security/advisories/new | ||
| about: Please report security issues privately via a security advisory, not a public issue. | ||
| - name: Yuque OpenAPI documentation | ||
| url: https://www.yuque.com/yuque/developer/api | ||
| about: Questions about the Yuque API itself (rather than this CLI) are answered here. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| name: Feature request | ||
| description: Propose a new command, flag, or behavior | ||
| labels: [enhancement] | ||
| body: | ||
| - type: textarea | ||
| id: problem | ||
| attributes: | ||
| label: Problem | ||
| description: What are you trying to do that the CLI currently makes hard? | ||
| validations: | ||
| required: true | ||
| - type: textarea | ||
| id: proposal | ||
| attributes: | ||
| label: Proposed command surface | ||
| description: >- | ||
| Sketch the command(s) as you would type them. If this maps to a Yuque | ||
| OpenAPI endpoint, link it β the CLI surface is spec-driven. | ||
| placeholder: | | ||
| yuque note list --all --json | ||
| validations: | ||
| required: true | ||
| - type: textarea | ||
| id: alternatives | ||
| attributes: | ||
| label: Alternatives considered | ||
| description: Workarounds you use today (scripts, other tools, raw curl). | ||
| validations: | ||
| required: false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <!-- Describe what changes and why. Link the issue if there is one. --> | ||
|
|
||
| ## Checklist | ||
|
|
||
| - [ ] `npm run check` passes locally (the exact gate CI runs) | ||
| - [ ] User-visible changes are reflected in **both** `README.md` and `README.zh-CN.md`, and in `CHANGELOG.md` | ||
| - [ ] API-surface changes follow the spec-driven flow: `spec/yuque-openapi.yaml` edited, `npm run gen:types` run, command surface extended (see [CONTRIBUTING.md](https://github.com/yuque/yuque-open-cli/blob/main/CONTRIBUTING.md)) | ||
| - [ ] Structural changes are reflected in `AGENTS.md` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| name: Release | ||
|
|
||
| # Tag-driven release: push a `vX.Y.Z` tag and this workflow runs the full | ||
| # check gate, publishes to npm with provenance, and creates the GitHub | ||
| # Release from the matching CHANGELOG.md section. | ||
| # | ||
| # One-time setup: add an npm automation token as the NPM_TOKEN repo secret | ||
| # (Settings β Secrets and variables β Actions). Publishing fails fast with a | ||
| # clear error if the secret is missing. | ||
| # | ||
| # Release steps (also documented in CONTRIBUTING.md): | ||
| # 1. Bump `version` in package.json and add the `## X.Y.Z` CHANGELOG entry. | ||
| # 2. Land that on main, then: git tag vX.Y.Z && git push origin vX.Y.Z | ||
|
|
||
| on: | ||
| push: | ||
| tags: ['v*.*.*'] | ||
|
|
||
| permissions: | ||
| contents: write # create the GitHub Release | ||
| id-token: write # npm provenance attestation | ||
|
|
||
| jobs: | ||
| release: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 22 | ||
| cache: npm | ||
| registry-url: https://registry.npmjs.org | ||
| # npm install, not npm ci β see ci.yml for the lockfile rationale. | ||
| - run: npm install --no-audit --no-fund | ||
| - name: Verify tag matches package.json version | ||
| run: | | ||
| pkg_version="$(node -p "require('./package.json').version")" | ||
| tag_version="${GITHUB_REF_NAME#v}" | ||
| if [ "$pkg_version" != "$tag_version" ]; then | ||
| echo "Tag $GITHUB_REF_NAME does not match package.json version $pkg_version" >&2 | ||
| exit 1 | ||
| fi | ||
| - name: Full check gate | ||
| run: npm run check | ||
| - name: Publish to npm (with provenance) | ||
| run: | | ||
| if [ -z "$NODE_AUTH_TOKEN" ]; then | ||
| echo "NPM_TOKEN secret is not configured (Settings β Secrets and variables β Actions)" >&2 | ||
| exit 1 | ||
| fi | ||
| npm publish --provenance --access public | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
| - name: Create GitHub Release from CHANGELOG | ||
| run: | | ||
| version="${GITHUB_REF_NAME#v}" | ||
| awk -v ver="$version" ' | ||
| $0 ~ "^## "ver"$" { found=1; next } | ||
| found && /^## / { exit } | ||
| found { print } | ||
| ' CHANGELOG.md > /tmp/release-notes.md | ||
| if ! [ -s /tmp/release-notes.md ]; then | ||
| echo "No CHANGELOG.md section found for $version" >&2 | ||
| exit 1 | ||
| fi | ||
| gh release create "$GITHUB_REF_NAME" \ | ||
| --title "$GITHUB_REF_NAME" \ | ||
| --notes-file /tmp/release-notes.md | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| # Contributing to yuque-open-cli | ||
|
|
||
| Thanks for your interest in improving the Yuque CLI! This document covers the | ||
| development workflow, the conventions the codebase enforces, and how releases | ||
| are cut. | ||
|
|
||
| > Working with an AI agent (or as one)? [AGENTS.md](./AGENTS.md) is the | ||
| > authoritative architecture map and convention guide β it is kept in lockstep | ||
| > with the code by tests. | ||
|
|
||
| ## Development setup | ||
|
|
||
| Requirements: Node.js β₯ 20. | ||
|
|
||
| ```bash | ||
| git clone https://github.com/yuque/yuque-open-cli.git | ||
| cd yuque-open-cli | ||
| npm install | ||
| npm run dev -- --help # run the CLI from source (tsx) | ||
| ``` | ||
|
|
||
| To exercise commands against the real API you need a token from | ||
| [Yuque Developer Settings](https://www.yuque.com/settings/tokens): | ||
|
|
||
| ```bash | ||
| YUQUE_TOKEN=... npm run dev -- auth status | ||
| ``` | ||
|
|
||
| ## The check gate | ||
|
|
||
| Every change must pass the single unified gate β the same command CI runs: | ||
|
|
||
| ```bash | ||
| npm run check | ||
| ``` | ||
|
|
||
| That is: ESLint, Prettier check, generated-types drift check, `tsc`, unit | ||
| tests with coverage, build, packaged-CLI smoke test, and the mock-server e2e | ||
| suite. If `npm run check` is green locally, CI will be green. | ||
|
|
||
| Useful narrower loops while iterating: | ||
|
|
||
| ```bash | ||
| npm test # unit tests once | ||
| npm run test:watch # unit tests in watch mode | ||
| npm run test:e2e # build + e2e against the bundled mock server | ||
| ``` | ||
|
|
||
| ## Spec-driven workflow | ||
|
|
||
| The OpenAPI spec is the source of truth for the API surface: | ||
|
|
||
| 1. Edit `spec/yuque-openapi.yaml` β never edit `src/client/types.gen.ts` by | ||
| hand. | ||
| 2. Run `npm run gen:types` to regenerate the types. | ||
| 3. Adapt the thin compatibility layer in `src/client/types.ts` if public type | ||
| names changed. | ||
|
|
||
| `npm run gen:types:check` (part of the check gate) fails if the generated | ||
| file drifts from the spec. `tests/spec-coverage.test.ts` fails if a spec | ||
| operation has no corresponding CLI command, so extending the spec means | ||
| extending the command surface in the same change. | ||
|
|
||
| ## Code layout and conventions | ||
|
|
||
| ``` | ||
| bin.ts β cli.ts (commander program, error β exit code) | ||
| βββ commands/<domain>.ts (flags, confirmation, rendering) | ||
| βββ client/api/<domain>.ts (typed calls, envelope unwrap) | ||
| βββ client/http.ts (auth header, retry/backoff, YuqueError) | ||
| ``` | ||
|
|
||
| - One domain = one `src/commands/<domain>.ts` exporting a single | ||
| `register<Domain>Commands` function, plus one thin `src/client/api/<domain>.ts`. | ||
| - `src/client/http.ts` is the only HTTP exit; `src/errors.ts` is the only | ||
| place exit codes are defined. | ||
| - Destructive commands must go through `confirmDestructive` (`--yes` to skip). | ||
| - Every command supports `--json`; human-readable output goes through the | ||
| helpers in `src/output.ts`. | ||
| - The full `--help` surface is pinned by a golden file β when you add or | ||
| change flags, regenerate it as instructed by the failing test and review | ||
| the diff. | ||
|
|
||
| ## Pull requests | ||
|
|
||
| - Branch from `main`; keep PRs focused on one concern. | ||
| - Update docs in the same PR: both `README.md` and `README.zh-CN.md` for any | ||
| user-visible change, `AGENTS.md` for structural changes, and `CHANGELOG.md` | ||
| under the upcoming version heading. | ||
| - `npm run check` must pass. | ||
|
|
||
| ## Releasing (maintainers) | ||
|
|
||
| Releases are tag-driven via `.github/workflows/release.yml`: | ||
|
|
||
| 1. Bump `version` in `package.json` and add the matching `## X.Y.Z` section | ||
| at the top of `CHANGELOG.md`; land that on `main`. | ||
| 2. Tag and push: | ||
|
|
||
| ```bash | ||
| git tag vX.Y.Z && git push origin vX.Y.Z | ||
| ``` | ||
|
|
||
| The workflow re-runs the full check gate, publishes to npm with provenance, | ||
| and creates the GitHub Release from the CHANGELOG section. It requires the | ||
| `NPM_TOKEN` repository secret (an npm automation token with publish rights on | ||
| `yuque-open-cli`). | ||
|
|
||
| ## Reporting security issues | ||
|
|
||
| Please do not open public issues for vulnerabilities β see | ||
| [SECURITY.md](./SECURITY.md). |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Security Policy | ||
|
|
||
| ## Supported versions | ||
|
|
||
| Only the latest release published on npm receives security fixes. | ||
|
|
||
| ## Reporting a vulnerability | ||
|
|
||
| Please report vulnerabilities privately via | ||
| [GitHub Security Advisories](https://github.com/yuque/yuque-open-cli/security/advisories/new) | ||
| β do not open a public issue. | ||
|
|
||
| Include what you can: affected version, reproduction steps, and impact. You | ||
| can expect an acknowledgement within a few business days. | ||
|
|
||
| ## Scope notes for this CLI | ||
|
|
||
| - The CLI authenticates with a Yuque API token supplied via `--token`, | ||
| `YUQUE_TOKEN`, or `YUQUE_PERSONAL_TOKEN`. Tokens are only ever sent to the | ||
| configured Yuque host (`https://www.yuque.com` by default, or the host you | ||
| set via `--host` / `YUQUE_HOST`) as the `X-Auth-Token` header. | ||
|
Comment on lines
+19
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the configured API endpoint returns a cross-origin 3xx response, Axios follows it by default, while Useful? React with πΒ / π. |
||
| - The CLI never writes your token to disk. Prefer the environment variable | ||
| over `--token` in shared environments β command-line flags can be visible | ||
| to other processes and shell history. | ||
| - Anything that would trick the CLI into sending the token to a non-Yuque | ||
| host, leaking it into output/logs, or executing content returned by the | ||
| API is in scope and we want to hear about it. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a release tag has no matching nonempty
## X.Y.Zsectionβfor example, because the version was bumped but the changelog was missedβthis validation runs only afternpm publishhas permanently published that name/version. The job then exits without creating the GitHub Release, and rerunning stops at the already-published version; extract and validate the notes before publishing, and ideally make already-published reruns idempotent.AGENTS.md reference: AGENTS.md:L89-L89
Useful? React with πΒ / π.