seqpulse 0.3.0 → 0.5.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/CI_CD_SNIPPETS_MULTI-PLATFORM.md +221 -0
- package/README.md +30 -11
- package/bin/seqpulse.js +242 -0
- package/index.js +2 -0
- package/package.json +6 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# CI/CD Snippets Multi-Platform
|
|
2
|
+
|
|
3
|
+
Snippets de reference pour integrer `SeqPulse` avec la meme logique sur plusieurs plateformes CI/CD:
|
|
4
|
+
|
|
5
|
+
1. `trigger` avant le deploy
|
|
6
|
+
2. deploy applicatif
|
|
7
|
+
3. `finish` toujours execute, meme en cas d'echec
|
|
8
|
+
|
|
9
|
+
Tous les snippets ci-dessous utilisent le package publie `@nassir_gouomba/seqpulse@0.5.0` et la sortie ciblee `--output deploymentId`.
|
|
10
|
+
|
|
11
|
+
## Variables requises
|
|
12
|
+
|
|
13
|
+
Definir ces secrets/variables dans votre plateforme CI:
|
|
14
|
+
|
|
15
|
+
- `SEQPULSE_BASE_URL`
|
|
16
|
+
- `SEQPULSE_API_KEY`
|
|
17
|
+
- `SEQPULSE_METRICS_ENDPOINT`
|
|
18
|
+
|
|
19
|
+
## Design cible
|
|
20
|
+
|
|
21
|
+
- `trigger` reste non bloquant pour ne pas casser le deploy si SeqPulse est indisponible
|
|
22
|
+
- `deploymentId` est capture dans une variable CI, pas dans un JSON parse fragile
|
|
23
|
+
- `finish` recoit un statut explicite venant de la plateforme
|
|
24
|
+
|
|
25
|
+
## GitHub Actions
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
name: deploy
|
|
29
|
+
|
|
30
|
+
on:
|
|
31
|
+
push:
|
|
32
|
+
branches: [main]
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
deploy:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
env:
|
|
38
|
+
SEQPULSE_BASE_URL: ${{ secrets.SEQPULSE_BASE_URL }}
|
|
39
|
+
SEQPULSE_API_KEY: ${{ secrets.SEQPULSE_API_KEY }}
|
|
40
|
+
SEQPULSE_METRICS_ENDPOINT: ${{ secrets.SEQPULSE_METRICS_ENDPOINT }}
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
|
|
45
|
+
- uses: actions/setup-node@v4
|
|
46
|
+
with:
|
|
47
|
+
node-version: 20
|
|
48
|
+
cache: npm
|
|
49
|
+
|
|
50
|
+
- name: Install
|
|
51
|
+
run: npm ci
|
|
52
|
+
|
|
53
|
+
- name: SeqPulse Trigger
|
|
54
|
+
id: seqpulse_trigger
|
|
55
|
+
run: |
|
|
56
|
+
DEPLOYMENT_ID="$(npx -y @nassir_gouomba/seqpulse@0.5.0 ci trigger \
|
|
57
|
+
--env prod \
|
|
58
|
+
--branch "${GITHUB_REF_NAME}" \
|
|
59
|
+
--non-blocking true \
|
|
60
|
+
--output deploymentId)"
|
|
61
|
+
echo "deployment_id=${DEPLOYMENT_ID}" >> "$GITHUB_OUTPUT"
|
|
62
|
+
|
|
63
|
+
- name: Deploy
|
|
64
|
+
run: ./deploy.sh
|
|
65
|
+
|
|
66
|
+
- name: SeqPulse Finish
|
|
67
|
+
if: ${{ always() }}
|
|
68
|
+
run: |
|
|
69
|
+
npx -y @nassir_gouomba/seqpulse@0.5.0 ci finish \
|
|
70
|
+
--deployment-id "${{ steps.seqpulse_trigger.outputs.deployment_id }}" \
|
|
71
|
+
--job-status "${{ job.status }}" \
|
|
72
|
+
--non-blocking true
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## GitLab CI
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
deploy_prod:
|
|
79
|
+
image: node:20
|
|
80
|
+
stage: deploy
|
|
81
|
+
script:
|
|
82
|
+
- npm ci
|
|
83
|
+
- |
|
|
84
|
+
DEPLOYMENT_ID="$(npx -y @nassir_gouomba/seqpulse@0.5.0 ci trigger \
|
|
85
|
+
--env prod \
|
|
86
|
+
--branch "${CI_COMMIT_REF_NAME}" \
|
|
87
|
+
--non-blocking true \
|
|
88
|
+
--output deploymentId)"
|
|
89
|
+
printf 'SEQPULSE_DEPLOYMENT_ID=%s\n' "$DEPLOYMENT_ID" > .seqpulse.env
|
|
90
|
+
- ./deploy.sh
|
|
91
|
+
after_script:
|
|
92
|
+
- . ./.seqpulse.env 2>/dev/null || true
|
|
93
|
+
- |
|
|
94
|
+
npx -y @nassir_gouomba/seqpulse@0.5.0 ci finish \
|
|
95
|
+
--deployment-id "${SEQPULSE_DEPLOYMENT_ID}" \
|
|
96
|
+
--job-status "${CI_JOB_STATUS}" \
|
|
97
|
+
--non-blocking true
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## CircleCI
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
version: 2.1
|
|
104
|
+
|
|
105
|
+
jobs:
|
|
106
|
+
deploy:
|
|
107
|
+
docker:
|
|
108
|
+
- image: cimg/node:20.11
|
|
109
|
+
steps:
|
|
110
|
+
- checkout
|
|
111
|
+
|
|
112
|
+
- run:
|
|
113
|
+
name: Install
|
|
114
|
+
command: npm ci
|
|
115
|
+
|
|
116
|
+
- run:
|
|
117
|
+
name: SeqPulse Trigger
|
|
118
|
+
command: |
|
|
119
|
+
DEPLOYMENT_ID="$(npx -y @nassir_gouomba/seqpulse@0.5.0 ci trigger \
|
|
120
|
+
--env prod \
|
|
121
|
+
--branch "${CIRCLE_BRANCH}" \
|
|
122
|
+
--non-blocking true \
|
|
123
|
+
--output deploymentId)"
|
|
124
|
+
echo "export SEQPULSE_DEPLOYMENT_ID=${DEPLOYMENT_ID}" >> "$BASH_ENV"
|
|
125
|
+
|
|
126
|
+
- run:
|
|
127
|
+
name: Deploy
|
|
128
|
+
command: |
|
|
129
|
+
set +e
|
|
130
|
+
./deploy.sh
|
|
131
|
+
DEPLOY_EXIT_CODE=$?
|
|
132
|
+
if [ "$DEPLOY_EXIT_CODE" -eq 0 ]; then
|
|
133
|
+
echo 'export SEQPULSE_JOB_STATUS=success' >> "$BASH_ENV"
|
|
134
|
+
else
|
|
135
|
+
echo 'export SEQPULSE_JOB_STATUS=failed' >> "$BASH_ENV"
|
|
136
|
+
fi
|
|
137
|
+
exit "$DEPLOY_EXIT_CODE"
|
|
138
|
+
|
|
139
|
+
- run:
|
|
140
|
+
name: SeqPulse Finish
|
|
141
|
+
when: always
|
|
142
|
+
command: |
|
|
143
|
+
. "$BASH_ENV"
|
|
144
|
+
npx -y @nassir_gouomba/seqpulse@0.5.0 ci finish \
|
|
145
|
+
--deployment-id "${SEQPULSE_DEPLOYMENT_ID}" \
|
|
146
|
+
--job-status "${SEQPULSE_JOB_STATUS:-failed}" \
|
|
147
|
+
--non-blocking true
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Jenkins
|
|
151
|
+
|
|
152
|
+
```groovy
|
|
153
|
+
pipeline {
|
|
154
|
+
agent any
|
|
155
|
+
|
|
156
|
+
options {
|
|
157
|
+
disableConcurrentBuilds()
|
|
158
|
+
timestamps()
|
|
159
|
+
timeout(time: 20, unit: 'MINUTES')
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
environment {
|
|
163
|
+
SEQPULSE_BASE_URL = credentials('seqpulse_base_url')
|
|
164
|
+
SEQPULSE_API_KEY = credentials('seqpulse_api_key')
|
|
165
|
+
SEQPULSE_METRICS_ENDPOINT = credentials('seqpulse_metrics_endpoint')
|
|
166
|
+
SEQPULSE_DEPLOYMENT_ID = ''
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
stages {
|
|
170
|
+
stage('Install') {
|
|
171
|
+
steps {
|
|
172
|
+
sh 'npm ci'
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
stage('SeqPulse Trigger') {
|
|
177
|
+
steps {
|
|
178
|
+
script {
|
|
179
|
+
def branch = env.CHANGE_BRANCH ?: env.BRANCH_NAME ?: env.GIT_BRANCH ?: 'main'
|
|
180
|
+
env.SEQPULSE_DEPLOYMENT_ID = sh(
|
|
181
|
+
script: """
|
|
182
|
+
npx -y @nassir_gouomba/seqpulse@0.5.0 ci trigger \
|
|
183
|
+
--env prod \
|
|
184
|
+
--branch "${branch}" \
|
|
185
|
+
--non-blocking true \
|
|
186
|
+
--output deploymentId
|
|
187
|
+
""",
|
|
188
|
+
returnStdout: true
|
|
189
|
+
).trim()
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
stage('Deploy') {
|
|
195
|
+
steps {
|
|
196
|
+
sh './deploy.sh'
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
post {
|
|
202
|
+
always {
|
|
203
|
+
script {
|
|
204
|
+
def jobStatus = (currentBuild.currentResult ?: 'SUCCESS').toLowerCase()
|
|
205
|
+
sh """
|
|
206
|
+
npx -y @nassir_gouomba/seqpulse@0.5.0 ci finish \
|
|
207
|
+
--deployment-id "${env.SEQPULSE_DEPLOYMENT_ID ?: ''}" \
|
|
208
|
+
--job-status "${jobStatus}" \
|
|
209
|
+
--non-blocking true
|
|
210
|
+
"""
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Notes pratiques
|
|
218
|
+
|
|
219
|
+
- Si le package est deja installe dans le projet, vous pouvez remplacer `npx -y @nassir_gouomba/seqpulse@0.5.0` par `npx seqpulse`.
|
|
220
|
+
- Pour les deploys `prod`, ajoutez un gate explicite sur `main`/tag si votre pipeline est multi-branches.
|
|
221
|
+
- Le pattern recommande est toujours le meme: `trigger -> deploy -> finish`.
|
package/README.md
CHANGED
|
@@ -3,21 +3,21 @@
|
|
|
3
3
|
SeqPulse Node SDK couvre deux usages:
|
|
4
4
|
|
|
5
5
|
- Runtime application: instrumentation HTTP + endpoint metrics + validation HMAC v2
|
|
6
|
-
- CI/CD integration: client `trigger/finish`
|
|
6
|
+
- CI/CD integration: client `trigger/finish` + CLI `seqpulse ci ...`
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
npm install seqpulse
|
|
11
|
+
npm install @nassir_gouomba/seqpulse
|
|
12
12
|
# or
|
|
13
|
-
pnpm add seqpulse
|
|
13
|
+
pnpm add @nassir_gouomba/seqpulse
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Runtime (Express)
|
|
17
17
|
|
|
18
18
|
```js
|
|
19
19
|
const express = require("express");
|
|
20
|
-
const seqpulse = require("seqpulse");
|
|
20
|
+
const seqpulse = require("@nassir_gouomba/seqpulse");
|
|
21
21
|
|
|
22
22
|
const app = express();
|
|
23
23
|
|
|
@@ -53,7 +53,7 @@ app.listen(3000, () => {
|
|
|
53
53
|
## CI/CD client (trigger/finish)
|
|
54
54
|
|
|
55
55
|
```js
|
|
56
|
-
const seqpulse = require("seqpulse");
|
|
56
|
+
const seqpulse = require("@nassir_gouomba/seqpulse");
|
|
57
57
|
|
|
58
58
|
const client = seqpulse.createCIClient({
|
|
59
59
|
baseUrl: process.env.SEQPULSE_BASE_URL,
|
|
@@ -66,7 +66,7 @@ const client = seqpulse.createCIClient({
|
|
|
66
66
|
async function runDeployment() {
|
|
67
67
|
const trigger = await client.trigger({
|
|
68
68
|
branch: process.env.GITHUB_REF_NAME,
|
|
69
|
-
idempotencyKey:
|
|
69
|
+
idempotencyKey: seqpulse.buildCiIdempotencyKey(),
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
// Deploy your app here...
|
|
@@ -81,11 +81,30 @@ async function runDeployment() {
|
|
|
81
81
|
}
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
## CI/CD CLI (short YAML)
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
-
|
|
86
|
+
```bash
|
|
87
|
+
# Trigger
|
|
88
|
+
DEPLOYMENT_ID="$(npx -y @nassir_gouomba/seqpulse@0.5.0 ci trigger \
|
|
89
|
+
--env prod \
|
|
90
|
+
--output deploymentId)"
|
|
91
|
+
|
|
92
|
+
# Finish
|
|
93
|
+
npx -y @nassir_gouomba/seqpulse@0.5.0 ci finish \
|
|
94
|
+
--deployment-id "$DEPLOYMENT_ID" \
|
|
95
|
+
--job-status "$JOB_STATUS"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Notes:
|
|
99
|
+
|
|
100
|
+
- `--output deploymentId` permet de capturer directement l'identifiant de deployment.
|
|
101
|
+
- `--github-output` ecrit `deployment_id`, `status`, `http_status`.
|
|
102
|
+
- mode par defaut: non-bloquant (`--non-blocking true`).
|
|
103
|
+
- pour mode strict: `--blocking`.
|
|
104
|
+
|
|
105
|
+
## Documentation
|
|
106
|
+
|
|
107
|
+
- [Multi-platform CI/CD snippets](./CI_CD_SNIPPETS_MULTI-PLATFORM.md)
|
|
89
108
|
|
|
90
109
|
## Compatibility note
|
|
91
110
|
|
|
@@ -93,7 +112,7 @@ Cette evolution **n'ecrase pas** le SDK runtime actuel:
|
|
|
93
112
|
|
|
94
113
|
- l'endpoint `/seqpulse-metrics` reste le meme
|
|
95
114
|
- la logique HMAC runtime reste la meme
|
|
96
|
-
-
|
|
115
|
+
- la CLI CI est une surcouche du client SDK existant
|
|
97
116
|
|
|
98
117
|
## Local smoke test
|
|
99
118
|
|
package/bin/seqpulse.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const seqpulse = require("../index.js");
|
|
6
|
+
|
|
7
|
+
function printUsage() {
|
|
8
|
+
console.error(`Usage:
|
|
9
|
+
seqpulse ci trigger [options]
|
|
10
|
+
seqpulse ci finish [options]
|
|
11
|
+
|
|
12
|
+
Commands:
|
|
13
|
+
ci trigger Trigger SeqPulse deployment in CI
|
|
14
|
+
ci finish Finish SeqPulse deployment in CI
|
|
15
|
+
|
|
16
|
+
Common options:
|
|
17
|
+
--base-url <url>
|
|
18
|
+
--api-key <key>
|
|
19
|
+
--metrics-endpoint <url>
|
|
20
|
+
--timeout-ms <number>
|
|
21
|
+
--env <name> (default: prod)
|
|
22
|
+
--non-blocking <true|false> (default: true)
|
|
23
|
+
--blocking (equivalent to --non-blocking false)
|
|
24
|
+
--output <field> (default: json)
|
|
25
|
+
--github-output <path> (writes outputs for GitHub Actions)
|
|
26
|
+
|
|
27
|
+
Trigger options:
|
|
28
|
+
--branch <name>
|
|
29
|
+
--idempotency-key <key>
|
|
30
|
+
|
|
31
|
+
Finish options:
|
|
32
|
+
--deployment-id <id>
|
|
33
|
+
--result <success|failed>
|
|
34
|
+
--job-status <status>
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseArgs(argv) {
|
|
39
|
+
const positional = [];
|
|
40
|
+
const options = {};
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
43
|
+
const token = argv[i];
|
|
44
|
+
if (!token.startsWith("--")) {
|
|
45
|
+
positional.push(token);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const eq = token.indexOf("=");
|
|
50
|
+
if (eq > -1) {
|
|
51
|
+
const key = token.slice(2, eq);
|
|
52
|
+
const value = token.slice(eq + 1);
|
|
53
|
+
options[key] = value;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const key = token.slice(2);
|
|
58
|
+
const next = argv[i + 1];
|
|
59
|
+
if (!next || next.startsWith("--")) {
|
|
60
|
+
options[key] = true;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
options[key] = next;
|
|
65
|
+
i += 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { positional, options };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function parseBoolean(value, defaultValue) {
|
|
72
|
+
if (value === undefined) return defaultValue;
|
|
73
|
+
if (typeof value === "boolean") return value;
|
|
74
|
+
const normalized = String(value).trim().toLowerCase();
|
|
75
|
+
if (["1", "true", "yes", "y", "on"].includes(normalized)) return true;
|
|
76
|
+
if (["0", "false", "no", "n", "off"].includes(normalized)) return false;
|
|
77
|
+
throw new Error(`Invalid boolean value: ${value}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function parseNumber(value, defaultValue) {
|
|
81
|
+
if (value === undefined) return defaultValue;
|
|
82
|
+
const num = Number(value);
|
|
83
|
+
if (!Number.isFinite(num) || num <= 0) {
|
|
84
|
+
throw new Error(`Invalid numeric value: ${value}`);
|
|
85
|
+
}
|
|
86
|
+
return num;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function sanitizeOutput(value) {
|
|
90
|
+
return String(value === undefined || value === null ? "" : value).replace(/[\r\n]/g, "");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function appendGithubOutput(filePath, pairs) {
|
|
94
|
+
if (!filePath) return;
|
|
95
|
+
const lines = Object.entries(pairs)
|
|
96
|
+
.map(([k, v]) => `${k}=${sanitizeOutput(v)}`)
|
|
97
|
+
.join("\n");
|
|
98
|
+
fs.appendFileSync(filePath, `${lines}\n`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function resolveOutputValue(result, output) {
|
|
102
|
+
const mode = String(output || "json").trim();
|
|
103
|
+
if (!mode || mode === "json") {
|
|
104
|
+
return JSON.stringify(result);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const aliases = {
|
|
108
|
+
deployment_id: "deploymentId",
|
|
109
|
+
http_status: "httpStatus",
|
|
110
|
+
};
|
|
111
|
+
const path = (aliases[mode] || mode).split(".");
|
|
112
|
+
|
|
113
|
+
let current = result;
|
|
114
|
+
for (const segment of path) {
|
|
115
|
+
if (current === undefined || current === null) {
|
|
116
|
+
current = "";
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
current = current[segment];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (current === undefined || current === null) {
|
|
123
|
+
return "";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (typeof current === "object") {
|
|
127
|
+
return JSON.stringify(current);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return String(current);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function printResult(result, output) {
|
|
134
|
+
console.log(sanitizeOutput(resolveOutputValue(result, output)));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function resolveNonBlocking(options) {
|
|
138
|
+
if (options.blocking !== undefined) return false;
|
|
139
|
+
if (options["non-blocking"] !== undefined) return parseBoolean(options["non-blocking"], true);
|
|
140
|
+
if (options.nonblocking !== undefined) return parseBoolean(options.nonblocking, true);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function buildClient(options) {
|
|
145
|
+
return {
|
|
146
|
+
baseUrl: options["base-url"],
|
|
147
|
+
apiKey: options["api-key"],
|
|
148
|
+
metricsEndpoint: options["metrics-endpoint"],
|
|
149
|
+
env: options.env || "prod",
|
|
150
|
+
timeoutMs: parseNumber(options["timeout-ms"], undefined),
|
|
151
|
+
nonBlocking: resolveNonBlocking(options),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function runTrigger(options) {
|
|
156
|
+
const clientConfig = buildClient(options);
|
|
157
|
+
const client = seqpulse.createCIClient(clientConfig);
|
|
158
|
+
const result = await client.trigger({
|
|
159
|
+
env: options.env || clientConfig.env || "prod",
|
|
160
|
+
branch: options.branch,
|
|
161
|
+
idempotencyKey: options["idempotency-key"] || seqpulse.buildCiIdempotencyKey(),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
appendGithubOutput(options["github-output"], {
|
|
165
|
+
deployment_id: result.ok ? result.deploymentId || "" : "",
|
|
166
|
+
status: result.status || result.error || "",
|
|
167
|
+
http_status: result.httpStatus || "",
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
printResult({ action: "trigger", ...result }, options.output);
|
|
171
|
+
|
|
172
|
+
if (!result.ok && !clientConfig.nonBlocking) {
|
|
173
|
+
process.exitCode = 1;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function runFinish(options) {
|
|
178
|
+
const clientConfig = buildClient(options);
|
|
179
|
+
const deploymentId = options["deployment-id"] || process.env.SEQPULSE_DEPLOYMENT_ID || "";
|
|
180
|
+
const jobStatus =
|
|
181
|
+
options["job-status"] ||
|
|
182
|
+
process.env.JOB_STATUS ||
|
|
183
|
+
process.env.CI_JOB_STATUS ||
|
|
184
|
+
process.env.BUILD_RESULT ||
|
|
185
|
+
"success";
|
|
186
|
+
const resultValue = options.result || seqpulse.inferResultFromPipelineStatus(jobStatus);
|
|
187
|
+
|
|
188
|
+
const client = seqpulse.createCIClient(clientConfig);
|
|
189
|
+
const result = await client.finish({
|
|
190
|
+
deploymentId,
|
|
191
|
+
result: resultValue,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
appendGithubOutput(options["github-output"], {
|
|
195
|
+
status: result.status || result.error || "",
|
|
196
|
+
http_status: result.httpStatus || "",
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
printResult({ action: "finish", ...result }, options.output);
|
|
200
|
+
|
|
201
|
+
if (!result.ok && !clientConfig.nonBlocking) {
|
|
202
|
+
process.exitCode = 1;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function main() {
|
|
207
|
+
const { positional, options } = parseArgs(process.argv.slice(2));
|
|
208
|
+
const [scope, command] = positional;
|
|
209
|
+
|
|
210
|
+
if (options.help || options.h) {
|
|
211
|
+
printUsage();
|
|
212
|
+
process.exit(0);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (!scope || !command) {
|
|
217
|
+
printUsage();
|
|
218
|
+
process.exit(1);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (scope !== "ci") {
|
|
223
|
+
throw new Error(`Unsupported scope: ${scope}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (command === "trigger") {
|
|
227
|
+
await runTrigger(options);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (command === "finish") {
|
|
232
|
+
await runFinish(options);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
throw new Error(`Unsupported command: ${command}`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
main().catch((error) => {
|
|
240
|
+
console.error(`[seqpulse] ${error && error.message ? error.message : String(error)}`);
|
|
241
|
+
process.exit(1);
|
|
242
|
+
});
|
package/index.js
CHANGED
|
@@ -228,9 +228,11 @@ function buildCiIdempotencyKey() {
|
|
|
228
228
|
|
|
229
229
|
function inferBranchName() {
|
|
230
230
|
return (
|
|
231
|
+
process.env.CHANGE_BRANCH ||
|
|
231
232
|
process.env.GITHUB_REF_NAME ||
|
|
232
233
|
process.env.CI_COMMIT_REF_NAME ||
|
|
233
234
|
process.env.CIRCLE_BRANCH ||
|
|
235
|
+
process.env.GIT_BRANCH ||
|
|
234
236
|
process.env.BRANCH_NAME ||
|
|
235
237
|
"unknown"
|
|
236
238
|
);
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seqpulse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "SeqPulse SDK for metrics endpoint instrumentation and HMAC validation",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"seqpulse": "bin/seqpulse.js"
|
|
9
|
+
},
|
|
7
10
|
"exports": {
|
|
8
11
|
".": {
|
|
9
12
|
"require": "./index.js",
|
|
@@ -13,7 +16,9 @@
|
|
|
13
16
|
"files": [
|
|
14
17
|
"index.js",
|
|
15
18
|
"index.d.ts",
|
|
19
|
+
"bin/seqpulse.js",
|
|
16
20
|
"README.md",
|
|
21
|
+
"CI_CD_SNIPPETS_MULTI-PLATFORM.md",
|
|
17
22
|
"LICENSE",
|
|
18
23
|
"scripts/smoke.js"
|
|
19
24
|
],
|