@dbx-tools/projen 0.8.1 → 0.9.1
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 +9 -5
- package/index.ts +1 -1
- package/package.json +1 -1
- package/src/codegen.ts +18 -6
- package/src/release-catalog.ts +14 -0
- package/src/release.ts +51 -17
- package/tasks/release-please.ts +0 -1
- package/tasks/release-request.ts +12 -12
package/README.md
CHANGED
|
@@ -454,16 +454,20 @@ a new package is covered without a re-synth. Work from the root:
|
|
|
454
454
|
before notes, AI, commits, pushes, or PR creation. It commits dirty source,
|
|
455
455
|
writes custom `--notes` / `--notes-file` content or a bounded Cursor, Codex,
|
|
456
456
|
Claude, then Git fallback to `.release-notes/requests/<branch>.md`, adds one
|
|
457
|
-
request commit, and pushes. The generated
|
|
458
|
-
|
|
457
|
+
request commit, and pushes. The generated workflow creates or updates the source
|
|
458
|
+
PR, merges it directly with `GITHUB_TOKEN`, and dispatches release planning, so
|
|
459
|
+
no UI approval or merge is required. GitHub may briefly record
|
|
460
|
+
`action_required` for the bot-authored PR validation; it is not a required gate.
|
|
459
461
|
|
|
460
462
|
After the source PR merges, Release Please retains direct conventional semantic
|
|
461
463
|
increments and applies required dependent patches. Reconciliation copies the
|
|
462
464
|
readable request Markdown into one temporary
|
|
463
465
|
`.release-notes/final/<component>-v<version>.md` per affected component and
|
|
464
|
-
deletes the consumed request file in the release PR
|
|
465
|
-
|
|
466
|
-
|
|
466
|
+
deletes the consumed request file in the release PR, then merges that generated
|
|
467
|
+
PR and explicitly dispatches publication. A source merge with no affected
|
|
468
|
+
release units creates no release PR or publication work. Publication applies
|
|
469
|
+
each file to its matching GitHub Release, then removes the temporary notes tree
|
|
470
|
+
in a cleanup commit. Request and final notes never count as source changes.
|
|
467
471
|
|
|
468
472
|
The GitHub PR workflow runs the explicit `pr:validate` task through Projen's
|
|
469
473
|
public `BuildWorkflow` `buildTask` option. That task runs synth plus the
|
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/projen";
|
|
6
|
-
export const PACKAGE_VERSION = "0.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.1";
|
|
7
7
|
export * as barrels from "./src/barrels.ts";
|
|
8
8
|
export * as bunApp from "./src/bun-app.ts";
|
|
9
9
|
export * as bunWorkflow from "./src/bun-workflow.ts";
|
package/package.json
CHANGED
package/src/codegen.ts
CHANGED
|
@@ -67,6 +67,16 @@ interface CodegenInput {
|
|
|
67
67
|
name: string;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
function packageName(dir: string): string {
|
|
71
|
+
const name = readPackageManifest(dir)?.name;
|
|
72
|
+
return typeof name === "string" && name.length > 0 ? name : basename(dir);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function sourceLabel(source: string): string {
|
|
76
|
+
const nodeModulesPrefix = "node_modules/";
|
|
77
|
+
return source.startsWith(nodeModulesPrefix) ? source.slice(nodeModulesPrefix.length) : source;
|
|
78
|
+
}
|
|
79
|
+
|
|
70
80
|
/** Read a package's `package.json` `codegen.inputs`, or `undefined` if absent. */
|
|
71
81
|
function codegenInputs(dir: string): string[] | undefined {
|
|
72
82
|
const codegen = readPackageManifest(dir)?.codegen;
|
|
@@ -282,6 +292,7 @@ function generatePackage(
|
|
|
282
292
|
): string {
|
|
283
293
|
const parsed = inputs.map(parseInputArg);
|
|
284
294
|
const srcDir = resolve(dir, "src");
|
|
295
|
+
const destinationPackage = packageName(dir);
|
|
285
296
|
mkdirSync(srcDir, { recursive: true });
|
|
286
297
|
|
|
287
298
|
// Remove prior generated modules (read-only + our header) so a dropped input
|
|
@@ -295,12 +306,13 @@ function generatePackage(
|
|
|
295
306
|
}
|
|
296
307
|
}
|
|
297
308
|
|
|
298
|
-
let warnings = 0;
|
|
299
309
|
for (const input of parsed) {
|
|
300
310
|
const sourcePath = resolveInputSource(input.source, dir, projectRoot);
|
|
301
311
|
if (!existsSync(sourcePath)) {
|
|
302
312
|
throw new Error(`codegen input not found: ${input.source}`);
|
|
303
313
|
}
|
|
314
|
+
const destination = `${destinationPackage}/src/${input.name}.ts`;
|
|
315
|
+
const source = sourceLabel(input.source);
|
|
304
316
|
|
|
305
317
|
const sourceText = preprocess(stripImports(tsRuntime, sourcePath));
|
|
306
318
|
const { getZodSchemasFile, getInferredTypes, errors } = generate({
|
|
@@ -310,8 +322,7 @@ function generatePackage(
|
|
|
310
322
|
keepComments: true,
|
|
311
323
|
});
|
|
312
324
|
if (errors.length) {
|
|
313
|
-
|
|
314
|
-
for (const err of errors) logger.warn(` ! ${err}`);
|
|
325
|
+
for (const err of errors) logger.warn(`${destination} from ${source}: ${err}`);
|
|
315
326
|
}
|
|
316
327
|
|
|
317
328
|
// ts-to-zod adds an import line only when the source references external
|
|
@@ -324,11 +335,12 @@ function generatePackage(
|
|
|
324
335
|
makeWritable(outPath);
|
|
325
336
|
writeFileSync(outPath, content);
|
|
326
337
|
makeReadonly(outPath);
|
|
338
|
+
logger.success(
|
|
339
|
+
`generated ${destination} from ${source}` +
|
|
340
|
+
(errors.length ? ` (${errors.length} warning(s))` : ""),
|
|
341
|
+
);
|
|
327
342
|
}
|
|
328
343
|
|
|
329
|
-
logger.success(
|
|
330
|
-
`${basename(dir)}: ${parsed.length} module(s)` + (warnings ? ` (${warnings} warning(s))` : ""),
|
|
331
|
-
);
|
|
332
344
|
return dir;
|
|
333
345
|
}
|
|
334
346
|
|
package/src/release-catalog.ts
CHANGED
|
@@ -800,12 +800,26 @@ function gitReleaseFiles(root: string, paths: readonly string[]): string[] | und
|
|
|
800
800
|
.filter(Boolean)
|
|
801
801
|
.map((path) => resolve(root, path))
|
|
802
802
|
.filter((path) => existsSync(path))
|
|
803
|
+
.filter((path) => paths.some((sourcePath) => trackedReleaseFile(sourcePath, path)))
|
|
803
804
|
.sort();
|
|
804
805
|
} catch {
|
|
805
806
|
return undefined;
|
|
806
807
|
}
|
|
807
808
|
}
|
|
808
809
|
|
|
810
|
+
function trackedReleaseFile(sourcePath: string, path: string): boolean {
|
|
811
|
+
const sourceRelative = toPosix(relative(sourcePath, path));
|
|
812
|
+
if (sourceRelative.startsWith("../") || sourceRelative === "..") return false;
|
|
813
|
+
const parts = sourceRelative.split("/");
|
|
814
|
+
const file = parts.pop();
|
|
815
|
+
if (!file) return false;
|
|
816
|
+
if (parts.some((part) => IGNORED_DIRECTORIES.has(part))) return false;
|
|
817
|
+
if (IGNORED_FILES.has(file) || file.endsWith(".lock") || file.startsWith("tsconfig")) {
|
|
818
|
+
return false;
|
|
819
|
+
}
|
|
820
|
+
return sourceRelative !== "index.ts";
|
|
821
|
+
}
|
|
822
|
+
|
|
809
823
|
function releaseFiles(path: string): string[] {
|
|
810
824
|
if (!existsSync(path)) return [];
|
|
811
825
|
const entries = readdirSync(path, { withFileTypes: true });
|
package/src/release.ts
CHANGED
|
@@ -352,9 +352,10 @@ function addDocsJobs(
|
|
|
352
352
|
|
|
353
353
|
function independentReleasePleaseJob(project: DBXToolsJavaScriptProject, branch: string): Job {
|
|
354
354
|
return {
|
|
355
|
-
if: "${{ github.event_name == 'push' }}",
|
|
355
|
+
if: "${{ github.event_name == 'push' || inputs.automatic == true }}",
|
|
356
356
|
runsOn: ["ubuntu-latest"],
|
|
357
357
|
permissions: {
|
|
358
|
+
actions: JobPermission.WRITE,
|
|
358
359
|
contents: JobPermission.WRITE,
|
|
359
360
|
pullRequests: JobPermission.WRITE,
|
|
360
361
|
},
|
|
@@ -419,7 +420,11 @@ function independentReleasePleaseJob(project: DBXToolsJavaScriptProject, branch:
|
|
|
419
420
|
{
|
|
420
421
|
name: "Reconcile generated release PR files",
|
|
421
422
|
if: "${{ steps.release.outputs.prs_created == 'true' }}",
|
|
422
|
-
env: {
|
|
423
|
+
env: {
|
|
424
|
+
GH_TOKEN: "${{ github.token }}",
|
|
425
|
+
RELEASE_BRANCH: branch,
|
|
426
|
+
RELEASE_PRS: "${{ steps.release.outputs.prs }}",
|
|
427
|
+
},
|
|
423
428
|
shell: "bash",
|
|
424
429
|
run: [
|
|
425
430
|
'BRANCH="$(jq -r \'.[0].headBranchName\' <<<"$RELEASE_PRS")"',
|
|
@@ -438,6 +443,26 @@ function independentReleasePleaseJob(project: DBXToolsJavaScriptProject, branch:
|
|
|
438
443
|
' git commit -m "chore: reconcile release metadata"',
|
|
439
444
|
' git push origin "HEAD:$BRANCH"',
|
|
440
445
|
"fi",
|
|
446
|
+
'MERGED="false"',
|
|
447
|
+
"for ATTEMPT in $(seq 1 15); do",
|
|
448
|
+
' STATE="$(gh pr view "$BRANCH" --json state,mergeable --jq \'[.state,.mergeable] | join(" ")\')"',
|
|
449
|
+
' if [[ "$STATE" == MERGED* ]]; then MERGED="true"; break; fi',
|
|
450
|
+
' if [ "$STATE" = "OPEN CONFLICTING" ]; then',
|
|
451
|
+
' echo "::error::release pull request has merge conflicts"',
|
|
452
|
+
" exit 1",
|
|
453
|
+
" fi",
|
|
454
|
+
' if [ "$STATE" = "OPEN MERGEABLE" ] && gh pr merge "$BRANCH" --merge; then',
|
|
455
|
+
' MERGED="true"',
|
|
456
|
+
" break",
|
|
457
|
+
" fi",
|
|
458
|
+
' echo "release pull request is not mergeable yet (attempt $ATTEMPT/15)"',
|
|
459
|
+
" sleep 2",
|
|
460
|
+
"done",
|
|
461
|
+
'if [ "$MERGED" != "true" ]; then',
|
|
462
|
+
' echo "::error::release pull request did not become mergeable"',
|
|
463
|
+
" exit 1",
|
|
464
|
+
"fi",
|
|
465
|
+
'gh workflow run release.yml --ref "$RELEASE_BRANCH" -f automatic=true',
|
|
441
466
|
].join("\n"),
|
|
442
467
|
},
|
|
443
468
|
],
|
|
@@ -464,6 +489,7 @@ function configureReleaseRequestWorkflow(
|
|
|
464
489
|
if: `\${{ github.ref_name != '${baseBranch}' }}`,
|
|
465
490
|
runsOn: ["ubuntu-latest"],
|
|
466
491
|
permissions: {
|
|
492
|
+
actions: JobPermission.WRITE,
|
|
467
493
|
contents: JobPermission.WRITE,
|
|
468
494
|
pullRequests: JobPermission.WRITE,
|
|
469
495
|
},
|
|
@@ -490,13 +516,12 @@ function configureReleaseRequestWorkflow(
|
|
|
490
516
|
"fi",
|
|
491
517
|
'echo "requested=true" >> "$GITHUB_OUTPUT"',
|
|
492
518
|
'echo "branch=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT"',
|
|
493
|
-
'echo "approve=$(sed -n \'s/^Release-Approve: //p\' <<<"$MESSAGE" | tail -1)" >> "$GITHUB_OUTPUT"',
|
|
494
519
|
'echo "notes_path=$(sed -n \'s/^Release-Notes-Path: //p\' <<<"$MESSAGE" | tail -1)" >> "$GITHUB_OUTPUT"',
|
|
495
520
|
'echo "title=$(git log -1 --skip=1 --format=%s)" >> "$GITHUB_OUTPUT"',
|
|
496
521
|
].join("\n"),
|
|
497
522
|
},
|
|
498
523
|
{
|
|
499
|
-
name: "Create
|
|
524
|
+
name: "Create, merge, and release source pull request",
|
|
500
525
|
if: "${{ steps.request.outputs.requested == 'true' }}",
|
|
501
526
|
env: {
|
|
502
527
|
GH_TOKEN: "${{ github.token }}",
|
|
@@ -504,7 +529,6 @@ function configureReleaseRequestWorkflow(
|
|
|
504
529
|
BASE_BRANCH: baseBranch,
|
|
505
530
|
TITLE: "${{ steps.request.outputs.title }}",
|
|
506
531
|
NOTES_PATH: "${{ steps.request.outputs.notes_path }}",
|
|
507
|
-
APPROVE: "${{ steps.request.outputs.approve }}",
|
|
508
532
|
},
|
|
509
533
|
shell: "bash",
|
|
510
534
|
run: [
|
|
@@ -518,7 +542,8 @@ function configureReleaseRequestWorkflow(
|
|
|
518
542
|
' gh pr create --head "$SOURCE_BRANCH" --base "$BASE_BRANCH" --title "$TITLE" --body "$BODY"',
|
|
519
543
|
' PR="$(gh pr list --head "$SOURCE_BRANCH" --base "$BASE_BRANCH" --state open --json number --jq \'.[0].number\')"',
|
|
520
544
|
"fi",
|
|
521
|
-
'
|
|
545
|
+
'gh pr merge "$PR" --merge',
|
|
546
|
+
'gh workflow run release.yml --repo "$GITHUB_REPOSITORY" --ref "$BASE_BRANCH" -f automatic=true',
|
|
522
547
|
].join("\n"),
|
|
523
548
|
},
|
|
524
549
|
],
|
|
@@ -527,7 +552,7 @@ function configureReleaseRequestWorkflow(
|
|
|
527
552
|
|
|
528
553
|
function independentReleasePlanJob(project: DBXToolsJavaScriptProject): Job {
|
|
529
554
|
return {
|
|
530
|
-
if: "${{ always() && (github.event_name == 'workflow_dispatch' || needs.release-please.outputs.releases_created == 'true' || needs.release-please.outputs.docs_changed == 'true' || needs.release-please.outputs.recovery_requested == 'true') }}",
|
|
555
|
+
if: "${{ always() && ((github.event_name == 'workflow_dispatch' && inputs.automatic != true) || needs.release-please.outputs.releases_created == 'true' || (needs.release-please.outputs.docs_changed == 'true' && needs.release-please.outputs.prs_created != 'true') || needs.release-please.outputs.recovery_requested == 'true') }}",
|
|
531
556
|
needs: ["release-please"],
|
|
532
557
|
runsOn: ["ubuntu-latest"],
|
|
533
558
|
permissions: { contents: JobPermission.READ },
|
|
@@ -687,9 +712,8 @@ function addIndependentDocsJobs(
|
|
|
687
712
|
timeoutMinutes: 30,
|
|
688
713
|
env: {
|
|
689
714
|
BUN_VERSION,
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
BASE_PATH: options.base ?? "${{ github.event.repository.name }}",
|
|
715
|
+
DOCS_SITE_URL: options.siteUrl,
|
|
716
|
+
DOCS_BASE: options.base ?? "/",
|
|
693
717
|
},
|
|
694
718
|
steps: [
|
|
695
719
|
...independentReleaseSetupSteps(project),
|
|
@@ -727,8 +751,9 @@ function addIndependentBranchSyncJob(
|
|
|
727
751
|
project: DBXToolsJavaScriptProject,
|
|
728
752
|
branch: string,
|
|
729
753
|
): void {
|
|
754
|
+
const releaseBranch = projectReleaseBranch(project);
|
|
730
755
|
workflow.addJob("sync-release-branch", {
|
|
731
|
-
if: "${{ always() && github.event_name == 'push' && needs['publication-complete'].result == 'success' }}",
|
|
756
|
+
if: "${{ always() && (github.event_name == 'push' || inputs.automatic == true) && needs['publication-complete'].result == 'success' }}",
|
|
732
757
|
needs: ["publication-complete"],
|
|
733
758
|
runsOn: ["ubuntu-latest"],
|
|
734
759
|
permissions: { contents: JobPermission.WRITE },
|
|
@@ -746,22 +771,23 @@ function addIndependentBranchSyncJob(
|
|
|
746
771
|
{
|
|
747
772
|
name: `Safely sync ${branch}`,
|
|
748
773
|
shell: "bash",
|
|
749
|
-
env: { SOURCE_BRANCH: branch },
|
|
774
|
+
env: { SOURCE_BRANCH: branch, RELEASE_BRANCH: releaseBranch },
|
|
750
775
|
run: [
|
|
751
776
|
'if ! git ls-remote --exit-code --heads origin "refs/heads/$SOURCE_BRANCH" >/dev/null 2>&1; then',
|
|
752
777
|
' echo "source branch $SOURCE_BRANCH no longer exists; nothing to sync"',
|
|
753
778
|
" exit 0",
|
|
754
779
|
"fi",
|
|
755
780
|
'git fetch origin "refs/heads/$SOURCE_BRANCH:refs/remotes/origin/$SOURCE_BRANCH"',
|
|
756
|
-
'
|
|
757
|
-
'
|
|
758
|
-
'
|
|
781
|
+
'git fetch origin "refs/heads/$RELEASE_BRANCH:refs/remotes/origin/$RELEASE_BRANCH"',
|
|
782
|
+
'if git merge-base --is-ancestor "origin/$SOURCE_BRANCH" "origin/$RELEASE_BRANCH"; then',
|
|
783
|
+
' git push origin "refs/remotes/origin/$RELEASE_BRANCH:refs/heads/$SOURCE_BRANCH"',
|
|
784
|
+
'elif git merge-base --is-ancestor "origin/$RELEASE_BRANCH" "origin/$SOURCE_BRANCH"; then',
|
|
759
785
|
' echo "source branch $SOURCE_BRANCH already contains released main"',
|
|
760
786
|
"else",
|
|
761
787
|
' git config user.name "github-actions[bot]"',
|
|
762
788
|
' git config user.email "41898282+github-actions[bot]@users.noreply.github.com"',
|
|
763
789
|
' git switch --force-create "$SOURCE_BRANCH" "origin/$SOURCE_BRANCH"',
|
|
764
|
-
' if git merge --no-ff --no-edit "
|
|
790
|
+
' if git merge --no-ff --no-edit "origin/$RELEASE_BRANCH"; then',
|
|
765
791
|
' git push origin "HEAD:refs/heads/$SOURCE_BRANCH"',
|
|
766
792
|
" else",
|
|
767
793
|
' SAFE_GENERATED="true"',
|
|
@@ -862,11 +888,18 @@ function configureIndependentRelease(
|
|
|
862
888
|
concurrencyOptions: { group: "release", cancelInProgress: false },
|
|
863
889
|
});
|
|
864
890
|
workflow.runName =
|
|
865
|
-
"release units " +
|
|
891
|
+
"release units " +
|
|
892
|
+
"${{ github.event_name == 'push' && github.sha || inputs.automatic && 'automatic' || inputs.component }}";
|
|
866
893
|
workflow.on({
|
|
867
894
|
push: { branches: [branch] },
|
|
868
895
|
workflowDispatch: {
|
|
869
896
|
inputs: {
|
|
897
|
+
automatic: {
|
|
898
|
+
description: "Continue an automatically merged Release Please pull request",
|
|
899
|
+
type: "boolean",
|
|
900
|
+
default: "false",
|
|
901
|
+
required: false,
|
|
902
|
+
},
|
|
870
903
|
component: {
|
|
871
904
|
description: "Component to recover",
|
|
872
905
|
type: "string",
|
|
@@ -889,6 +922,7 @@ function configureIndependentRelease(
|
|
|
889
922
|
},
|
|
890
923
|
},
|
|
891
924
|
});
|
|
925
|
+
workflow.file?.addOverride("on.workflow_dispatch.inputs.automatic.default", false);
|
|
892
926
|
workflow.file?.addOverride("permissions.contents", "read");
|
|
893
927
|
workflow.addJob("release-please", independentReleasePleaseJob(project, branch));
|
|
894
928
|
workflow.addJob("release-plan", independentReleasePlanJob(project));
|
package/tasks/release-please.ts
CHANGED
package/tasks/release-request.ts
CHANGED
|
@@ -13,7 +13,6 @@ const logger = log.logger("projen:release-request");
|
|
|
13
13
|
export interface PrepareReleaseRequestOptions {
|
|
14
14
|
readonly root: string;
|
|
15
15
|
readonly baseBranch: string;
|
|
16
|
-
readonly approve?: boolean;
|
|
17
16
|
readonly message?: string;
|
|
18
17
|
readonly notes?: string;
|
|
19
18
|
readonly notesFile?: string;
|
|
@@ -94,12 +93,11 @@ export async function prepareReleaseRequest(
|
|
|
94
93
|
[
|
|
95
94
|
"Release-Request: true",
|
|
96
95
|
`Release-Source-Branch: ${branch}`,
|
|
97
|
-
`Release-Approve: ${options.approve === true}`,
|
|
98
96
|
`Release-Notes-Path: ${notesPath}`,
|
|
99
97
|
].join("\n"),
|
|
100
98
|
]);
|
|
101
99
|
if (options.push !== false) run(root, ["push", "--set-upstream", "origin", branch]);
|
|
102
|
-
logger.success("release request pushed", { branch
|
|
100
|
+
logger.success("release request pushed", { branch });
|
|
103
101
|
return true;
|
|
104
102
|
}
|
|
105
103
|
|
|
@@ -155,19 +153,22 @@ function run(root: string, args: string[]): void {
|
|
|
155
153
|
});
|
|
156
154
|
}
|
|
157
155
|
|
|
156
|
+
/** Restore option text after Projen forwards task arguments without shell quoting. */
|
|
157
|
+
function optionText(values?: readonly string[]): string | undefined {
|
|
158
|
+
return values?.join(" ");
|
|
159
|
+
}
|
|
160
|
+
|
|
158
161
|
if (import.meta.main) {
|
|
159
162
|
await new Command()
|
|
160
163
|
.option("--base <branch>", "release target branch", "main")
|
|
161
|
-
.option("--
|
|
162
|
-
.option("--
|
|
163
|
-
.option("--notes <notes>", "custom release notes")
|
|
164
|
+
.option("--message <message...>", "commit message for uncommitted source changes")
|
|
165
|
+
.option("--notes <notes...>", "custom release notes")
|
|
164
166
|
.option("--notes-file <path>", "read custom release notes from a file")
|
|
165
167
|
.action(
|
|
166
168
|
async (options: {
|
|
167
169
|
base: string;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
notes?: string;
|
|
170
|
+
message?: string[];
|
|
171
|
+
notes?: string[];
|
|
171
172
|
notesFile?: string;
|
|
172
173
|
}) => {
|
|
173
174
|
if (options.notes && options.notesFile) {
|
|
@@ -176,9 +177,8 @@ if (import.meta.main) {
|
|
|
176
177
|
await prepareReleaseRequest({
|
|
177
178
|
root: project.root() ?? process.cwd(),
|
|
178
179
|
baseBranch: options.base,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
notes: options.notes,
|
|
180
|
+
message: optionText(options.message),
|
|
181
|
+
notes: optionText(options.notes),
|
|
182
182
|
notesFile: options.notesFile,
|
|
183
183
|
});
|
|
184
184
|
},
|