Skip to content
Closed
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
61 changes: 61 additions & 0 deletions .cursor/skills/js-packages-release/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
name: js-packages-release
description: Conventions for unified GitHub Packages release-prep tooling in scripts/js-packages-release/ (preflight registry checks, build_packages make chain, manifest pins, GitHub workflow js-packages-release@ tags, TypeScript .mts source, and Vitest). Use when working in that directory, editing src/*.mts files, tests, or .github/workflows/js-packages-release.yaml.
---

# js-packages-release

## Scope

TypeScript CLIs and helpers under **`scripts/js-packages-release/`** for preparing four scoped packages to release together via **GitHub Packages**:

`@opentrons/shared-data`, `@opentrons/step-generation`, `@opentrons/components`, `@opentrons/protocol-visualization`.

**Tags:** `js-packages-release@<semver>` (see workflow and `publish_core.TAG_PREFIX`).

## Tooling

- **Root JS toolchain:** run `make setup-js` at the monorepo root
- **TypeScript / Vitest:** `make clean`, `make build`, `make format`, `make lint`, `make test` from `scripts/js-packages-release/`
- **Node:** `npm` required for `src/publish.mts` (`npm view` against GitHub Packages). **yarn** + root **make** required for `src/build_packages.mts`

## Modules (single responsibility)

| Module | Purpose |
| ------------------------ | --------------------------------------------------------------------------------------- |
| `src/publish_core.mts` | `PACKAGES`, `PACKAGE_REL_DIRS`, semver and tag parsing, `priorPackages()` for pin order |
| `src/publish.mts` | Small Node CLI for preflight and current-version inspection |
| `src/build_packages.mts` | Ordered `make` invocations; optional `--version`; manifest apply |
| `src/manifests.mts` | `applyReleaseVersions(repoRoot, semver)` only |

Do not duplicate version parsing: import **`resolveVersionInput`** (or helpers) from **`src/publish_core.mts`**.

## CLI behavior

- **`src/publish.mts`:** non-interactive only; use `--version` for preflight or `--current` to inspect the current published versions. Full tag ref allowed. Defaults to `https://npm.pkg.github.com` and fails on partial or complete “already published” for the target version.
- **`src/build_packages.mts`:** Omit `--version` for **build only**. `--skip-build` requires `--version`.

## CI

`.github/workflows/js-packages-release.yaml`:

- **PR** (paths): lint + test jobs, no `needs` between them
- **push** `js-packages-release@*`: **publish** job only (preflight with version from `github.ref`), no lint or unit test jobs
- CI uses `./.github/actions/js/setup`, not uv

## Monorepo build order

`src/build_packages.mts` uses a fixed tuple of make commands: root **`build-ts`**, **`shared-data lib-js`**, **`step-generation lib`**, components **`build-ts`** + **`lib`**, protocol-visualization **`build-ts`** + **`lib`**. Keep this in sync with **`PACKAGES`** publish order in `src/publish_core.mts`.

## step-generation

Release-oriented **`package.json`** (`lib` entry points, `files`, `exports`) and **`Makefile`** targets **`build-ts`**, **`lib`**, **`pack`**. `.PHONY` kept inline per target.

## Tests

- Preflight parsing and version validation: **`tests/publish.test.ts`**
- Manifests: **`tests/manifests.test.ts`**

## Roadmap

See **`scripts/js-packages-release/PLAN.md`** for remaining work (`npm publish` wiring to GitHub Packages, removing legacy workflow publish jobs, components-testing).
84 changes: 84 additions & 0 deletions .github/workflows/js-packages-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: js-packages-release

# PR: lint and unit tests only (file-filtered). Tag push: publish only (no lint/tests).
on:
pull_request:
paths:
- '.github/workflows/js-packages-release.yaml'
- 'scripts/js-packages-release/**'
push:
tags:
- 'js-packages-release@*'

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

defaults:
run:
shell: bash

env:
CI: true
OT_NPM_REGISTRY: https://npm.pkg.github.com

permissions:
contents: read
packages: write

jobs:
lint:
name: Lint js-packages-release
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v6

- uses: ./.github/actions/js/setup

- name: Lint
working-directory: scripts/js-packages-release
run: make lint

test:
name: Unit test js-packages-release
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v6

- uses: ./.github/actions/js/setup

- name: Unit tests
working-directory: scripts/js-packages-release
run: make test

publish:
name: Publish preflight (tag only)
runs-on: ubuntu-24.04
# Only tag pushes matching js-packages-release@* (not PRs).
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/js-packages-release@')
steps:
- name: Checkout Repository
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Fix actions checkout odd handling of tags
run: |
git fetch -f origin ${{ github.ref }}:${{ github.ref }}
git checkout ${{ github.ref }}

- uses: ./.github/actions/js/setup

# This job currently runs build + preflight only. Add GitHub Packages auth
# when the script actually performs publish.
- name: build packages
working-directory: scripts/js-packages-release
run: make build-packages VERSION=${{ github.ref }}

- name: publish packages
working-directory: scripts/js-packages-release
run: make publish-ci VERSION=${{ github.ref }}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import type {
InvariantContext,
LabwareEntities,
PipetteEntities,
} from '../../../../step-generation/src/types'
} from '@opentrons/step-generation'
import type { LabwareDefByDefURI } from '../../labware-defs'

vi.mock('../../load-file/migration/utils/getLoadLiquidCommands')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
InvariantContext,
RobotState,
ThermocyclerStateStepArgs,
} from '../../../../step-generation/src/types'
} from '@opentrons/step-generation'
import type { LabwareNamesByModuleId, StepArgsAndErrors } from '../types'

describe('generateSubstepItem', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
saveStepForm,
} from '../thunks'

import type { Timeline } from '@opentrons/step-generation/src/types'
import type { Timeline } from '@opentrons/step-generation'
import type { FormData } from '/protocol-designer/form-types'
import type { StepHierarchy } from '/protocol-designer/steplist/utils/stepHierarchy'
import type {
Expand Down
43 changes: 43 additions & 0 deletions scripts/js-packages-release/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.PHONY: clean
clean:
yarn shx rm -rf dist

.PHONY: build
build:
cd ../.. && yarn tsc -p scripts/js-packages-release/tsconfig.json

.PHONY: format
format:
cd ../.. && yarn prettier --ignore-path .eslintignore --write "scripts/js-packages-release/**/*.@(ts|mts|md|json)"

