Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ jobs:
environment: npm-publish

steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0

# No `cache: pnpm`. This is the SLSA L3 trusted builder: a pnpm
# store restored from a prior run's cache (this is what
Expand Down Expand Up @@ -107,12 +107,12 @@ jobs:
pnpm sbom --sbom-format spdx --prod > "$SBOM_DIR/sbom.spdx.json"

- name: Generate GitHub artifact attestations for release tarballs
uses: actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6 # v4.2.0
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
with:
subject-path: ${{ runner.temp }}/npm-pack/*.tgz

- name: Generate GitHub artifact attestations for SBOMs
uses: actions/attest@f7c74d28b9d84cb8768d0b8ca14a4bac6ef463e6 # v4.2.0
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
with:
subject-path: ${{ runner.temp }}/sbom/*.json

Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
name: no em dashes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# The job runs `git grep` on the checkout but never pushes or
# talks to the remote, so the `GITHUB_TOKEN` Actions stashes
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
- '>=26.0.0 <27' # latest 26.x

steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

Expand All @@ -117,7 +117,7 @@ jobs:
# 11.13.1 (platform packages ship the binary again); 11.11.0 was
# the last good release before the gap. See pnpm/pnpm#12955
# (release-flow regression from pnpm/pnpm#12949, fixed in 11.13.1).
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
standalone: true

Expand Down Expand Up @@ -344,7 +344,7 @@ jobs:
- '>=26.0.0 <27' # latest 26.x
id: [pnpm-9, pnpm-10, pnpm-11, npm, yarn, yarn-berry, bun]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

Expand Down Expand Up @@ -544,12 +544,12 @@ jobs:
id-token: write
code-quality: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# Same reason as the build job; see comment there.
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
standalone: true

Expand Down Expand Up @@ -681,7 +681,7 @@ jobs:
# extra `if:` gating is needed for those cases.
- name: Upload arkor coverage to GitHub
if: ${{ !cancelled() }}
uses: actions/upload-code-coverage@abb5995db9e0199b0e2bb9dbd136fce4cb1ec4d3 # v1.3.0
uses: actions/upload-code-coverage@d8e329117199404bba6fc81efe8093dc7c015e34 # v1.4.2
with:
file: ./packages/arkor/coverage/cobertura-coverage.xml
language: TypeScript
Expand All @@ -690,7 +690,7 @@ jobs:

- name: Upload create-arkor coverage to GitHub
if: ${{ !cancelled() }}
uses: actions/upload-code-coverage@abb5995db9e0199b0e2bb9dbd136fce4cb1ec4d3 # v1.3.0
uses: actions/upload-code-coverage@d8e329117199404bba6fc81efe8093dc7c015e34 # v1.4.2
with:
file: ./packages/create-arkor/coverage/cobertura-coverage.xml
language: TypeScript
Expand All @@ -699,7 +699,7 @@ jobs:

- name: Upload cli-internal coverage to GitHub
if: ${{ !cancelled() }}
uses: actions/upload-code-coverage@abb5995db9e0199b0e2bb9dbd136fce4cb1ec4d3 # v1.3.0
uses: actions/upload-code-coverage@d8e329117199404bba6fc81efe8093dc7c015e34 # v1.4.2
with:
file: ./packages/cli-internal/coverage/cobertura-coverage.xml
language: TypeScript
Expand All @@ -708,7 +708,7 @@ jobs:

- name: Upload studio-app coverage to GitHub
if: ${{ !cancelled() }}
uses: actions/upload-code-coverage@abb5995db9e0199b0e2bb9dbd136fce4cb1ec4d3 # v1.3.0
uses: actions/upload-code-coverage@d8e329117199404bba6fc81efe8093dc7c015e34 # v1.4.2
with:
file: ./packages/studio-app/coverage/cobertura-coverage.xml
language: TypeScript
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Match every other workflow in the repo: don't leave the GITHUB_TOKEN
# persisted in .git/config (zizmor `artipacked`). CodeQL doesn't push.
Expand All @@ -65,7 +65,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
Expand Down Expand Up @@ -94,6 +94,6 @@ jobs:
exit 1

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
with:
category: "/language:${{matrix.language}}"
6 changes: 3 additions & 3 deletions .github/workflows/release-dry-run.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
exit 1
fi

- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
Expand Down Expand Up @@ -154,12 +154,12 @@ jobs:
needs: preflight
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0

# No `cache: pnpm`. Same rationale as the preflight job above and
# release.yaml's test job: dry-run runs the same pack/publish
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
exit 1
fi

- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
Expand Down Expand Up @@ -157,12 +157,12 @@ jobs:
needs: preflight
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0

# No `cache: pnpm`. Same reasoning as the no-Playwright-cache step
# further down: a pnpm store restored from a prior run's cache
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,5 @@ Don't split these into "docs in a follow-up PR" or "tests later"; land them in t
- **oxlint native bindings + `minimumReleaseAge`**: pnpm 10.x has a known interaction where `minimumReleaseAge` can cause some `optionalDependencies` (notably the host platform's native binding) to be skipped during a fresh install, leaving `oxlint --version` to die with "Cannot find native binding" even though the gate's 24h window has passed. The workaround when bumping oxlint is to update the `oxlint` entry in the `pnpm-workspace.yaml` `catalog:` block and then run `pnpm install --config.minimum-release-age=0`; once the binding entries land in `pnpm-lock.yaml`, regular `pnpm install` (and CI's `--frozen-lockfile`) resolves them normally. Do not paper over this by adding an explicit `@oxlint/binding-<platform>` devDependency: that would pin a platform-specific binding into the root `package.json` and break installs on other machines.
- **oxfmt owns formatting.** Whitespace, wrapping, quote style, and trailing commas are oxfmt's job ([`oxfmt.config.ts`](oxfmt.config.ts), `printWidth: 80`; the filename is the one shape oxfmt auto-discovers for TS configs (alongside `.oxfmtrc.json` / `.oxfmtrc.jsonc`), so the `format` / `format:check` root scripts can just invoke `oxfmt` without `-c`. The file uses `defineConfig` from `oxfmt` like the other `*.config.ts` files in the repo, so typescript-eslint's `allowDefaultProject: ["*.config.ts"]` covers it without a root-config change), gated in CI by `pnpm format:check` (root script, not a Turbo task: one pass over the whole repo takes a few seconds, so it needs no per-package fan-out or caching). ESLint keeps its narrow `@stylistic` rules (`no-trailing-spaces`, `object-curly-spacing`, `keyword-spacing`); oxfmt's defaults already agree with all three, so the redundant overlap is intentional and the two tools never fight over the same byte. Scope is JS/TS/JSON/CSS/HTML only: `ignorePatterns` excludes `**/*.md` and `**/*.mdx` (the bilingual doc pairing is hand-managed), `**/*.yaml`/`**/*.yml` (oxfmt would collapse the column-aligned inline comments in `ci.yaml`'s Node matrix and rewrite the deliberate single-quoted `semver@6.3.1` in `pnpm-workspace.yaml`), and `.claude/**` (local Claude Code state; `.claude/worktrees/` holds other branches' checkouts); `.gitignore` already covers `dist`/`coverage`/`node_modules`/etc., and (since ENG-1121) `.claude/` itself. That gitignore line, not the `ignorePatterns` entry, is what keeps `pnpm format` fast: oxfmt searches subdirectories for nested config files by default, and that walk respects the ignore file (the cwd's `.gitignore`) but not `ignorePatterns`, so before the gitignore line it descended into every checkout under `.claude/worktrees/` (11 of them carrying a full `node_modules`) and that few-second pass turned into a 4+ minute hang. Keep both exclusions: the `ignorePatterns` entry still guards target selection for invocations that don't read the repo-root `.gitignore` (editor/LSP integrations, explicit `--ignore-path`). `sortPackageJson` (oxfmt default `true`) is pinned `false` so package.json key order stays as authored, and `sortImports` is `false` so import ordering stays owned by ESLint's `import-x/order`. Same native-binding caveat as oxlint above: when bumping the catalog `oxfmt` pin, run `pnpm install --config.minimum-release-age=0` once so the platform binding lands in `pnpm-lock.yaml`.
- **Two linters, single root config each.** Every package's `lint` script is `oxlint --deny-warnings . && eslint .`. oxlint reads [`oxlint.config.ts`](oxlint.config.ts) at the repo root (auto-discovered, typed via `defineConfig` from the `oxlint` package); ESLint 10 reads [`eslint.config.ts`](eslint.config.ts) at the repo root (flat config, type-aware via `projectService`). Both walk up from the package directory, so per-package configs would shadow rather than extend; add overrides at the root instead. The oxlint config carries root-level `rules` that mirror the explicit non-type-aware rules in `eslint.config.ts` (`eqeqeq`, `typescript/consistent-type-imports`, `typescript/no-import-type-side-effects`, `promise/always-return` with `ignoreLastCallback`, `import/no-cycle`, `no-unused-vars` with the `^_` ignore patterns, `unicorn/filename-case` with the kebab/camel/pascal carve-out, plus the `unicorn` off-set), and `overrides` for the studio-app SPA (React/jsx-a11y plugins, browser env, `react/rules-of-hooks` + `react/exhaustive-deps`), test/spec files (vitest plugin, with the same relaxations ESLint applies plus `vitest/no-standalone-expect`'s `additionalTestBlockFunctions`), the Playwright fixture path (`eslint/no-empty-pattern` off, because Playwright's `({}, use) => ...` fixture signature requires an empty destructure), and the scripts/bin/CLI paths (`unicorn/no-process-exit` off); the ESLint config mirrors those file-glob overrides and adds its own (test-file relaxations for the `no-unsafe-*` family, `no-non-null-assertion`, `no-base-to-string`, `import-x/order`, etc.). When a rule is opinionated against an established codebase pattern (`unicorn/no-typeof-undefined` vs build-time `define` guards, `unicorn/no-nested-ternary` vs React multi-state render ladders), prefer a scoped override in `eslint.config.ts` with the **why** in a comment over inline `// eslint-disable` at every site.
- **Why both linters now.** oxlint is the fast pre-flight guardrail; strict ESLint (typescript-eslint `strictTypeChecked` + `stylisticTypeChecked` + unicorn / import-x / promise / n / react-hooks / jsx-a11y / vitest) is the type-aware second opinion. oxlint's speed advantage is currently thin (Coding Agent runtime dominates the loop, so the extra ESLint seconds are inside budget) and overlapping rules are intentionally left enabled on the ESLint side so we catch (a) oxlint coverage gaps, (b) any cross-linter disagreement, and (c) regressions if oxlint's transform changes. As of ENG-788 the oxlint config explicitly mirrors every non-type-aware rule that `eslint.config.ts` configures and that oxlint 1.66 implements, so the two are at parity on that set; the overlap is now deliberate parity, not just an unaudited duplicate. What stays ESLint-only is (a) every type-aware rule (oxlint 1.66's `--type-aware` is `tsgo`-backed and still preview, so the `lint` script does not pass it and the type-aware rules, `no-unsafe-*`, `prefer-nullish-coalescing`, `restrict-template-expressions`, `no-unnecessary-condition`, `require-await`, `unbound-method`, stay on ESLint), and (b) a few rules with no oxlint 1.66 equivalent at all: `import-x/order`, the `eslint-plugin-regexp` set, the `@stylistic/*` rules, the `n/*` family (`no-missing-import`, `hashbang`, `no-unsupported-features/node-builtins`), `unicorn/prevent-abbreviations`, and `unicorn/import-style`. The next non-type-aware step is to raise oxlint past `correctness` *selectively*, not via a blanket category flip: `oxlint -D suspicious/pedantic/style` pulls in opinionated rules the repo never adopted (`capitalized-comments`, `sort-keys`, `no-magic-numbers`, `require-unicode-regexp`, `no-ternary`), so categories are not a proxy for the ESLint presets and must be enabled rule-by-rule. The end state is still oxlint-only: once `tsgo` (TypeScript-Go) reaches GA, the type-aware rules fold into oxlint and ESLint gets dropped. Treat this setup as the intermediate state, not the destination.
- **Why both linters now.** oxlint is the fast pre-flight guardrail; strict ESLint (typescript-eslint `strictTypeChecked` + `stylisticTypeChecked` + unicorn / import-x / promise / n / react-hooks / jsx-a11y / vitest) is the type-aware second opinion. oxlint's speed advantage is currently thin (Coding Agent runtime dominates the loop, so the extra ESLint seconds are inside budget) and overlapping rules are intentionally left enabled on the ESLint side so we catch (a) oxlint coverage gaps, (b) any cross-linter disagreement, and (c) regressions if oxlint's transform changes. As of ENG-788 the oxlint config explicitly mirrors every non-type-aware rule that `eslint.config.ts` configures and that oxlint 1.66 implements, so the two are at parity on that set; the overlap is now deliberate parity, not just an unaudited duplicate. (ENG-1157 moved the pin to 1.82 without repeating that audit, so rules oxlint implemented between 1.66 and 1.82 are not yet mirrored. The claims below about what oxlint lacks are likewise as-of-1.66 and are the thing to re-check before treating any of them as still true.) What stays ESLint-only is (a) every type-aware rule (oxlint 1.66's `--type-aware` is `tsgo`-backed and still preview, so the `lint` script does not pass it and the type-aware rules, `no-unsafe-*`, `prefer-nullish-coalescing`, `restrict-template-expressions`, `no-unnecessary-condition`, `require-await`, `unbound-method`, stay on ESLint), and (b) a few rules with no oxlint 1.66 equivalent at all: `import-x/order`, the `eslint-plugin-regexp` set, the `@stylistic/*` rules, the `n/*` family (`no-missing-import`, `hashbang`, `no-unsupported-features/node-builtins`), `unicorn/prevent-abbreviations`, and `unicorn/import-style`. The next non-type-aware step is to raise oxlint past `correctness` *selectively*, not via a blanket category flip: `oxlint -D suspicious/pedantic/style` pulls in opinionated rules the repo never adopted (`capitalized-comments`, `sort-keys`, `no-magic-numbers`, `require-unicode-regexp`, `no-ternary`), so categories are not a proxy for the ESLint presets and must be enabled rule-by-rule. The end state is still oxlint-only: once `tsgo` (TypeScript-Go) reaches GA, the type-aware rules fold into oxlint and ESLint gets dropped. Treat this setup as the intermediate state, not the destination.
- **Auto-fix has unsafe rules.** When running `pnpm exec eslint . --fix`, two rules produced behaviour-breaking rewrites on this codebase and are off as a result: `unicorn/no-typeof-undefined` (rewrote `typeof __SDK_VERSION__ !== "undefined"` guards on tsdown `define` constants to `__SDK_VERSION__ !== undefined`, which throws `ReferenceError` under vitest where the transform never runs) and `@typescript-eslint/no-unnecessary-type-assertion` (stripped real narrowings such as `(await screen.findByRole(...)) as HTMLSelectElement`, `null as unknown` widenings, and vitest mock helper assertions). The comments next to each `off` in `eslint.config.ts` enumerate the observed failure modes; revisit only with a safer fix mode upstream, or treat their findings as manual-review items.
16 changes: 8 additions & 8 deletions packages/arkor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
},
"dependencies": {
"@arkor/cloud-api-client": "^0.0.1-alpha.2",
"@clack/prompts": "^0.8.0",
"@hono/node-server": "^1.14.0",
"commander": "^13.0.0",
"esbuild": "^0.28.0",
"hono": "^4.12.23",
"open": "^11.0.0",
"posthog-node": "^5.30.6",
"zod": "^4.3.6"
"@clack/prompts": "^1.8.0",
Comment thread
sentry[bot] marked this conversation as resolved.
"@hono/node-server": "^2.1.1",
"commander": "^15.0.0",
"esbuild": "^0.28.2",
"hono": "^4.13.7",
"open": "^11.0.2",
"posthog-node": "^5.51.8",
"zod": "^4.6.1"
},
"devDependencies": {
"@arkor/cli-internal": "workspace:*",
Expand Down
3 changes: 0 additions & 3 deletions packages/arkor/src/cli/commands/whoami.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createClient } from "@arkor/cloud-api-client";

import { CloudApiClient } from "../../core/client";
import {
defaultArkorCloudApiUrl,
readCredentials,
Expand Down Expand Up @@ -80,6 +79,4 @@ export async function runWhoami(): Promise<void> {
`Orgs: ${body.orgs.map((o) => String(o.slug ?? o.id)).join(", ")}\n`,
);
}
// Avoid "unused import" noise by referencing CloudApiClient in an assertion.
void CloudApiClient;
}
Loading
Loading