@quiltdata/benchling-webhook 0.21.2 → 0.21.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,7 +45,7 @@ To put each scientist's notebook packages in the same namespace as their raw-dat
45
45
 
46
46
  #### Package Metadata
47
47
 
48
- The package metadata is the package's `entry.json`. Besides the entry's IDs, name, creator, authors, and timestamps, it includes the entry's schema `fields` and `customFields`. Benchling keys these by display name, so the webhook re-keys them in snake_case: "Experiment Type" becomes `experiment_type` and "ELN-ID #" becomes `eln_id`. Each field keeps its display name as `name`; its other values are exactly what Benchling returns. Both keys are always present, as `{}` when the entry has none. The package's `entry_data.json` keeps the raw entry.
48
+ The package metadata is the package's `entry.json`. Besides the entry's IDs, name, creator, authors, and timestamps, it includes the entry's schema `fields` and `customFields`. Benchling keys these by display name, so the webhook re-keys them in snake_case: "Experiment Type" becomes `experiment_type` and "ELN-ID #" becomes `eln_id`. Each key maps to the field's `value` as Benchling returns it. Both keys are always present, as `{}` when the entry has none. The package's `entry_data.json` keeps the raw entry, with each field's display name, `displayValue`, `type`, and so on.
49
49
 
50
50
  ```json
51
51
  {
@@ -53,11 +53,11 @@ The package metadata is the package's `entry.json`. Besides the entry's IDs, nam
53
53
  "display_id": "EXP26000025",
54
54
  "name": "HPLC run 3",
55
55
  "fields": {
56
- "project": {"name": "Project", "value": "VIR-0001", "displayValue": "VIR-0001", "type": "text", "isMulti": false, "textValue": "VIR-0001"},
57
- "experiment_type": {"name": "Experiment Type", "value": "Assay", "displayValue": "Assay", "type": "dropdown", "isMulti": false, "textValue": "Assay"}
56
+ "project": "VIR-0001",
57
+ "experiment_type": "Assay"
58
58
  },
59
59
  "customFields": {
60
- "instrument": {"name": "Instrument", "value": "HPLC-02"}
60
+ "instrument": "HPLC-02"
61
61
  }
62
62
  }
63
63
  ```
@@ -73,7 +73,7 @@ A bucket's [Quilt workflow](https://docs.quilt.bio/advanced-features/workflows)
73
73
  "fields": {
74
74
  "type": "object",
75
75
  "properties": {
76
- "project": {"properties": {"value": {"type": "string", "pattern": "^VIR-"}}}
76
+ "project": {"type": "string", "pattern": "^VIR-"}
77
77
  }
78
78
  }
79
79
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quiltdata/benchling-webhook",
3
- "version": "0.21.2",
3
+ "version": "0.21.3",
4
4
  "description": "AWS CDK deployment for Benchling webhook processing using Fargate - Deploy directly with npx",
5
5
  "main": "dist/lib/index.js",
6
6
  "types": "dist/lib/index.d.ts",
@@ -54,10 +54,13 @@
54
54
  "test:prod": "make -C docker test-deployed-prod PROFILE=default",
55
55
  "test:python": "make -C docker test-unit",
56
56
  "test:ts": "cross-env NODE_ENV=test NODE_OPTIONS='--experimental-vm-modules' jest --maxWorkers=50%",
57
+ "release:context": "ts-node scripts/version.ts release-context",
58
+ "release:publish": "ts-node scripts/npm-publish.ts",
57
59
  "version": "ts-node scripts/version.ts",
58
60
  "version:dev": "ts-node scripts/get-dev-version.ts",
59
61
  "version:verify": "ts-node scripts/version.ts verify-clean-git",
60
62
  "version:tag": "npm run version:verify && npm test && ts-node scripts/version.ts tag",
63
+ "version:tag:auto": "ts-node scripts/version.ts auto-tag",
61
64
  "version:tag:dev": "npm run version:verify && npm test && ts-node scripts/version.ts tag dev",
62
65
  "test:integration": "cross-env NODE_ENV=test NODE_OPTIONS='--experimental-vm-modules' jest --config jest.integration.config.js --testMatch='**/test/integration/**/*.test.ts' --runInBand",
