@docupace/pipeline 1.0.123 → 1.0.126

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/.gitignore ADDED
@@ -0,0 +1,103 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # IDE
4
+ .idea
5
+ *.iml
6
+ # Dependencies
7
+ /node_modules
8
+ /.pnp
9
+ .pnp.js
10
+
11
+ # Testing
12
+ /coverage
13
+
14
+ # Next.js
15
+ /.next/
16
+ /out/
17
+
18
+ # Production
19
+ /build
20
+ /dist
21
+
22
+ # Misc
23
+ .DS_Store
24
+ *.pem
25
+ cypress/screenshots/
26
+
27
+ # Debug
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+
32
+ # Local env files
33
+ .env*.local
34
+
35
+ # Vercel
36
+ .vercel
37
+
38
+ # Typescript
39
+ *.tsbuildinfo
40
+ next-env.d.ts
41
+
42
+
43
+ # Logs
44
+ logs
45
+ *.log
46
+
47
+ # Runtime data
48
+ pids
49
+ *.pid
50
+ *.seed
51
+
52
+ # Directory for instrumented libs generated by jscoverage/JSCover
53
+ lib-cov
54
+
55
+ # Coverage directory used by tools like istanbul
56
+ coverage
57
+
58
+ # nyc test coverage
59
+ .nyc_output
60
+
61
+ # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
62
+ .grunt
63
+
64
+ # node-waf configuration
65
+ .lock-wscript
66
+
67
+ # Compiled binary addons (http://nodejs.org/api/addons.html)
68
+ build/Release
69
+
70
+ # Dependency directories
71
+ node_modules
72
+ jspm_packages
73
+
74
+ # Optional npm cache directory
75
+ .npm
76
+
77
+ # Optional REPL history
78
+ .node_repl_history
79
+ .next
80
+
81
+ scratch
82
+
83
+ # visual studio code
84
+ .vscode/
85
+
86
+ src/gql/graphql.js
87
+ .yalc/
88
+ yalc.lock
89
+
90
+ .last-run.json
91
+
92
+ test-results
93
+ coverage-reports
94
+ .sonar
95
+ .v8-coverage
96
+ /assets
97
+ tests/lib/data/auth.json
98
+
99
+ failed-tests.json
100
+
101
+ /tmp
102
+
103
+ .claude
@@ -8,11 +8,33 @@ definitions:
8
8
  caches:
9
9
  pnpm: ~/.pnpm-store
10
10
 
11
- # Pipelines under `definitions.pipelines` are the ones other repos can pull in
12
- # with `import: pipeline-shared-scripts:master:<name>`. Names under
13
- # `pipelines.custom` below are local to this repo and are NOT importable.
11
+ steps:
12
+ - step: &version-step
13
+ runs-on:
14
+ - self.hosted
15
+ - linux.shell
16
+ - onprem
17
+ name: On Merge
18
+ script:
19
+ - npm config set //registry.npmjs.org/:_authToken $DOCUPACE_NPM_TOKEN
20
+ - pnpm install --frozen-lockfile
21
+ - export HOME=/tmp
22
+ - node src/changeset/cli.js version-commit-tag --install-latest
23
+
24
+ # Bitbucket's cross-repo `import: pipeline-shared-scripts:master:<name>`
25
+ # resolves against definitions.pipelines.<name> in the exporting repo, and
26
+ # extracts just that one target subtree — so each entry here must be fully
27
+ # self-contained: a YAML alias pointing at an anchor defined outside of it
28
+ # (in a sibling entry here, or anywhere else in this file) resolves to
29
+ # nothing once extracted in isolation, and the imported step comes back
30
+ # "empty, null, or missing" on the consumer side. Content needed in more
31
+ # than one of these (the Tenable step, the Sonar scan script) is therefore
32
+ # duplicated instead of shared via anchor/alias. pipelines.custom below
33
+ # aliases into these (safe: same-document, not crossing the export
34
+ # boundary) purely so this repo can also run each one manually from its
35
+ # own Pipelines UI.
14
36
  pipelines:
15
- xray-scan: &xray-scan-pipeline
37
+ xray-scan: &def-xray-scan
16
38
  - step:
17
39
  name: JFrog Xray Scan (dependencies + Docker image)