.PHONY: lint
lint:
cd ../.. && yarn eslint --report-unused-disable-directives-severity error --ignore-pattern "node_modules/" "scripts/js-packages-release/**/*.@(ts|mts)"
cd ../.. && yarn prettier --ignore-path .eslintignore --check "scripts/js-packages-release/**/*.@(ts|mts|md|json)"

.PHONY: test
test:
cd ../.. && yarn vitest --config scripts/js-packages-release/vitest.config.mts run

.PHONY: publish-ci
publish-ci: build
@if [ -z "$(VERSION)" ]; then echo "Set VERSION= to semver or js-packages-release tag ref"; exit 1; fi
node dist/publish.mjs --version "$(VERSION)"

.PHONY: publish-current
publish-current: build
node dist/publish.mjs --current

# With VERSION: build then rewrite package.json. Without VERSION: build only.
.PHONY: build-packages
build-packages: build
@if [ -n "$(VERSION)" ]; then \
node dist/build_packages.mjs --version "$(VERSION)"; \
else \
node dist/build_packages.mjs; \
fi

.PHONY: build-packages-manifests-only
build-packages-manifests-only: build
@if [ -z "$(VERSION)" ]; then echo "Set VERSION= to semver or js-packages-release tag ref"; exit 1; fi
node dist/build_packages.mjs --version "$(VERSION)" --skip-build
111 changes: 111 additions & 0 deletions scripts/js-packages-release/PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
name: GitHub Packages release + component testing
overview: Unified GitHub Packages release prep for four scoped packages via `scripts/js-packages-release/` (TypeScript `.mts` CLIs), tag `js-packages-release@*`, registry preflight, manifest rewrites, ordered builds. Old `shared-data@` / `components@` NPM jobs to be removed from legacy workflows. Extend `components-testing` for step-generation and protocol-visualization.
todos:
- id: scaffold-cli
content: 'scripts/js-packages-release TypeScript project: preflight (registry + semver), manifest rewrite, build orchestration. Remaining: npm publish orchestration in CLI or workflow, optional dry-run.'
status: in_progress
- id: step-gen-shippable
content: 'step-generation publishable (private removed, lib exports/files, Makefile build-ts lib pack).'
status: completed
- id: ci-unify
content: 'Remove NPM publish jobs from shared-data and components workflows; point tag releases at js-packages-release workflow only; adjust notify needs. Partially done: js-packages-release.yaml exists for tag + PR.'
status: in_progress
- id: components-testing-pv
content: 'Extend components-testing to pack/link step-generation and protocol-visualization; paths and SKILL.'
status: pending
- id: tests-docs
content: 'Vitest for version parsing/validation rules; document tag and local workflow. Partially done: tests under scripts/js-packages-release/tests; README and Cursor skill added.'
status: in_progress
---

# Unified GitHub Packages release and components-testing for protocol-visualization