63
66
  "test:integration:verbose": "npm run test:integration -- --verbose"
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Retry-safe npm publication with monotonic shared dist-tags.
4
+ *
5
+ * npm trusted publishing (OIDC) authorizes only `npm publish`; `npm dist-tag`
6
+ * needs a registry token. Promotion therefore happens atomically inside
7
+ * `npm publish --tag <channel>`, and stale candidates are parked under a
8
+ * per-version tag so a shared channel never moves backward.
9
+ */
10
+ export interface NpmRegistry {
11
+ versions(packageName: string): string[];
12
+ distTags(packageName: string): Record<string, string>;
13
+ publish(tag: string): void;
14
+ }
15
+ export interface PublishResult {
16
+ immutableCreated: boolean;
17
+ channel: "latest" | "dev";
18
+ promotion: "initialized" | "promoted" | "current" | "stale";
19
+ }
20
+ export interface NpmCommandResult {
21
+ status: number;
22
+ stdout: string;
23
+ stderr: string;
24
+ }
25
+ export type NpmCommandRunner = (args: readonly string[], inherit?: boolean) => NpmCommandResult;
26
+ export declare const defaultNpmRunner: NpmCommandRunner;
27
+ export declare class CliNpmRegistry implements NpmRegistry {
28
+ private readonly runner;
29
+ constructor(runner?: NpmCommandRunner);
30
+ versions(packageName: string): string[];
31
+ distTags(packageName: string): Record<string, string>;
32
+ publish(tag: string): void;
33
+ }
34
+ export declare function parkingDistTag(version: string): string;
35
+ export declare function publishRelease(registry: NpmRegistry, packageName: string, version: string, packageVersion: string): PublishResult;
36
+ export declare function main(args?: string[]): number;
37
+ //# sourceMappingURL=npm-publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-publish.d.ts","sourceRoot":"","sources":["../../scripts/npm-publish.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AAOH,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC1B,SAAS,EAAE,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;CAC/D;AAOD,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,gBAAgB,CAAC;AAOhG,eAAO,MAAM,gBAAgB,EAAE,gBAU9B,CAAC;AAUF,qBAAa,cAAe,YAAW,WAAW;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,GAAE,gBAAmC;IAExE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE;IAcvC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkBrD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAOpC;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAaD,wBAAgB,cAAc,CAC1B,QAAQ,EAAE,WAAW,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,GACvB,aAAa,CAgCf;AAWD,wBAAgB,IAAI,CAAC,IAAI,WAAwB,GAAG,MAAM,CAWzD"}
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Retry-safe npm publication with monotonic shared dist-tags.
5
+ *
6
+ * npm trusted publishing (OIDC) authorizes only `npm publish`; `npm dist-tag`
7
+ * needs a registry token. Promotion therefore happens atomically inside
8
+ * `npm publish --tag <channel>`, and stale candidates are parked under a
9
+ * per-version tag so a shared channel never moves backward.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.CliNpmRegistry = exports.defaultNpmRunner = void 0;
46
+ exports.parkingDistTag = parkingDistTag;
47
+ exports.publishRelease = publishRelease;
48
+ exports.main = main;
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const child_process_1 = require("child_process");
52
+ const version_1 = require("./version");
53
+ function npmError(args, result) {
54
+ const detail = result.stderr.trim() || result.stdout.trim() || `exit status ${result.status}`;
55
+ return new Error(`npm ${args.join(" ")} failed: ${detail}`);
56
+ }
57
+ const defaultNpmRunner = (args, inherit = false) => {
58
+ const result = (0, child_process_1.spawnSync)("npm", [...args], {
59
+ encoding: "utf8",
60
+ stdio: inherit ? "inherit" : "pipe",
61
+ });
62
+ return {
63
+ status: result.status ?? 127,
64
+ stdout: result.stdout?.toString() ?? "",
65
+ stderr: [result.stderr?.toString(), result.error?.message].filter(Boolean).join("\n"),
66
+ };
67
+ };
68
+ exports.defaultNpmRunner = defaultNpmRunner;
69
+ function parseJson(value, label) {
70
+ try {
71
+ return JSON.parse(value);
72
+ }
73
+ catch (error) {
74
+ throw new Error(`Malformed npm ${label} response: ${error instanceof Error ? error.message : String(error)}`);
75
+ }
76
+ }
77
+ class CliNpmRegistry {
78
+ constructor(runner = exports.defaultNpmRunner) {
79
+ this.runner = runner;
80
+ }
81
+ versions(packageName) {
82
+ const args = ["view", packageName, "versions", "--json"];
83
+ const result = this.runner(args);
84
+ if (result.status !== 0) {
85
+ throw npmError(args, result);
86
+ }
87
+ const parsed = parseJson(result.stdout, "versions");
88
+ const versions = typeof parsed === "string" ? [parsed] : parsed;
89
+ if (!Array.isArray(versions) || !versions.every((version) => typeof version === "string")) {
90
+ throw new Error("Malformed npm versions response: expected a string array");
91
+ }
92
+ return versions;
93
+ }
94
+ distTags(packageName) {
95
+ const args = ["view", packageName, "dist-tags", "--json"];
96
+ const result = this.runner(args);
97
+ if (result.status !== 0) {
98
+ throw npmError(args, result);
99
+ }
100
+ const parsed = parseJson(result.stdout, "dist-tags");
101
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
102
+ throw new Error("Malformed npm dist-tags response: expected an object");
103
+ }
104
+ for (const value of Object.values(parsed)) {
105
+ if (typeof value !== "string") {
106
+ throw new Error("Malformed npm dist-tags response: expected string versions");
107
+ }
108
+ }
109
+ return parsed;
110
+ }
111
+ publish(tag) {
112
+ const args = ["publish", "--provenance", "--access", "public", "--tag", tag];
113
+ const result = this.runner(args, true);
114
+ if (result.status !== 0) {
115
+ throw npmError(args, result);
116
+ }
117
+ }
118
+ }
119
+ exports.CliNpmRegistry = CliNpmRegistry;
120
+ function parkingDistTag(version) {
121
+ return `release-${version.replace(/[^0-9A-Za-z-]/g, "-")}`;
122
+ }
123
+ function promotionDecision(candidate, current) {
124
+ if (!current) {
125
+ return "initialized";
126
+ }
127
+ const comparison = (0, version_1.compareReleaseVersions)(candidate, current);
128
+ if (comparison > 0) {
129
+ return "promoted";
130
+ }
131
+ return comparison === 0 ? "current" : "stale";
132
+ }
133
+ function publishRelease(registry, packageName, version, packageVersion) {
134
+ const release = (0, version_1.parseReleaseVersion)(version);
135
+ if (packageVersion !== version) {
136
+ throw new Error(`package.json version ${packageVersion} does not match release ${version}`);
137
+ }
138
+ const channel = release.prerelease ? "dev" : "latest";
139
+ const immutableCreated = !registry.versions(packageName).includes(version);
140
+ const current = registry.distTags(packageName)[channel];
141
+ if (current) {
142
+ const currentRelease = (0, version_1.parseReleaseVersion)(current);
143
+ if (!release.prerelease && currentRelease.prerelease) {
144
+ throw new Error(`npm latest must point to a plain semantic version, found ${current}`);
145
+ }
146
+ }
147
+ const promotion = promotionDecision(version, current);
148
+ const advancesChannel = promotion === "initialized" || promotion === "promoted";
149
+ if (immutableCreated) {
150
+ registry.publish(advancesChannel ? channel : parkingDistTag(version));
151
+ }
152
+ else if (advancesChannel) {
153
+ throw new Error(`${packageName}@${version} is already published but npm ${channel} is ${current ?? "unset"}; ` +
154
+ `trusted publishing cannot move dist-tags, so run: npm dist-tag add ${packageName}@${version} ${channel}`);
155
+ }
156
+ return {
157
+ immutableCreated,
158
+ channel,
159
+ promotion,
160
+ };
161
+ }
162
+ function readPackageJson() {
163
+ const packagePath = path.join(__dirname, "..", "package.json");
164
+ const parsed = JSON.parse(fs.readFileSync(packagePath, "utf8"));
165
+ if (typeof parsed.name !== "string" || typeof parsed.version !== "string") {
166
+ throw new Error("package.json must contain string name and version fields");
167
+ }
168
+ return parsed;
169
+ }
170
+ function main(args = process.argv.slice(2)) {
171
+ try {
172
+ const pkg = readPackageJson();
173
+ const version = args[0] ?? process.env.RELEASE_VERSION ?? pkg.version;
174
+ const result = publishRelease(new CliNpmRegistry(), pkg.name, version, pkg.version);
175
+ console.log(`npm ${result.channel}: immutable=${result.immutableCreated}, promotion=${result.promotion}`);
176
+ return 0;
177
+ }
178
+ catch (error) {
179
+ console.error(`❌ ${error instanceof Error ? error.message : String(error)}`);
180
+ return 1;
181
+ }
182
+ }
183
+ if (require.main === module) {
184
+ process.exitCode = main();
185
+ }
186
+ //# sourceMappingURL=npm-publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-publish.js","sourceRoot":"","sources":["../../scripts/npm-publish.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,102 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Version management script - bumps version numbers and creates release tags
3
+ * Version management and release-tag tooling.
4
4
  *