18
40
  runs-on:
@@ -235,15 +257,15 @@ definitions:
235
257
  artifacts:
236
258
  - xray-report/**
237
259
 
238
- - step: &tenable-scan-step
260
+ - step:
239
261
  name: Tenable Cloud Security Scan (container image)
240
262
  runs-on:
241
263
  - self.hosted
242
264
  - linux.shell
243
265
  - onprem
244
266
  script:
245
- # bin/tenable-scan.sh lives in this shared repo; an import only brings
246
- # the YAML across, so fetch it the same way the Xray step does.
267
+ # bin/tenable-scan.sh lives in this shared repo, but an import only
268
+ # brings the YAML across — so fetch it the same way the Xray step does.
247
269
  - |
248
270
  TENABLE_BIN=""
249
271
  if [ -f ./bin/tenable-scan.sh ]; then
@@ -289,8 +311,56 @@ definitions:
289
311
 
290
312
  # Runs the Tenable image scan on its own, for repos that want it separately
291
313
  # from the Xray scan: import: pipeline-shared-scripts:master:tenable-scan
292
- tenable-scan:
293
- - step: *tenable-scan-step
314
+ tenable-scan: &def-tenable-scan
315
+ - step:
316
+ name: Tenable Cloud Security Scan (container image)
317
+ runs-on:
318
+ - self.hosted
319
+ - linux.shell
320
+ - onprem
321
+ script:
322
+ - |
323
+ TENABLE_BIN=""
324
+ if [ -f ./bin/tenable-scan.sh ]; then
325
+ TENABLE_BIN=./bin
326
+ else
327
+ DEST=/tmp/pipeline-shared-scripts
328
+ rm -rf "${DEST}"
329
+ LABELS=""; URLS=""
330
+ add_src() { LABELS="${LABELS}${LABELS:+|}$1"; URLS="${URLS}${URLS:+|}$2"; }
331
+ [ -n "${SCRIPTS_REPO:-}" ] && add_src "SCRIPTS_REPO" "${SCRIPTS_REPO}"
332
+ if [ -n "${BITBUCKET_USERNAME:-}" ] && [ -n "${BITBUCKET_APP_PASSWORD:-}" ]; then
333
+ add_src "BITBUCKET_USERNAME+APP_PASSWORD" "https://${BITBUCKET_USERNAME}:${BITBUCKET_APP_PASSWORD}@bitbucket.org/dp-cloud/pipeline-shared-scripts.git"
334
+ fi
335
+ [ -n "${BITBUCKET_STEP_OAUTH_TOKEN:-}" ] && add_src "step OAuth token" "https://x-token-auth:${BITBUCKET_STEP_OAUTH_TOKEN}@bitbucket.org/dp-cloud/pipeline-shared-scripts.git"
336
+ add_src "ssh" "git@bitbucket.org:dp-cloud/pipeline-shared-scripts.git"
337
+ i=1
338
+ while :; do
339
+ label="$(printf '%s' "${LABELS}" | cut -d'|' -f${i})"
340
+ url="$(printf '%s' "${URLS}" | cut -d'|' -f${i})"
341
+ [ -z "${label}" ] && break
342
+ echo "Fetching shared scripts via ${label}..."
343
+ if GIT_TERMINAL_PROMPT=0 GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new -o BatchMode=yes" \
344
+ git clone --depth 1 --quiet "${url}" "${DEST}" 2>/dev/null; then
345
+ TENABLE_BIN="${DEST}/bin"
346
+ echo "Fetched shared scripts via ${label}."
347
+ break
348
+ fi
349
+ rm -rf "${DEST}"
350
+ i=$((i + 1))
351
+ done
352
+ fi
353
+ if [ -z "${TENABLE_BIN}" ]; then
354
+ echo "Could not fetch shared scripts (tried: $(printf '%s' "${LABELS}" | tr '|' ' ')) — skipping Tenable scan."
355
+ exit 0
356
+ fi
357
+ if [ ! -f "${TENABLE_BIN}/tenable-scan.sh" ]; then
358
+ echo "tenable-scan.sh not present in ${TENABLE_BIN} — skipping Tenable scan."
359
+ exit 0
360
+ fi
361
+ bash "${TENABLE_BIN}/tenable-scan.sh"
362
+ artifacts:
363
+ - tenable-report/**
294
364
 
295
365
  # Uploads and scans one or more app targets with Veracode:
296
366
  # import: pipeline-shared-scripts:master:veracode-scan
@@ -300,7 +370,7 @@ definitions:
300
370
  # (an app profile named <appname> must already exist in the Veracode portal)
301
371
  # Optional: VERACODE_BUILD_CMD — eval'd before packaging, so this step is
302
372
  # self-contained and needs no separate build step in the consumer pipeline.
303
- veracode-scan:
373
+ veracode-scan: &def-veracode-scan
304
374
  - step:
305
375
  name: Veracode Upload and Scan
306
376
  runs-on:
@@ -409,8 +479,8 @@ definitions:
409
479
  #
410
480
  # depth: full — Sonar reads git blame to attribute New Code; a shallow clone
411
481
  # only sees the tip commit and silently treats everything as new.
412
- sonar-scan: &sonar-scan-pipeline
413
- - step: &sonar-scan-step
482
+ sonar-scan: &def-sonar-scan
483
+ - step:
414
484
  name: SonarQube Scan
415
485
  runs-on:
416
486
  - self.hosted
@@ -424,7 +494,7 @@ definitions:
424
494
  echo "Skipping SonarQube scan: SONAR_TOKEN not set"
425
495
  exit 0
426
496
  fi
427
- - &sonar-scan-script |
497
+ - |
428
498
  export DOCKER_HOST=""
429
499
  unset DOCKER_CONTEXT
430
500
  SONAR_HOST="${SONAR_HOST_URL:-https://sonarcloud.io}"
@@ -527,7 +597,7 @@ definitions:
527
597
  # Required: SONAR_TOKEN (hard-fails if unset and the gate applies to this PR)
528
598
  # Optional: same as sonar-scan, plus SONAR_GATE_BRANCH (default "main") and
529
599
  # SONAR_QUALITYGATE_TIMEOUT (default 300 seconds).
530
- sonar-pr-gate:
600
+ sonar-pr-gate: &def-sonar-pr-gate
531
601
  - step:
532
602
  name: SonarQube Quality Gate
533
603
  runs-on:
@@ -557,27 +627,106 @@ definitions:
557
627
  fi
558
628
 
559
629
  export SONAR_WAIT_FOR_GATE=true
560
- - *sonar-scan-script
630
+ - |
631
+ export DOCKER_HOST=""
632
+ unset DOCKER_CONTEXT
633
+ SONAR_HOST="${SONAR_HOST_URL:-https://sonarcloud.io}"
634
+ DEFAULT_BRANCH="${SONAR_DEFAULT_BRANCH:-main}"
635
+ WORKDIR="$(pwd)"
561
636
 
562
- steps:
563
- - step: &version-step
564
- runs-on:
565
- - self.hosted
566
- - linux.shell
567
- - onprem
568
- name: On Merge
569
- script:
570
- - npm config set //registry.npmjs.org/:_authToken $DOCUPACE_NPM_TOKEN
571
- - pnpm install --frozen-lockfile
572
- - export HOME=/tmp
573
- - node src/changeset/cli.js version-commit-tag --install-latest
637
+ # Bitbucket's built-ins: BITBUCKET_BRANCH / BITBUCKET_PR_ID /
638
+ # BITBUCKET_PR_DESTINATION_BRANCH. An upload with no branch parameter
639
+ # is filed against the project's default branch, so scanning a
640
+ # feature branch without one would silently overwrite that branch's
641
+ # analysis and quality-gate status. Resolved once — every target in
642
+ # this run shares the same branch/PR context.
643
+ BRANCH="${BITBUCKET_BRANCH:-}"
644
+ PR_ID="${BITBUCKET_PR_ID:-}"
645
+ PR_BASE="${BITBUCKET_PR_DESTINATION_BRANCH:-}"
646
+ BRANCH_DOCKER_ARGS=""
647
+ BRANCH_SONAR_ARGS=""
648
+
649
+ if [ -n "${PR_ID}" ]; then
650
+ BRANCH_DOCKER_ARGS="-e PR_ID=${PR_ID}"
651
+ BRANCH_SONAR_ARGS="-Dsonar.pullrequest.key=${PR_ID}"
652
+ [ -n "${BRANCH}" ] && BRANCH_SONAR_ARGS="${BRANCH_SONAR_ARGS} -Dsonar.pullrequest.branch=${BRANCH}"
653
+ [ -n "${PR_BASE}" ] && BRANCH_SONAR_ARGS="${BRANCH_SONAR_ARGS} -Dsonar.pullrequest.base=${PR_BASE}"
654
+ elif [ -n "${BRANCH}" ] && [ "${BRANCH}" != "${DEFAULT_BRANCH}" ]; then
655
+ BRANCH_DOCKER_ARGS="-e BRANCH=${BRANCH}"
656
+ BRANCH_SONAR_ARGS="-Dsonar.branch.name=${BRANCH}"
657
+ elif [ -n "${BITBUCKET_TAG:-}" ] || [ "${BRANCH}" = "${DEFAULT_BRANCH}" ]; then
658
+ echo "Sonar: analysing as the default branch (${DEFAULT_BRANCH})"
659
+ else
660
+ echo "ERROR: cannot tell which branch this analysis belongs to — none of BITBUCKET_PR_ID, BITBUCKET_BRANCH or BITBUCKET_TAG is set." >&2
661
+ echo " Refusing to upload: SonarCloud would file it against '${DEFAULT_BRANCH}' and overwrite that branch's analysis." >&2
662
+ exit 1
663
+ fi
664
+
665
+ if [ "${SONAR_WAIT_FOR_GATE:-false}" = "true" ]; then
666
+ BRANCH_SONAR_ARGS="${BRANCH_SONAR_ARGS} -Dsonar.qualitygate.wait=true -Dsonar.qualitygate.timeout=${SONAR_QUALITYGATE_TIMEOUT:-300}"
667
+ fi
668
+
669
+ # Looks up "${1}_<SLUG>" if set, else prints nothing — POSIX sh has no
670
+ # ${!indirect} expansion, so this shells out through eval instead.
671
+ target_var() {
672
+ eval "printf '%s' \"\${$1_${2}:-}\""
673
+ }
674
+
675
+ # Each target is its own SonarCloud project — like Veracode's per-app
676
+ # profiles, a repo with several components (frontend/backend) needs
677
+ # its own sonar.projectKey per component, not one shared analysis.
678
+ failed=0
679
+ OLD_IFS="${IFS}"
680
+ IFS=';'
681
+ set -- ${SONAR_TARGETS:-default:${SONAR_PROJECT_DIR:-.}}
682
+ IFS="${OLD_IFS}"
683
+
684
+ for target in "$@"; do
685
+ [ -z "${target}" ] && continue
686
+ label="$(printf '%s' "${target}" | cut -d: -f1)"
687
+ project_dir="$(printf '%s' "${target}" | cut -d: -f2)"
688
+ [ -z "${label}" ] && label="default"
689
+ [ -z "${project_dir}" ] && project_dir="."
690
+ slug="$(printf '%s' "${label}" | tr -c 'A-Za-z0-9' '_' | tr 'a-z' 'A-Z')"
691
+
692
+ coverage_cmd="$(target_var SONAR_COVERAGE_CMD "${slug}")"
693
+ [ -z "${coverage_cmd}" ] && coverage_cmd="${SONAR_COVERAGE_CMD:-}"
694
+ coverage_path="$(target_var SONAR_COVERAGE_REPORT_PATH "${slug}")"
695
+ [ -z "${coverage_path}" ] && coverage_path="${SONAR_COVERAGE_REPORT_PATH:-}"
696
+
697
+ if [ -n "${coverage_cmd}" ]; then
698
+ echo "[${label}] Running coverage command..."
699
+ eval "${coverage_cmd}" || echo "WARN: coverage command exited non-zero for '${label}'; checking for the report anyway."
700
+ fi
701
+ if [ -n "${coverage_path}" ] && [ ! -s "${coverage_path}" ]; then
702
+ echo "ERROR: ${coverage_path} missing or empty for target '${label}' — Sonar would report 0% coverage." >&2
703
+ failed=1
704
+ continue
705
+ fi
706
+
707
+ DOCKER_ARGS="run --rm --platform linux/amd64 -e SONAR_HOST_URL=${SONAR_HOST} -e SONAR_TOKEN ${BRANCH_DOCKER_ARGS} -v ${WORKDIR}:/workspace -w /workspace/${project_dir}"
708
+ SONAR_ARGS="sonar-scanner -Dsonar.host.url=${SONAR_HOST} -Dproject.settings=/workspace/${project_dir}/sonar-project.properties ${BRANCH_SONAR_ARGS}"
709
+
710
+ echo "[${label}] Running: docker ${DOCKER_ARGS} sonarsource/sonar-scanner-cli:latest ${SONAR_ARGS}"
711
+ docker ${DOCKER_ARGS} sonarsource/sonar-scanner-cli:latest ${SONAR_ARGS} || {
712
+ failed=1
713
+ echo "ERROR: Sonar scan failed for target '${label}'." >&2
714
+ }
715
+ done
716
+
717
+ [ "${failed}" -ne 0 ] && exit 1
718
+ exit 0
574
719
 
575
720
  pipelines:
576
- # Lets this repo run the shared scans against itself from the Bitbucket UI.
721
+ # These simply alias the definitions.pipelines entries above (safe:
722
+ # same-document reuse, not a cross-repo import) so this repo can also run
723
+ # each shared pipeline manually from its own Pipelines UI.
577
724
  custom:
578
- xray-scan: *xray-scan-pipeline
579
- tenable-scan:
580
- - step: *tenable-scan-step
725
+ xray-scan: *def-xray-scan
726
+ tenable-scan: *def-tenable-scan
727
+ veracode-scan: *def-veracode-scan
728
+ sonar-scan: *def-sonar-scan
729
+ sonar-pr-gate: *def-sonar-pr-gate
581
730
 
582
731
  pull-requests:
583
732
  '**':
@@ -618,4 +767,4 @@ pipelines:
618
767
  - pnpm install --frozen-lockfile
619
768
  - 'npx eslint . --rule "no-unused-vars: warn" --rule "no-useless-escape: warn" --color'
620
769
  - pnpm test
621
- - pnpm publish --no-git-checks
770
+ - pnpm publish --no-git-checks
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docupace/pipeline",
3
- "version": "1.0.123",
3
+ "version": "1.0.126",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -94,6 +94,10 @@ export async function uploadToCanny(releaseNote, labelIDs) {
94
94
 
95
95
  const body = JSON.stringify(bodyPayload);
96
96
 
97
+ console.log(
98
+ `📤 Posting to Canny: ${JSON.stringify({ ...bodyPayload, apiKey: undefined }, null, 2)}`,
99
+ );
100
+
97
101
  // Create a new changelog entry in Canny
98
102
  const createResponse = await fetch(
99
103
  'https://canny.io/api/v1/entries/create',
@@ -5,7 +5,12 @@ import lodash from 'lodash';
5
5
  import path from 'path';
6
6
  import semver from 'semver';
7
7
  import { $ } from 'zx';
8
- import { appInfo, environmentConfig, getRepUrl } from './config.js';
8
+ import {
9
+ appInfo,
10
+ environmentConfig,
11
+ getDefaultAppInfo,
12
+ getRepUrl,
13
+ } from './config.js';
9
14
  import { copy2 } from './copy.js';
10
15
  import { gitDescribeToSemver } from './git-to-semver.js';
11
16
  import { deployConnect, deployCore } from './jenkins.js';
@@ -393,7 +398,12 @@ export async function deployTemplate(
393
398
  export async function deployAppWithTag(application, env, site, deployTag) {
394
399
  console.log(`Deploying application: ${application} for site: ${site}`);
395
400
  console.log(`Using deployment tag: ${deployTag}`);
396
- const appDetails = appInfo[application];
401
+ const appDetails = appInfo[application] ?? getDefaultAppInfo(application);
402
+ if (!appInfo[application]) {
403
+ console.log(
404
+ `No appInfo entry for "${application}"; using default naming convention: repositoryName/imageName = "${appDetails.repositoryName}".`,
405
+ );
406
+ }
397
407
 
398
408
  const repoPath = await cloneEnvRepository(env);
399
409
  const { deployConfigFilePath: valuesFilePath } = getConfigPath(