## Implementation status (snapshot)

**Delivered in repo (ongoing work):**

- **`scripts/js-packages-release/`** (not `npm-release`): `src/publish_core.mts`, `src/publish.mts`, `src/build_packages.mts`, `src/manifests.mts`, Makefile, Vitest.
- **Tag:** `js-packages-release@<semver>` for workflow and version parsing.
- **Preflight:** non-interactive TypeScript CLI; rejects invalid semver and wrong tag prefixes; queries GitHub Packages and treats partial and full “already on registry” cases as **errors**.
- **Build chain:** `src/build_packages.mts` runs `make build-ts`, `shared-data lib-js`, `step-generation lib`, components `build-ts` + `lib`, protocol-visualization `build-ts` + `lib`, then optional manifest rewrite.
- **Workflow** [`.github/workflows/js-packages-release.yaml`](../../.github/workflows/js-packages-release.yaml): PR path filters run lint + test; tag push runs **publish** preflight only (no lint or unit tests on the tag).
- **step-generation:** npm-oriented `package.json` and `Makefile` targets (`build-ts`, `lib`, `pack`).

**Not done yet:**

- **`npm publish` to GitHub Packages** for all four packages from CI or from this CLI.
- **Removing** `publish-to-npm` / `publish-components` (and related notify wiring) from legacy workflows.
- **components-testing** parity for four packages.
- Optional **dry-run** and any “resume partial publish” flag (current policy is fail on partial).

---

## Current behavior (pain points), historical

- Versioning and NPM manifest edits lived in CI in [components-test-build-deploy.yaml](../../.github/workflows/components-test-build-deploy.yaml) (`publish-components` on `components@*` tags) and [shared-data-test-lint-deploy.yaml](../../.github/workflows/shared-data-test-lint-deploy.yaml) (`publish-to-npm` gated by `publish-switch` for `shared-data@*` / `components@*` tags).
- NPM publishing was **split across two workflows** and could **race** (ordering not guaranteed).

## Target behavior

- **One TypeScript-oriented toolkit** for local and CI: version resolution, **GitHub Packages registry checks**, manifest rewrites, ordered builds, then **`npm publish`** (publish step still to be wired).
- **Four JS packages**, same semver per release: `@opentrons/shared-data`, `@opentrons/step-generation`, `@opentrons/components`, `@opentrons/protocol-visualization`.
- **GitHub Packages publishing** should eventually **not** run inside shared-data or components test-and-deploy workflows; use the dedicated **`js-packages-release@*`** workflow (and local scripts) as the single entry point.

### Dependency graph

```mermaid
flowchart TD
sd[@opentrons/shared-data]
sg[@opentrons/step-generation]
co[@opentrons/components]
pv[@opentrons/protocol-visualization]
sd --> sg
sd --> co
sg --> co
sd --> pv
sg --> pv
co --> pv
```

**Publish order:** `shared-data` → `step-generation` → `components` → `protocol-visualization`.

---

## Sections 1–7 (original plan detail)

The sections below are the **original** design notes. Treat the **Implementation status** block at the top as the source of truth for what is merged today. Path names in older bullets may say `scripts/npm-release/`; the actual directory is **`scripts/js-packages-release/`**.

### 1. CLI package (TypeScript + Node ESM)

Use `.mts` source under `src/`, compile with `tsc`, and run tests with Vitest.

Registry checks use `npm view` against GitHub Packages. Manifest rewrite keeps **step-generation** as a dependency of **components** (no deletion of that dependency).

### 2. CI: one workflow + tag

**Still to do:** remove NPM publish from legacy workflows; rely on `js-packages-release.yaml` for the four-package line.

**Done:** dedicated workflow on `js-packages-release@*`, PR checks for this script tree.

### 3. `step-generation`

**Done:** publish-oriented `package.json`, `lib` build via `tsc --build`, Makefile **pack** path.

### 4. `protocol-visualization`

In the build train after components; pins come from `applyReleaseVersions()` and `PACKAGES` order in `src/publish_core.mts`.

### 5. `components-testing`

**Pending:** pack/link step-generation and protocol-visualization; workflow paths; skill update there.

### 6. Local developer workflow

Use **`make publish-ci`** with `VERSION=` or **`make publish-current`**; use **`make build-packages`** with or without `VERSION=` from `scripts/js-packages-release`.

### 7. Testing and verification

**Ongoing:** keep tests focused on parsing and validation helpers; run **`make -C components-testing test`** after components-testing Makefile changes.

When legacy NPM jobs are removed, **`components@`** / **`shared-data@`** tag pushes should **not** drive the four-package NPM release (migration to **`js-packages-release@`**).
Loading
Loading