diff --git a/.agents/skills/_shared/shopify-cli-ci-repo-contracts.md b/.agents/skills/_shared/shopify-cli-ci-repo-contracts.md index 9dae6696d24..aee77847a8d 100644 --- a/.agents/skills/_shared/shopify-cli-ci-repo-contracts.md +++ b/.agents/skills/_shared/shopify-cli-ci-repo-contracts.md @@ -25,6 +25,12 @@ For normal PR CI work, start with `.github/workflows/tests-pr.yml`. - Generated outputs are often part of the required change set when a workflow step verifies cleanliness after regeneration. - `dev.yml` is a useful local workflow entrypoint, but workflow YAML is the source of truth for what CI actually enforces. +## Local pre-submit tooling + +- `pnpm pre-ci` runs the local subset of PR gates at full CI parity (type-check, lint, build, knip, codegen freshness, unit tests). `pnpm pre-ci:affected` runs the diff-scoped fast variant (nx/vitest affected; skips the codegen freshness checks unless the diff touches commands, flags, or GraphQL). Default to affected; reach for full `pre-ci` before a high-risk push. +- Codegen freshness is single-sourced in `package.json`: `pnpm codegen` regenerates all generated files; `pnpm codegen:check:graphql` / `:oclif` regenerate and assert a clean tree. The workflow's `graphql-schema` and `oclif-checks` jobs call these scripts, so local and CI cannot drift. +- `bin/ci-gates.js` is the source of truth mapping each `tests-pr.yml` job to a `pre-ci` command or a `ci-only` reason. `pnpm check-ci-gates` (CI job `CI gate manifest`) fails if a workflow job is unclassified or if the Node/pnpm versions in `dev.yml` and `tests-pr.yml` disagree. + ## Gotchas - Do not guess from a check name alone when the workflow or job definition is available. diff --git a/.agents/skills/cli-pre-submit-ci/SKILL.md b/.agents/skills/cli-pre-submit-ci/SKILL.md index 98870d67742..5f09abfd00d 100644 --- a/.agents/skills/cli-pre-submit-ci/SKILL.md +++ b/.agents/skills/cli-pre-submit-ci/SKILL.md @@ -35,14 +35,16 @@ If the diff clearly maps to a narrow family, keep the investigation narrow. |---|---| | docs/config/wiring only, with no obvious workflow-enforced generator family | **stop there unless contradicted**: run lightweight sanity checks only (`git diff --check`, validate changed symlink targets, validate local markdown links if relevant); do not full-read large workflow/script files | | user is at PR time (`submit`, `open`, `update`, `restack`) | advisory mode: suggest minimal checks, staging needs, and likely CI risk; ask before running anything substantial | -| user asks what to run before push | recommend the minimal high-signal checks implied by the workflow | +| user asks what to run before push | `pnpm pre-ci:affected` for a diff-scoped fast check, or the minimal high-signal checks implied by the workflow; `pnpm pre-ci` for full parity before a high-risk push | | user asks what to commit or stage | reproduce the relevant generator/check path, then inspect git status and diffs | | user explicitly asks to run checks | run the minimal derived set, not the whole world | ### 2) Resolve the contract for the relevant family Only do this if the diff class suggests a real CI-family mapping, or if the user asks for broader confidence. -Read sources in this order: +The gate list is already resolved in [`bin/ci-gates.js`](../../../bin/ci-gates.js) — each `tests-pr.yml` job mapped to its local command (full and affected) or a ci-only reason. Read it first; `pnpm pre-ci` / `pnpm pre-ci:affected` run those gates, so most pre-submit work needs no per-diff YAML archaeology. + +When the manifest is not enough, resolve from the contract files in this order: 1. relevant `.github/workflows/*.yml` 2. `dev.yml` @@ -57,11 +59,11 @@ Read only the files and script sections needed for the diff class you identified | Change shape | Inspect first | Likely response | |---|---|---| -| Command/flag/help surface | docs/manifests/readme freshness jobs | derive the generator path from workflow → scripts | -| GraphQL queries or schemas | schema/codegen freshness jobs | derive the schema fetch + codegen path | -| TypeScript implementation or exports | type-check, lint, knip, bundle jobs | focused tests plus required static checks | -| Test helpers, async UI, network/auth/callback logic | unit-test jobs and nearby tests | focused tests plus a CI-risk warning | -| Workflow files or CI plumbing | affected workflow definitions | validate the changed contract directly | +| Command/flag/help surface | OCLIF manifests/readme/docs freshness gate | run `pnpm codegen`; stage the regenerated manifests, README, and docs | +| GraphQL queries or schemas | graphql-codegen freshness gate | run `pnpm codegen` (or `pnpm codegen:check:graphql`); stage generated types | +| TypeScript implementation or exports | type-check, lint, knip, bundle jobs | `pnpm pre-ci:affected` (type-check, lint, knip, affected tests) | +| Test helpers, async UI, network/auth/callback logic | unit-test jobs and nearby tests | focused affected tests plus a CI-risk warning | +| Workflow files or CI plumbing | affected workflow definitions | validate the changed contract; `pnpm check-ci-gates` | ### 4) Finish with staging guidance After any generator, freshness check, or lightweight sanity pass: @@ -75,17 +77,16 @@ After any generator, freshness check, or lightweight sanity pass: ## Gotchas -- At PR time, do **not** automatically run the full workflow-equivalent validation set unless the user asks. +- At PR time, do **not** automatically run the full workflow-equivalent validation set unless the user asks. `pnpm pre-ci` is that full set; `pnpm pre-ci:affected` is the diff-scoped fast check (and skips the codegen freshness checks unless the diff touches commands, flags, or GraphQL). Default to affected or the minimal derived checks. - `dev.yml` is a useful local entrypoint, but workflow YAML is the source of truth for what CI enforces. - Broad generated diffs are not automatically wrong; distinguish required churn from suspicious churn. - Do not stop at “run this command.” Explain what likely needs staging. -- If the diff is docs/config/wiring only, do not escalate to heavyweight checks unless the workflow or the user gives a reason. -- For docs/config/wiring-only diffs, avoid full reads of large workflow or script files unless the diff clearly maps to an enforced CI family. +- For docs/config/wiring-only diffs, do not escalate to heavyweight checks or full reads of large workflow/script files unless the diff clearly maps to an enforced CI family. - If the change touches async/timing-heavy tests, local servers, callback flows, socket teardown, or workflow topology, warn that CI-only failures may still appear even after local checks pass. ## Examples -- "What should I run before I push this PR?" → derive the minimal checks from workflow → `dev.yml` → `package.json`, then recommend focused tests plus any required generators. +- "What should I run before I push this PR?" → `pnpm pre-ci:affected` for a fast diff-scoped check; if the diff touches commands, flags, or GraphQL, also run `pnpm codegen` and stage the output; `pnpm pre-ci` before a high-risk push. - "Submit this PR." → treat it as a pre-submit moment, suggest the minimal recommended checks and likely staging requirements first, and ask before running them. -- "Which generated files do I need to commit?" → reproduce the relevant generation path, inspect git status, and separate required generated output from optional churn. -- "I changed a command flag; what repo checks matter?" → start from the freshness job that enforces command-surface updates rather than from memory. +- "Which generated files do I need to commit?" → run the relevant `pnpm codegen` path, inspect git status, and separate required generated output from optional churn. +- "I changed a command flag; what repo checks matter?" → the OCLIF manifests/readme/docs freshness gate; run `pnpm codegen` and commit the regenerated files. diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md deleted file mode 100644 index fe7f29ba506..00000000000 --- a/.claude/CLAUDE.md +++ /dev/null @@ -1,2 +0,0 @@ -See @../.cursor/rules/base.mdc for information on your desired behavior. -See @../.cursor/rules/docs.mdc for details on Shopify CLI architecture and conventions. diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 120000 index 00000000000..be77ac83a18 --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1 @@ +../AGENTS.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..d79d54bbe4d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,21 @@ +See @.cursor/rules/base.mdc for your desired behavior. +See @.cursor/rules/docs.mdc for Shopify CLI architecture and conventions. + +# Working in Shopify CLI + +Entry point for contributors and coding agents. It summarizes the pre-submit commands below and links to the canonical material: docs under [`docs/`](./docs/README.md), agent skills under [`.agents/skills/`](./.agents/skills). + +## Before you push + +- Run `pnpm pre-ci:affected` for a fast, diff-scoped pre-push check, or `pnpm pre-ci` for full CI parity before a high-risk push. The [`cli-pre-submit-ci`](./.agents/skills/cli-pre-submit-ci/SKILL.md) skill covers deriving the minimal set and what to stage. +- After changing commands, flags, or GraphQL queries, run `pnpm codegen` and commit the regenerated files. +- `pnpm check-ci-gates` keeps the local gate list ([`bin/ci-gates.js`](./bin/ci-gates.js)) and pinned tool versions in sync with the workflow. + +## Key docs + +- [Get started / setup and scripts](./docs/cli/get-started.md) +- [Local development against services](./docs/cli/local-development.md) +- [ESLint rules](./docs/cli/eslint-rules.md) +- [Testing strategy](./docs/cli/testing-strategy.md) +- [Cross-OS compatibility](./docs/cli/cross-os-compatibility.md) +- [Changesets and versioning](./CONTRIBUTING.md) diff --git a/docs/README.md b/docs/README.md index 5e6e3c44c9b..4321490af04 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,6 +11,7 @@ The Shopify CLI is a tool for merchants, partners, and developers to interact wi The list below contains valuable resources for people interested in contributing to the CLI project in this repository. * [Get started](./cli/get-started.md) +* [Local development against services](./cli/local-development.md) * [Architecture](./cli/architecture.md) * [Conventions](./cli/conventions.md) * [Performance](./cli/performance.md) diff --git a/docs/cli/get-started.md b/docs/cli/get-started.md index 259eabda141..ddbd4b3f571 100644 --- a/docs/cli/get-started.md +++ b/docs/cli/get-started.md @@ -72,5 +72,11 @@ Besides the scripts for building and running the CLIs, there are others that mig - `pnpm lint:fix`: Runs ESLint and Prettier checks for all the packages and fixes the fixable issues. - `pnpm type-check`: Type-checks all the packagesusing the Typescript `tsc` tool. - `pnpm clean`: Removes the `dist` directory from all the packages. +- `pnpm pre-ci`: Runs the local subset of PR CI gates (type-check, lint, build, knip, codegen freshness, unit tests) at full parity with CI. Slower, for a high-risk push. +- `pnpm pre-ci:affected`: The diff-scoped fast variant for routine PRs (nx/vitest affected; skips codegen freshness checks unless the diff touches commands, flags, or GraphQL). +- `pnpm codegen`: Regenerates all generated files (GraphQL types, OCLIF manifests, README, docs). Run after changing commands, flags, or queries, and commit the result. +- `pnpm check-ci-gates`: Verifies the local CI-gate manifest stays in sync with the GitHub Actions workflow. + +Prefer these scripts over invoking `eslint`/`prettier`/`tsc` directly: CI runs them through Nx over package sources, not over root `bin/` scripts. All the packages in the repository contain the above scripts so they can be executed too for an individual package. diff --git a/docs/cli/local-development.md b/docs/cli/local-development.md new file mode 100644 index 00000000000..586f581fcbc --- /dev/null +++ b/docs/cli/local-development.md @@ -0,0 +1,18 @@ +# Local development against services + +Most contributions run against production Shopify services. When developing against a local services stack, the CLI changes behavior based on the service environment. + +## Service environment + +- `SHOPIFY_SERVICE_ENV=local` +- `SHOPIFY_CLI_NEVER_USE_PARTNERS_API=1` + +In local mode the CLI maps a store's `{store}.my.shop.dev` host to `admin.shop.dev/store/{store}` — see `packages/cli-kit/src/public/node/context/fqdn.ts`. + +## Running the CLI + +See [Get started](./get-started.md) for building and running the CLI (`pnpm shopify `) and the available scripts. + +## Before opening a PR + +Derive the minimal pre-submit checks for your diff (see the `cli-pre-submit-ci` agent skill), or run `pnpm pre-ci` for full local CI parity. After changing commands, flags, or GraphQL queries, run `pnpm codegen` and commit the regenerated files.