5
- * Usage:
6
- * node bin/version.ts # Show all three version files
7
- * node bin/version.ts patch # 0.4.7 -> 0.4.8
8
- * node bin/version.ts minor # 0.4.7 -> 0.5.0
9
- * node bin/version.ts major # 0.4.7 -> 1.0.0
10
- * node bin/version.ts sync # Force TOML and YAML to match JSON version
11
- * node bin/version.ts tag # Create and push production release tag
12
- * node bin/version.ts tag dev # Create and push dev release tag
5
+ * Version bumps remain explicit commands. Release commands share tag construction,
6
+ * local/remote target verification, and annotated-tag creation semantics.
13
7
  */
8
+ interface VersionParts {
9
+ major: number;
10
+ minor: number;
11
+ patch: number;
12
+ }
13
+ export interface ReleaseVersion extends VersionParts {
14
+ raw: string;
15
+ prerelease: boolean;
16
+ timestamp?: string;
17
+ }
18
+ export interface CommandResult {
19
+ status: number;
20
+ stdout: string;
21
+ stderr: string;
22
+ }
23
+ export interface CommandOptions {
24
+ cwd: string;
25
+ inherit?: boolean;
26
+ }
27
+ export type CommandRunner = (command: string, args: readonly string[], options: CommandOptions) => CommandResult;
28
+ export type AutoTagOutcome = "no-version-change" | "non-production-version" | "verified-existing-tag" | "verified-recovered-tag" | "created" | "verified-race";
29
+ export interface AutoTagResult {
30
+ outcome: AutoTagOutcome;
31
+ releaseRequired: boolean;
32
+ verified: boolean;
33
+ tag: string;
34
+ targetSha: string;
35
+ }
36
+ export interface ReleaseContext {
37
+ verified: boolean;
38
+ tag: string;
39
+ version: string;
40
+ baseVersion: string;
41
+ targetSha: string;
42
+ isPrerelease: boolean;
43
+ }
44
+ export interface TagAnnotation {
45
+ message: string;
46
+ taggerName: string;
47
+ taggerEmail: string;
48
+ }
49
+ export interface RemoteReleaseTag {
50
+ targetSha: string;
51
+ annotation: TagAnnotation | null;
52
+ }
53
+ export interface ReleaseRepository {
54
+ resolveCommit(ref: string): string;
55
+ commitExists(ref: string): boolean;
56
+ readFileAtCommit(commit: string, file: string): string;
57
+ localTagTarget(tag: string): string | null;
58
+ remoteTag(tag: string): RemoteReleaseTag | null;
59
+ createAnnotatedTag(tag: string, message: string, targetSha: string): void;
60
+ pushTag(tag: string): boolean;
61
+ isClean(): boolean;
62
+ }
63
+ export interface AutomaticReleaseOptions {
64
+ repository: ReleaseRepository;
65
+ currentVersion: string;
66
+ beforeSha?: string;
67
+ githubSha: string;
68
+ runProductionGate: () => void;
69
+ }
70
+ export declare const AUTOMATIC_RELEASE_TAGGER_NAME = "github-actions[bot]";
71
+ export declare const AUTOMATIC_RELEASE_TAGGER_EMAIL = "41898282+github-actions[bot]@users.noreply.github.com";
72
+ export declare const defaultCommandRunner: CommandRunner;
73
+ export declare function isSemanticVersion(version: string): boolean;
74
+ export declare function parseReleaseVersion(version: string): ReleaseVersion;
75
+ export declare function compareReleaseVersions(left: string, right: string): number;
76
+ export declare function productionTag(version: string): string;
77
+ export declare function devTag(version: string, now?: Date): string;
78
+ export declare function annotatedTagMessage(tag: string): string;
79
+ export declare function parseTag(tag: string): Omit<ReleaseContext, "verified" | "targetSha">;
80
+ export declare class GitReleaseRepository implements ReleaseRepository {
81
+ private readonly cwd;
82
+ private readonly runner;
83
+ constructor(cwd: string, runner?: CommandRunner);
84
+ private git;
85
+ resolveCommit(ref: string): string;
86
+ commitExists(ref: string): boolean;
87
+ readFileAtCommit(commit: string, file: string): string;
88
+ localTagTarget(tag: string): string | null;
89
+ private fetchedTagAnnotation;
90
+ remoteTag(tag: string): RemoteReleaseTag | null;
91
+ remoteTagTarget(tag: string): string | null;
92
+ createAnnotatedTag(tag: string, message: string, targetSha: string): void;
93
+ pushTag(tag: string): boolean;
94
+ isClean(): boolean;
95
+ }
96
+ export declare function isAutomaticReleaseTag(tag: string, remote: RemoteReleaseTag): boolean;
97
+ export declare function runAutomaticRelease(options: AutomaticReleaseOptions): AutoTagResult;
98
+ export declare function validateReleaseContext(repository: ReleaseRepository, tag: string, packageVersion: string, githubSha: string): ReleaseContext;
99
+ export declare function runProductionGate(repository: ReleaseRepository, cwd?: string, runner?: CommandRunner): void;
100
+ export declare function main(args?: string[]): number;
14
101
  export {};
15
102
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../scripts/version.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;GAWG"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../scripts/version.ts"],"names":[],"mappings":"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"}