diff --git a/.github/workflows/cli-ci.yml b/.github/workflows/cli-ci.yml index 1cb3bc1..961eb4a 100644 --- a/.github/workflows/cli-ci.yml +++ b/.github/workflows/cli-ci.yml @@ -36,7 +36,7 @@ jobs: lint-and-test: runs-on: ubuntu-latest - # The mock-api lives in the private moropo-com/dcd repo, checked out via an + # The mock-api lives in the private devicecloud-dev/dcd repo, checked out via an # SSH deploy key. GitHub does NOT expose secrets to pull_request workflows # triggered from forks, so that checkout (and the integration tests that need # it) can only run for same-repo events. Fork PRs still run lint/typecheck/build. @@ -57,7 +57,7 @@ jobs: if: env.HAS_PRIVATE_ACCESS == 'true' uses: actions/checkout@v7 with: - repository: moropo-com/dcd + repository: devicecloud-dev/dcd path: dcd ssh-key: ${{ secrets.DCD_SSH_DEPLOY_KEY }} # api/swagger.json is a file, which cone-mode sparse checkout rejects @@ -106,7 +106,7 @@ jobs: - name: Skip integration tests (fork PR — no mock-api access) if: env.HAS_PRIVATE_ACCESS != 'true' - run: echo "::notice::Integration tests skipped — the mock-api (private moropo-com/dcd) is not accessible from fork PRs. Lint, typecheck, and build still ran." + run: echo "::notice::Integration tests skipped — the mock-api (private devicecloud-dev/dcd) is not accessible from fork PRs. Lint, typecheck, and build still ran." - name: Build CLI working-directory: ./cli diff --git a/CLAUDE.md b/CLAUDE.md index ab99a23..985e4a3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -56,7 +56,7 @@ Full guide in `CONTRIBUTING.md`; the operationally important parts (the ones tha - Type → bump (pre-1.0, so `feat` and breaking `!` both bump **minor**): `feat` minor; `fix`/`perf`/`deps`/`revert`/`refactor` patch; `docs`/`chore`/`test`/`ci`/`build`/`style` are hidden and bump nothing. Allowed scopes are free-form. - **Never hand-edit `package.json` version, `CHANGELOG.md`, or the `.release-please-manifest*.json` files** — release-please owns all of them. `src/types/generated/schema.types.ts` is likewise generated (openapi-typescript). - A first-time contributor must sign the CLA (the CLA Assistant bot comments on the first PR); the CLA check must be green to merge. -- **CI (`.github/workflows/cli-ci.yml`) runs on every PR** including forks: gitleaks secret scan, `pnpm lint`, `pnpm typecheck`, `pnpm build`, `pnpm audit --audit-level moderate`. The **integration tests need the private `moropo-com/dcd` mock-api** (cloned via the `DCD_SSH_DEPLOY_KEY` secret), and GitHub withholds secrets from fork and Dependabot PRs — so `pnpm test` is **skipped there** and a maintainer runs the full suite before merge. gitleaks also runs as a pre-commit hook (allowlist in `.gitleaks.toml`); without the binary installed the hook self-skips and CI is the backstop. +- **CI (`.github/workflows/cli-ci.yml`) runs on every PR** including forks: gitleaks secret scan, `pnpm lint`, `pnpm typecheck`, `pnpm build`, `pnpm audit --audit-level moderate`. The **integration tests need the private `devicecloud-dev/dcd` mock-api** (cloned via the `DCD_SSH_DEPLOY_KEY` secret), and GitHub withholds secrets from fork and Dependabot PRs — so `pnpm test` is **skipped there** and a maintainer runs the full suite before merge. gitleaks also runs as a pre-commit hook (allowlist in `.gitleaks.toml`); without the binary installed the hook self-skips and CI is the backstop. ## Releases diff --git a/src/commands/cloud.ts b/src/commands/cloud.ts index 5f8a75c..db1c0fb 100644 --- a/src/commands/cloud.ts +++ b/src/commands/cloud.ts @@ -491,7 +491,7 @@ export const cloudCommand = defineCommand({ ci_provider: ciContext.provider, ci_wrapper_version: ciContext.wrapperVersion, }, - { out, warnOut }, + { out }, ); deviceValidationService.validateAndroidDevice( diff --git a/src/services/notices.service.ts b/src/services/notices.service.ts index ea3c5f5..55296aa 100644 --- a/src/services/notices.service.ts +++ b/src/services/notices.service.ts @@ -1,5 +1,5 @@ import { ui } from '../utils/ui.js'; -import { colors } from '../utils/styling.js'; +import { colors, symbols } from '../utils/styling.js'; import { compareSemver } from './version.service.js'; export type NoticeLevel = 'deprecation' | 'warn' | 'info' | 'marketing'; @@ -88,8 +88,13 @@ export function matchesRules( } export interface RenderNoticesOptions { + /** + * Emit a line of human output. Notices route through the same gated `out` as + * the rest of the CLI (suppressed under `--json`); we don't use the `warn` + * channel because its logger prepends its own `⚠`, which would double up with + * the symbol the `ui.*` helpers already add. + */ out: (message: string) => void; - warnOut: (message: string) => void; } /** Render a single notice with styling appropriate to its level. */ @@ -101,9 +106,13 @@ function renderNotice(notice: Notice, opts: RenderNoticesOptions): void { switch (notice.level) { case 'deprecation': + // Red ⚠ so a deprecation reads as more serious than a plain (yellow) warn. + opts.out(`${colors.error('⚠')} ${colors.bold(notice.title)}`); + opts.out(ui.branch(rows)); + break; case 'warn': - opts.warnOut(ui.warn(colors.bold(notice.title))); - opts.warnOut(ui.branch(rows)); + opts.out(`${symbols.warning} ${colors.bold(notice.title)}`); + opts.out(ui.branch(rows)); break; case 'marketing': opts.out(ui.section(notice.title)); @@ -120,8 +129,8 @@ function renderNotice(notice: Notice, opts: RenderNoticesOptions): void { /** * Filter notices by their local-context `match` gate and render those that pass. * Returns the visible notices so a `--json` caller can include them in its - * payload instead of printing. When `--json` is active, callers pass no-op - * out/warnOut so nothing is printed but the list is still returned. + * payload instead of printing. `opts.out` is the caller's `--json`-gated + * emitter, so under `--json` nothing prints but the list is still returned. */ export function renderNotices( notices: Notice[] | undefined,