@invarn/cibuild 1.3.16 → 1.3.18
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/dist/cli.cjs +1 -1
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +987 -0
- package/dist/src/commands/android-scanner.d.ts +32 -0
- package/dist/src/commands/android-scanner.d.ts.map +1 -0
- package/dist/src/commands/android-scanner.js +667 -0
- package/dist/src/commands/build.d.ts +5 -0
- package/dist/src/commands/build.d.ts.map +1 -0
- package/dist/src/commands/build.js +1096 -0
- package/dist/src/commands/edit.d.ts +3 -0
- package/dist/src/commands/edit.d.ts.map +1 -0
- package/dist/src/commands/edit.js +651 -0
- package/dist/src/commands/file-secret-collector.d.ts +37 -0
- package/dist/src/commands/file-secret-collector.d.ts.map +1 -0
- package/dist/src/commands/file-secret-collector.js +199 -0
- package/dist/src/commands/github-workflow.d.ts +5 -0
- package/dist/src/commands/github-workflow.d.ts.map +1 -0
- package/dist/src/commands/github-workflow.js +45 -0
- package/dist/src/commands/ios-scanner.d.ts +27 -0
- package/dist/src/commands/ios-scanner.d.ts.map +1 -0
- package/dist/src/commands/ios-scanner.js +337 -0
- package/dist/src/commands/reset.d.ts +7 -0
- package/dist/src/commands/reset.d.ts.map +1 -0
- package/dist/src/commands/reset.js +81 -0
- package/dist/src/commands/secrets-sync-workflow.d.ts +15 -0
- package/dist/src/commands/secrets-sync-workflow.d.ts.map +1 -0
- package/dist/src/commands/secrets-sync-workflow.js +255 -0
- package/dist/src/commands/secrets-upload.d.ts +21 -0
- package/dist/src/commands/secrets-upload.d.ts.map +1 -0
- package/dist/src/commands/secrets-upload.js +177 -0
- package/dist/src/commands/secrets-upload.test.d.ts +5 -0
- package/dist/src/commands/secrets-upload.test.d.ts.map +1 -0
- package/dist/src/commands/secrets-upload.test.js +60 -0
- package/dist/src/config.d.ts +3 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +47 -0
- package/dist/src/envman/cli.d.ts +21 -0
- package/dist/src/envman/cli.d.ts.map +1 -0
- package/dist/src/envman/cli.js +240 -0
- package/dist/src/envman/envman.d.ts +83 -0
- package/dist/src/envman/envman.d.ts.map +1 -0
- package/dist/src/envman/envman.js +361 -0
- package/dist/src/envman/envman.test.d.ts +5 -0
- package/dist/src/envman/envman.test.d.ts.map +1 -0
- package/dist/src/envman/envman.test.js +236 -0
- package/dist/src/envman/index.d.ts +23 -0
- package/dist/src/envman/index.d.ts.map +1 -0
- package/dist/src/envman/index.js +23 -0
- package/dist/src/envman/types.d.ts +55 -0
- package/dist/src/envman/types.d.ts.map +1 -0
- package/dist/src/envman/types.js +12 -0
- package/dist/src/lib.d.ts +27 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +32 -0
- package/dist/src/pipeline.d.ts +3 -0
- package/dist/src/pipeline.d.ts.map +1 -0
- package/dist/src/pipeline.js +57 -0
- package/dist/src/runner.d.ts +17 -0
- package/dist/src/runner.d.ts.map +1 -0
- package/dist/src/runner.js +234 -0
- package/dist/src/types.d.ts +58 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/yaml/bitrise-compat.d.ts +65 -0
- package/dist/src/yaml/bitrise-compat.d.ts.map +1 -0
- package/dist/src/yaml/bitrise-compat.js +206 -0
- package/dist/src/yaml/bitrise-compat.test.d.ts +5 -0
- package/dist/src/yaml/bitrise-compat.test.d.ts.map +1 -0
- package/dist/src/yaml/bitrise-compat.test.js +347 -0
- package/dist/src/yaml/converter.d.ts +33 -0
- package/dist/src/yaml/converter.d.ts.map +1 -0
- package/dist/src/yaml/converter.js +222 -0
- package/dist/src/yaml/converter.test.d.ts +5 -0
- package/dist/src/yaml/converter.test.d.ts.map +1 -0
- package/dist/src/yaml/converter.test.js +348 -0
- package/dist/src/yaml/e2e.test.d.ts +6 -0
- package/dist/src/yaml/e2e.test.d.ts.map +1 -0
- package/dist/src/yaml/e2e.test.js +446 -0
- package/dist/src/yaml/env-resolver.d.ts +120 -0
- package/dist/src/yaml/env-resolver.d.ts.map +1 -0
- package/dist/src/yaml/env-resolver.js +405 -0
- package/dist/src/yaml/env-resolver.test.d.ts +5 -0
- package/dist/src/yaml/env-resolver.test.d.ts.map +1 -0
- package/dist/src/yaml/env-resolver.test.js +502 -0
- package/dist/src/yaml/interactive-prompts.d.ts +71 -0
- package/dist/src/yaml/interactive-prompts.d.ts.map +1 -0
- package/dist/src/yaml/interactive-prompts.js +258 -0
- package/dist/src/yaml/missing-env-handler.d.ts +45 -0
- package/dist/src/yaml/missing-env-handler.d.ts.map +1 -0
- package/dist/src/yaml/missing-env-handler.js +64 -0
- package/dist/src/yaml/parser.d.ts +33 -0
- package/dist/src/yaml/parser.d.ts.map +1 -0
- package/dist/src/yaml/parser.js +145 -0
- package/dist/src/yaml/pipeline-with-secrets.d.ts +25 -0
- package/dist/src/yaml/pipeline-with-secrets.d.ts.map +1 -0
- package/dist/src/yaml/pipeline-with-secrets.js +76 -0
- package/dist/src/yaml/platform-detector.d.ts +83 -0
- package/dist/src/yaml/platform-detector.d.ts.map +1 -0
- package/dist/src/yaml/platform-detector.js +188 -0
- package/dist/src/yaml/platform-detector.test.d.ts +5 -0
- package/dist/src/yaml/platform-detector.test.d.ts.map +1 -0
- package/dist/src/yaml/platform-detector.test.js +414 -0
- package/dist/src/yaml/preflight-validation.d.ts +40 -0
- package/dist/src/yaml/preflight-validation.d.ts.map +1 -0
- package/dist/src/yaml/preflight-validation.js +152 -0
- package/dist/src/yaml/secrets-manager.d.ts +77 -0
- package/dist/src/yaml/secrets-manager.d.ts.map +1 -0
- package/dist/src/yaml/secrets-manager.js +219 -0
- package/dist/src/yaml/step-validator.d.ts +54 -0
- package/dist/src/yaml/step-validator.d.ts.map +1 -0
- package/dist/src/yaml/step-validator.js +403 -0
- package/dist/src/yaml/steps/android-sign.d.ts +35 -0
- package/dist/src/yaml/steps/android-sign.d.ts.map +1 -0
- package/dist/src/yaml/steps/android-sign.js +147 -0
- package/dist/src/yaml/steps/android-version.d.ts +26 -0
- package/dist/src/yaml/steps/android-version.d.ts.map +1 -0
- package/dist/src/yaml/steps/android-version.js +128 -0
- package/dist/src/yaml/steps/android-version.test.d.ts +5 -0
- package/dist/src/yaml/steps/android-version.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/android-version.test.js +196 -0
- package/dist/src/yaml/steps/android.d.ts +95 -0
- package/dist/src/yaml/steps/android.d.ts.map +1 -0
- package/dist/src/yaml/steps/android.js +916 -0
- package/dist/src/yaml/steps/app-store-deploy.d.ts +48 -0
- package/dist/src/yaml/steps/app-store-deploy.d.ts.map +1 -0
- package/dist/src/yaml/steps/app-store-deploy.js +162 -0
- package/dist/src/yaml/steps/base.d.ts +238 -0
- package/dist/src/yaml/steps/base.d.ts.map +1 -0
- package/dist/src/yaml/steps/base.js +345 -0
- package/dist/src/yaml/steps/bitrise-android-tools.d.ts +26 -0
- package/dist/src/yaml/steps/bitrise-android-tools.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-android-tools.js +198 -0
- package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-android-tools.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-android-tools.test.js +280 -0
- package/dist/src/yaml/steps/bitrise-apk-info.d.ts +22 -0
- package/dist/src/yaml/steps/bitrise-apk-info.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-apk-info.js +144 -0
- package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-apk-info.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-apk-info.test.js +331 -0
- package/dist/src/yaml/steps/bitrise-slack.d.ts +49 -0
- package/dist/src/yaml/steps/bitrise-slack.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-slack.js +280 -0
- package/dist/src/yaml/steps/bitrise-slack.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-slack.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-slack.test.js +484 -0
- package/dist/src/yaml/steps/bitrise-ssh.d.ts +27 -0
- package/dist/src/yaml/steps/bitrise-ssh.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-ssh.js +134 -0
- package/dist/src/yaml/steps/bitrise-ssh.test.d.ts +5 -0
- package/dist/src/yaml/steps/bitrise-ssh.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/bitrise-ssh.test.js +205 -0
- package/dist/src/yaml/steps/cache.d.ts +52 -0
- package/dist/src/yaml/steps/cache.d.ts.map +1 -0
- package/dist/src/yaml/steps/cache.js +352 -0
- package/dist/src/yaml/steps/fastlane.d.ts +27 -0
- package/dist/src/yaml/steps/fastlane.d.ts.map +1 -0
- package/dist/src/yaml/steps/fastlane.js +79 -0
- package/dist/src/yaml/steps/file.d.ts +27 -0
- package/dist/src/yaml/steps/file.d.ts.map +1 -0
- package/dist/src/yaml/steps/file.js +35 -0
- package/dist/src/yaml/steps/flutter.d.ts +63 -0
- package/dist/src/yaml/steps/flutter.d.ts.map +1 -0
- package/dist/src/yaml/steps/flutter.js +215 -0
- package/dist/src/yaml/steps/git-clone.d.ts +26 -0
- package/dist/src/yaml/steps/git-clone.d.ts.map +1 -0
- package/dist/src/yaml/steps/git-clone.js +111 -0
- package/dist/src/yaml/steps/google-play-deploy.d.ts +37 -0
- package/dist/src/yaml/steps/google-play-deploy.d.ts.map +1 -0
- package/dist/src/yaml/steps/google-play-deploy.js +193 -0
- package/dist/src/yaml/steps/google-play-deploy.test.d.ts +5 -0
- package/dist/src/yaml/steps/google-play-deploy.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/google-play-deploy.test.js +310 -0
- package/dist/src/yaml/steps/index.d.ts +10 -0
- package/dist/src/yaml/steps/index.d.ts.map +1 -0
- package/dist/src/yaml/steps/index.js +1361 -0
- package/dist/src/yaml/steps/ios-deps.d.ts +43 -0
- package/dist/src/yaml/steps/ios-deps.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-deps.js +141 -0
- package/dist/src/yaml/steps/ios-deps.test.d.ts +5 -0
- package/dist/src/yaml/steps/ios-deps.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-deps.test.js +90 -0
- package/dist/src/yaml/steps/ios-signing.d.ts +31 -0
- package/dist/src/yaml/steps/ios-signing.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-signing.js +144 -0
- package/dist/src/yaml/steps/ios-version.d.ts +47 -0
- package/dist/src/yaml/steps/ios-version.d.ts.map +1 -0
- package/dist/src/yaml/steps/ios-version.js +151 -0
- package/dist/src/yaml/steps/linting.d.ts +47 -0
- package/dist/src/yaml/steps/linting.d.ts.map +1 -0
- package/dist/src/yaml/steps/linting.js +148 -0
- package/dist/src/yaml/steps/phase2.test.d.ts +6 -0
- package/dist/src/yaml/steps/phase2.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase2.test.js +197 -0
- package/dist/src/yaml/steps/phase3.test.d.ts +5 -0
- package/dist/src/yaml/steps/phase3.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase3.test.js +144 -0
- package/dist/src/yaml/steps/phase4.test.d.ts +5 -0
- package/dist/src/yaml/steps/phase4.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase4.test.js +166 -0
- package/dist/src/yaml/steps/phase5.test.d.ts +6 -0
- package/dist/src/yaml/steps/phase5.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/phase5.test.js +263 -0
- package/dist/src/yaml/steps/registry.d.ts +88 -0
- package/dist/src/yaml/steps/registry.d.ts.map +1 -0
- package/dist/src/yaml/steps/registry.js +125 -0
- package/dist/src/yaml/steps/registry.test.d.ts +5 -0
- package/dist/src/yaml/steps/registry.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/registry.test.js +235 -0
- package/dist/src/yaml/steps/release.d.ts +50 -0
- package/dist/src/yaml/steps/release.d.ts.map +1 -0
- package/dist/src/yaml/steps/release.js +154 -0
- package/dist/src/yaml/steps/script.d.ts +23 -0
- package/dist/src/yaml/steps/script.d.ts.map +1 -0
- package/dist/src/yaml/steps/script.js +63 -0
- package/dist/src/yaml/steps/spec-validation.test.d.ts +6 -0
- package/dist/src/yaml/steps/spec-validation.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/spec-validation.test.js +130 -0
- package/dist/src/yaml/steps/steps.test.d.ts +6 -0
- package/dist/src/yaml/steps/steps.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/steps.test.js +505 -0
- package/dist/src/yaml/steps/test-config.d.ts +3 -0
- package/dist/src/yaml/steps/test-config.d.ts.map +1 -0
- package/dist/src/yaml/steps/test-config.js +17 -0
- package/dist/src/yaml/steps/xcode-new.test.d.ts +5 -0
- package/dist/src/yaml/steps/xcode-new.test.d.ts.map +1 -0
- package/dist/src/yaml/steps/xcode-new.test.js +211 -0
- package/dist/src/yaml/steps/xcode.d.ts +222 -0
- package/dist/src/yaml/steps/xcode.d.ts.map +1 -0
- package/dist/src/yaml/steps/xcode.js +999 -0
- package/dist/src/yaml/types.d.ts +68 -0
- package/dist/src/yaml/types.d.ts.map +1 -0
- package/dist/src/yaml/types.js +5 -0
- package/dist/src/yaml/validation-types.d.ts +96 -0
- package/dist/src/yaml/validation-types.d.ts.map +1 -0
- package/dist/src/yaml/validation-types.js +8 -0
- package/dist/src/yaml/yaml-updater.d.ts +24 -0
- package/dist/src/yaml/yaml-updater.d.ts.map +1 -0
- package/dist/src/yaml/yaml-updater.js +128 -0
- package/package.json +16 -4
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI Build Environment Variable Manager (envman)
|
|
3
|
+
*
|
|
4
|
+
* A tool for managing environment variables between CI/CD pipeline steps.
|
|
5
|
+
* Similar to Bitrise's envman, this allows scripts to register outputs
|
|
6
|
+
* that subsequent steps can use as environment variables.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* envman add --key KEY --value 'value'
|
|
10
|
+
* envman add --key KEY --valuefile /path/to/file
|
|
11
|
+
* echo "value" | envman add --key KEY
|
|
12
|
+
* envman run <command>
|
|
13
|
+
* envman print [--format json|export]
|
|
14
|
+
* envman clear
|
|
15
|
+
*/
|
|
16
|
+
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'node:fs';
|
|
17
|
+
import { spawn } from 'node:child_process';
|
|
18
|
+
import { resolve } from 'node:path';
|
|
19
|
+
import { DEFAULT_STORE_FILE, STORE_VERSION } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Get the path to the envstore file
|
|
22
|
+
* Uses ENVMAN_ENVSTORE_PATH env var if set, otherwise defaults to .envstore.json in cwd
|
|
23
|
+
*/
|
|
24
|
+
export function getStorePath() {
|
|
25
|
+
return process.env.ENVMAN_ENVSTORE_PATH || resolve(process.cwd(), DEFAULT_STORE_FILE);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Load the environment store from disk
|
|
29
|
+
* Returns an empty store if file doesn't exist
|
|
30
|
+
*/
|
|
31
|
+
export function loadStore(storePath) {
|
|
32
|
+
const path = storePath || getStorePath();
|
|
33
|
+
if (!existsSync(path)) {
|
|
34
|
+
return createEmptyStore();
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const content = readFileSync(path, 'utf-8');
|
|
38
|
+
const store = JSON.parse(content);
|
|
39
|
+
// Validate store structure
|
|
40
|
+
if (!store.version || !Array.isArray(store.envs)) {
|
|
41
|
+
console.error('Warning: Invalid envstore format, creating new store');
|
|
42
|
+
return createEmptyStore();
|
|
43
|
+
}
|
|
44
|
+
return store;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error(`Warning: Failed to read envstore at ${path}, creating new store`);
|
|
48
|
+
return createEmptyStore();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Save the environment store to disk
|
|
53
|
+
*/
|
|
54
|
+
export function saveStore(store, storePath) {
|
|
55
|
+
const path = storePath || getStorePath();
|
|
56
|
+
writeFileSync(path, JSON.stringify(store, null, 2), 'utf-8');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Create an empty environment store
|
|
60
|
+
*/
|
|
61
|
+
export function createEmptyStore() {
|
|
62
|
+
return {
|
|
63
|
+
version: STORE_VERSION,
|
|
64
|
+
envs: [],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Initialize a new envstore file
|
|
69
|
+
* Creates an empty store at the specified path (or default)
|
|
70
|
+
*/
|
|
71
|
+
export function init(storePath) {
|
|
72
|
+
const path = storePath || getStorePath();
|
|
73
|
+
if (existsSync(path)) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
error: `Envstore already exists at ${path}. Use 'clear' to reset.`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const store = createEmptyStore();
|
|
80
|
+
saveStore(store, path);
|
|
81
|
+
return {
|
|
82
|
+
success: true,
|
|
83
|
+
message: `Created envstore at ${path}`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Add an environment variable to the store
|
|
88
|
+
*/
|
|
89
|
+
export function add(options, storePath) {
|
|
90
|
+
const { key, value, valueFile, sensitive, skipIfEmpty, append } = options;
|
|
91
|
+
if (!key || key.trim() === '') {
|
|
92
|
+
return {
|
|
93
|
+
success: false,
|
|
94
|
+
error: 'Key is required',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Validate key format (must be valid env var name)
|
|
98
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
99
|
+
return {
|
|
100
|
+
success: false,
|
|
101
|
+
error: `Invalid key '${key}'. Must start with letter or underscore, contain only letters, numbers, and underscores.`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
let finalValue;
|
|
105
|
+
// Determine the value source
|
|
106
|
+
if (valueFile) {
|
|
107
|
+
// Read from file
|
|
108
|
+
if (!existsSync(valueFile)) {
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: `Value file not found: ${valueFile}`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
finalValue = readFileSync(valueFile, 'utf-8');
|
|
115
|
+
}
|
|
116
|
+
else if (value !== undefined) {
|
|
117
|
+
// Use provided value
|
|
118
|
+
finalValue = value;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: 'Either --value or --valuefile must be provided',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// Handle skip if empty
|
|
127
|
+
if (skipIfEmpty && finalValue.trim() === '') {
|
|
128
|
+
return {
|
|
129
|
+
success: true,
|
|
130
|
+
message: `Skipped empty value for key '${key}'`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// Load existing store
|
|
134
|
+
const store = loadStore(storePath);
|
|
135
|
+
const now = new Date().toISOString();
|
|
136
|
+
// Find existing entry
|
|
137
|
+
const existingIndex = store.envs.findIndex(e => e.key === key);
|
|
138
|
+
if (existingIndex >= 0) {
|
|
139
|
+
// Update existing entry
|
|
140
|
+
const existing = store.envs[existingIndex];
|
|
141
|
+
if (append) {
|
|
142
|
+
existing.value += finalValue;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
existing.value = finalValue;
|
|
146
|
+
}
|
|
147
|
+
existing.sensitive = sensitive ?? existing.sensitive;
|
|
148
|
+
existing.updatedAt = now;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Add new entry
|
|
152
|
+
const entry = {
|
|
153
|
+
key,
|
|
154
|
+
value: finalValue,
|
|
155
|
+
sensitive: sensitive ?? false,
|
|
156
|
+
createdAt: now,
|
|
157
|
+
updatedAt: now,
|
|
158
|
+
};
|
|
159
|
+
store.envs.push(entry);
|
|
160
|
+
}
|
|
161
|
+
// Save store
|
|
162
|
+
saveStore(store, storePath);
|
|
163
|
+
const displayValue = sensitive ? '[REDACTED]' : (finalValue.length > 50 ? finalValue.substring(0, 47) + '...' : finalValue);
|
|
164
|
+
return {
|
|
165
|
+
success: true,
|
|
166
|
+
message: `Added ${key}=${displayValue}`,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Add an environment variable from stdin
|
|
171
|
+
*/
|
|
172
|
+
export async function addFromStdin(key, sensitive, storePath) {
|
|
173
|
+
return new Promise((resolve) => {
|
|
174
|
+
let data = '';
|
|
175
|
+
process.stdin.setEncoding('utf-8');
|
|
176
|
+
process.stdin.on('data', (chunk) => {
|
|
177
|
+
data += chunk;
|
|
178
|
+
});
|
|
179
|
+
process.stdin.on('end', () => {
|
|
180
|
+
// Remove trailing newline (like envman does)
|
|
181
|
+
const value = data.replace(/\n$/, '');
|
|
182
|
+
const result = add({ key, value, sensitive }, storePath);
|
|
183
|
+
resolve(result);
|
|
184
|
+
});
|
|
185
|
+
process.stdin.on('error', (err) => {
|
|
186
|
+
resolve({
|
|
187
|
+
success: false,
|
|
188
|
+
error: `Failed to read from stdin: ${err.message}`,
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get all environment variables from the store as a Record
|
|
195
|
+
*/
|
|
196
|
+
export function getAll(storePath) {
|
|
197
|
+
const store = loadStore(storePath);
|
|
198
|
+
const result = {};
|
|
199
|
+
for (const entry of store.envs) {
|
|
200
|
+
result[entry.key] = entry.value;
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get a single environment variable from the store
|
|
206
|
+
*/
|
|
207
|
+
export function get(key, storePath) {
|
|
208
|
+
const store = loadStore(storePath);
|
|
209
|
+
const entry = store.envs.find(e => e.key === key);
|
|
210
|
+
return entry?.value;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Print environment variables in various formats
|
|
214
|
+
*/
|
|
215
|
+
export function print(format = 'table', storePath) {
|
|
216
|
+
const store = loadStore(storePath);
|
|
217
|
+
switch (format) {
|
|
218
|
+
case 'json':
|
|
219
|
+
return JSON.stringify(store.envs.map(e => ({
|
|
220
|
+
key: e.key,
|
|
221
|
+
value: e.sensitive ? '[REDACTED]' : e.value,
|
|
222
|
+
sensitive: e.sensitive,
|
|
223
|
+
})), null, 2);
|
|
224
|
+
case 'export':
|
|
225
|
+
return store.envs.map(e => {
|
|
226
|
+
const escapedValue = e.value.replace(/'/g, "'\\''");
|
|
227
|
+
return `export ${e.key}='${escapedValue}'`;
|
|
228
|
+
}).join('\n');
|
|
229
|
+
case 'table':
|
|
230
|
+
default:
|
|
231
|
+
if (store.envs.length === 0) {
|
|
232
|
+
return 'No environment variables stored.';
|
|
233
|
+
}
|
|
234
|
+
const lines = [];
|
|
235
|
+
lines.push('┌─────────────────────────────────────────────────────────────────┐');
|
|
236
|
+
lines.push('│ Environment Variables │');
|
|
237
|
+
lines.push('├─────────────────────────────────────────────────────────────────┤');
|
|
238
|
+
for (const entry of store.envs) {
|
|
239
|
+
const displayValue = entry.sensitive
|
|
240
|
+
? '[REDACTED]'
|
|
241
|
+
: (entry.value.length > 40 ? entry.value.substring(0, 37) + '...' : entry.value);
|
|
242
|
+
const line = `│ ${entry.key.padEnd(20)} = ${displayValue.padEnd(38)}│`;
|
|
243
|
+
lines.push(line);
|
|
244
|
+
}
|
|
245
|
+
lines.push('└─────────────────────────────────────────────────────────────────┘');
|
|
246
|
+
return lines.join('\n');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Run a command with the environment variables from the store
|
|
251
|
+
*/
|
|
252
|
+
export async function run(command, storePath) {
|
|
253
|
+
if (command.length === 0) {
|
|
254
|
+
console.error('Error: No command specified');
|
|
255
|
+
return 1;
|
|
256
|
+
}
|
|
257
|
+
// Load environment variables
|
|
258
|
+
const envVars = getAll(storePath);
|
|
259
|
+
// Merge with current environment
|
|
260
|
+
const env = {
|
|
261
|
+
...process.env,
|
|
262
|
+
...envVars,
|
|
263
|
+
};
|
|
264
|
+
// Spawn the command
|
|
265
|
+
const [cmd, ...args] = command;
|
|
266
|
+
return new Promise((resolve) => {
|
|
267
|
+
const child = spawn(cmd, args, {
|
|
268
|
+
env,
|
|
269
|
+
stdio: 'inherit',
|
|
270
|
+
shell: true,
|
|
271
|
+
});
|
|
272
|
+
child.on('error', (err) => {
|
|
273
|
+
console.error(`Failed to execute command: ${err.message}`);
|
|
274
|
+
resolve(1);
|
|
275
|
+
});
|
|
276
|
+
child.on('exit', (code) => {
|
|
277
|
+
resolve(code ?? 0);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Clear the environment store
|
|
283
|
+
*/
|
|
284
|
+
export function clear(storePath) {
|
|
285
|
+
const path = storePath || getStorePath();
|
|
286
|
+
if (!existsSync(path)) {
|
|
287
|
+
return {
|
|
288
|
+
success: true,
|
|
289
|
+
message: 'Envstore does not exist, nothing to clear.',
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
try {
|
|
293
|
+
unlinkSync(path);
|
|
294
|
+
return {
|
|
295
|
+
success: true,
|
|
296
|
+
message: `Cleared envstore at ${path}`,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
return {
|
|
301
|
+
success: false,
|
|
302
|
+
error: `Failed to clear envstore: ${error.message}`,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Unset (remove) a specific environment variable from the store
|
|
308
|
+
*/
|
|
309
|
+
export function unset(key, storePath) {
|
|
310
|
+
const store = loadStore(storePath);
|
|
311
|
+
const index = store.envs.findIndex(e => e.key === key);
|
|
312
|
+
if (index === -1) {
|
|
313
|
+
return {
|
|
314
|
+
success: false,
|
|
315
|
+
error: `Key '${key}' not found in envstore`,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
store.envs.splice(index, 1);
|
|
319
|
+
saveStore(store, storePath);
|
|
320
|
+
return {
|
|
321
|
+
success: true,
|
|
322
|
+
message: `Removed ${key} from envstore`,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Generate a bash script that sources the envstore
|
|
327
|
+
* This can be prepended to step scripts to load environment variables
|
|
328
|
+
*/
|
|
329
|
+
export function generateSourceScript(storePath) {
|
|
330
|
+
const path = storePath || getStorePath();
|
|
331
|
+
return `
|
|
332
|
+
# CI Build envman: Load environment variables from store
|
|
333
|
+
if [ -f "${path}" ]; then
|
|
334
|
+
while IFS= read -r line; do
|
|
335
|
+
if [ -n "$line" ]; then
|
|
336
|
+
export "$line"
|
|
337
|
+
fi
|
|
338
|
+
done < <(node -e "
|
|
339
|
+
const fs = require('fs');
|
|
340
|
+
try {
|
|
341
|
+
const store = JSON.parse(fs.readFileSync('${path}', 'utf-8'));
|
|
342
|
+
for (const e of store.envs || []) {
|
|
343
|
+
const escaped = e.value.replace(/'/g, \"'\\\\\\\\\\\\\\''\" );
|
|
344
|
+
console.log(e.key + '=' + escaped);
|
|
345
|
+
}
|
|
346
|
+
} catch(e) {}
|
|
347
|
+
")
|
|
348
|
+
fi
|
|
349
|
+
`;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Export all environment variables to the current process
|
|
353
|
+
* Useful for programmatic usage
|
|
354
|
+
*/
|
|
355
|
+
export function exportToProcess(storePath) {
|
|
356
|
+
const envVars = getAll(storePath);
|
|
357
|
+
for (const [key, value] of Object.entries(envVars)) {
|
|
358
|
+
process.env[key] = value;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=envman.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envman.test.d.ts","sourceRoot":"","sources":["../../../src/envman/envman.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the CI Build Environment Variable Manager (envman)
|
|
3
|
+
*/
|
|
4
|
+
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import * as envman from './envman.js';
|
|
8
|
+
import { STORE_VERSION } from './types.js';
|
|
9
|
+
describe('envman', () => {
|
|
10
|
+
const testStorePath = path.join(process.cwd(), '.envstore.test.json');
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// Clean up any existing test store
|
|
13
|
+
if (fs.existsSync(testStorePath)) {
|
|
14
|
+
fs.unlinkSync(testStorePath);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
// Clean up test store after each test
|
|
19
|
+
if (fs.existsSync(testStorePath)) {
|
|
20
|
+
fs.unlinkSync(testStorePath);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
describe('init', () => {
|
|
24
|
+
test('should create an empty envstore file', () => {
|
|
25
|
+
const result = envman.init(testStorePath);
|
|
26
|
+
expect(result.success).toBe(true);
|
|
27
|
+
expect(fs.existsSync(testStorePath)).toBe(true);
|
|
28
|
+
const content = JSON.parse(fs.readFileSync(testStorePath, 'utf-8'));
|
|
29
|
+
expect(content.version).toBe(STORE_VERSION);
|
|
30
|
+
expect(content.envs).toEqual([]);
|
|
31
|
+
});
|
|
32
|
+
test('should fail if envstore already exists', () => {
|
|
33
|
+
// Create the store first
|
|
34
|
+
envman.init(testStorePath);
|
|
35
|
+
// Try to init again
|
|
36
|
+
const result = envman.init(testStorePath);
|
|
37
|
+
expect(result.success).toBe(false);
|
|
38
|
+
expect(result.error).toContain('already exists');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('add', () => {
|
|
42
|
+
test('should add a new environment variable', () => {
|
|
43
|
+
const result = envman.add({
|
|
44
|
+
key: 'TEST_VAR',
|
|
45
|
+
value: 'test_value',
|
|
46
|
+
}, testStorePath);
|
|
47
|
+
expect(result.success).toBe(true);
|
|
48
|
+
const value = envman.get('TEST_VAR', testStorePath);
|
|
49
|
+
expect(value).toBe('test_value');
|
|
50
|
+
});
|
|
51
|
+
test('should update an existing environment variable', () => {
|
|
52
|
+
// Add initial value
|
|
53
|
+
envman.add({ key: 'TEST_VAR', value: 'initial' }, testStorePath);
|
|
54
|
+
// Update value
|
|
55
|
+
const result = envman.add({ key: 'TEST_VAR', value: 'updated' }, testStorePath);
|
|
56
|
+
expect(result.success).toBe(true);
|
|
57
|
+
expect(envman.get('TEST_VAR', testStorePath)).toBe('updated');
|
|
58
|
+
});
|
|
59
|
+
test('should append to existing value with --append flag', () => {
|
|
60
|
+
envman.add({ key: 'TEST_VAR', value: 'hello' }, testStorePath);
|
|
61
|
+
envman.add({ key: 'TEST_VAR', value: ' world', append: true }, testStorePath);
|
|
62
|
+
expect(envman.get('TEST_VAR', testStorePath)).toBe('hello world');
|
|
63
|
+
});
|
|
64
|
+
test('should read value from file', () => {
|
|
65
|
+
const valueFilePath = path.join(process.cwd(), '.test-value-file.txt');
|
|
66
|
+
fs.writeFileSync(valueFilePath, 'value_from_file');
|
|
67
|
+
try {
|
|
68
|
+
const result = envman.add({
|
|
69
|
+
key: 'FILE_VAR',
|
|
70
|
+
valueFile: valueFilePath,
|
|
71
|
+
}, testStorePath);
|
|
72
|
+
expect(result.success).toBe(true);
|
|
73
|
+
expect(envman.get('FILE_VAR', testStorePath)).toBe('value_from_file');
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
fs.unlinkSync(valueFilePath);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
test('should fail with invalid key name', () => {
|
|
80
|
+
const result = envman.add({
|
|
81
|
+
key: '123-invalid',
|
|
82
|
+
value: 'test',
|
|
83
|
+
}, testStorePath);
|
|
84
|
+
expect(result.success).toBe(false);
|
|
85
|
+
expect(result.error).toContain('Invalid key');
|
|
86
|
+
});
|
|
87
|
+
test('should skip empty values with --skip-if-empty', () => {
|
|
88
|
+
const result = envman.add({
|
|
89
|
+
key: 'EMPTY_VAR',
|
|
90
|
+
value: ' ',
|
|
91
|
+
skipIfEmpty: true,
|
|
92
|
+
}, testStorePath);
|
|
93
|
+
expect(result.success).toBe(true);
|
|
94
|
+
expect(result.message).toContain('Skipped');
|
|
95
|
+
expect(envman.get('EMPTY_VAR', testStorePath)).toBeUndefined();
|
|
96
|
+
});
|
|
97
|
+
test('should mark sensitive variables', () => {
|
|
98
|
+
const result = envman.add({
|
|
99
|
+
key: 'SECRET_VAR',
|
|
100
|
+
value: 'super_secret',
|
|
101
|
+
sensitive: true,
|
|
102
|
+
}, testStorePath);
|
|
103
|
+
expect(result.success).toBe(true);
|
|
104
|
+
expect(result.message).toContain('REDACTED');
|
|
105
|
+
const store = envman.loadStore(testStorePath);
|
|
106
|
+
const entry = store.envs.find(e => e.key === 'SECRET_VAR');
|
|
107
|
+
expect(entry?.sensitive).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('get', () => {
|
|
111
|
+
test('should return undefined for non-existent key', () => {
|
|
112
|
+
const value = envman.get('NON_EXISTENT', testStorePath);
|
|
113
|
+
expect(value).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
test('should return value for existing key', () => {
|
|
116
|
+
envman.add({ key: 'TEST_VAR', value: 'test_value' }, testStorePath);
|
|
117
|
+
const value = envman.get('TEST_VAR', testStorePath);
|
|
118
|
+
expect(value).toBe('test_value');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe('getAll', () => {
|
|
122
|
+
test('should return empty object for empty store', () => {
|
|
123
|
+
const all = envman.getAll(testStorePath);
|
|
124
|
+
expect(all).toEqual({});
|
|
125
|
+
});
|
|
126
|
+
test('should return all variables as key-value pairs', () => {
|
|
127
|
+
envman.add({ key: 'VAR1', value: 'value1' }, testStorePath);
|
|
128
|
+
envman.add({ key: 'VAR2', value: 'value2' }, testStorePath);
|
|
129
|
+
const all = envman.getAll(testStorePath);
|
|
130
|
+
expect(all).toEqual({
|
|
131
|
+
VAR1: 'value1',
|
|
132
|
+
VAR2: 'value2',
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
describe('unset', () => {
|
|
137
|
+
test('should remove an existing variable', () => {
|
|
138
|
+
envman.add({ key: 'TO_REMOVE', value: 'test' }, testStorePath);
|
|
139
|
+
const result = envman.unset('TO_REMOVE', testStorePath);
|
|
140
|
+
expect(result.success).toBe(true);
|
|
141
|
+
expect(envman.get('TO_REMOVE', testStorePath)).toBeUndefined();
|
|
142
|
+
});
|
|
143
|
+
test('should fail for non-existent key', () => {
|
|
144
|
+
const result = envman.unset('NON_EXISTENT', testStorePath);
|
|
145
|
+
expect(result.success).toBe(false);
|
|
146
|
+
expect(result.error).toContain('not found');
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe('clear', () => {
|
|
150
|
+
test('should remove the envstore file', () => {
|
|
151
|
+
envman.add({ key: 'TEST_VAR', value: 'test' }, testStorePath);
|
|
152
|
+
expect(fs.existsSync(testStorePath)).toBe(true);
|
|
153
|
+
const result = envman.clear(testStorePath);
|
|
154
|
+
expect(result.success).toBe(true);
|
|
155
|
+
expect(fs.existsSync(testStorePath)).toBe(false);
|
|
156
|
+
});
|
|
157
|
+
test('should succeed even if envstore does not exist', () => {
|
|
158
|
+
const result = envman.clear(testStorePath);
|
|
159
|
+
expect(result.success).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe('print', () => {
|
|
163
|
+
beforeEach(() => {
|
|
164
|
+
envman.add({ key: 'VAR1', value: 'value1' }, testStorePath);
|
|
165
|
+
envman.add({ key: 'VAR2', value: 'value2' }, testStorePath);
|
|
166
|
+
});
|
|
167
|
+
test('should print in table format by default', () => {
|
|
168
|
+
const output = envman.print('table', testStorePath);
|
|
169
|
+
expect(output).toContain('VAR1');
|
|
170
|
+
expect(output).toContain('value1');
|
|
171
|
+
expect(output).toContain('VAR2');
|
|
172
|
+
expect(output).toContain('value2');
|
|
173
|
+
});
|
|
174
|
+
test('should print in export format', () => {
|
|
175
|
+
const output = envman.print('export', testStorePath);
|
|
176
|
+
expect(output).toContain("export VAR1='value1'");
|
|
177
|
+
expect(output).toContain("export VAR2='value2'");
|
|
178
|
+
});
|
|
179
|
+
test('should print in JSON format', () => {
|
|
180
|
+
const output = envman.print('json', testStorePath);
|
|
181
|
+
const parsed = JSON.parse(output);
|
|
182
|
+
expect(parsed).toHaveLength(2);
|
|
183
|
+
expect(parsed.find((e) => e.key === 'VAR1')?.value).toBe('value1');
|
|
184
|
+
});
|
|
185
|
+
test('should redact sensitive values in table format', () => {
|
|
186
|
+
envman.add({ key: 'SECRET', value: 'secret_value', sensitive: true }, testStorePath);
|
|
187
|
+
const output = envman.print('table', testStorePath);
|
|
188
|
+
expect(output).toContain('SECRET');
|
|
189
|
+
expect(output).toContain('[REDACTED]');
|
|
190
|
+
expect(output).not.toContain('secret_value');
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
describe('loadStore', () => {
|
|
194
|
+
test('should return empty store if file does not exist', () => {
|
|
195
|
+
const store = envman.loadStore(testStorePath);
|
|
196
|
+
expect(store.version).toBe(STORE_VERSION);
|
|
197
|
+
expect(store.envs).toEqual([]);
|
|
198
|
+
});
|
|
199
|
+
test('should load existing store from file', () => {
|
|
200
|
+
const testStore = {
|
|
201
|
+
version: STORE_VERSION,
|
|
202
|
+
envs: [
|
|
203
|
+
{ key: 'TEST', value: 'value', createdAt: '', updatedAt: '' },
|
|
204
|
+
],
|
|
205
|
+
};
|
|
206
|
+
fs.writeFileSync(testStorePath, JSON.stringify(testStore));
|
|
207
|
+
const store = envman.loadStore(testStorePath);
|
|
208
|
+
expect(store.envs).toHaveLength(1);
|
|
209
|
+
expect(store.envs[0].key).toBe('TEST');
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
describe('createEmptyStore', () => {
|
|
213
|
+
test('should create a valid empty store', () => {
|
|
214
|
+
const store = envman.createEmptyStore();
|
|
215
|
+
expect(store.version).toBe(STORE_VERSION);
|
|
216
|
+
expect(store.envs).toEqual([]);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
describe('special characters handling', () => {
|
|
220
|
+
test('should handle values with single quotes', () => {
|
|
221
|
+
envman.add({ key: 'QUOTED', value: "it's a test" }, testStorePath);
|
|
222
|
+
expect(envman.get('QUOTED', testStorePath)).toBe("it's a test");
|
|
223
|
+
const exported = envman.print('export', testStorePath);
|
|
224
|
+
expect(exported).toContain('QUOTED');
|
|
225
|
+
});
|
|
226
|
+
test('should handle values with newlines', () => {
|
|
227
|
+
envman.add({ key: 'MULTILINE', value: 'line1\nline2\nline3' }, testStorePath);
|
|
228
|
+
expect(envman.get('MULTILINE', testStorePath)).toBe('line1\nline2\nline3');
|
|
229
|
+
});
|
|
230
|
+
test('should handle empty values', () => {
|
|
231
|
+
envman.add({ key: 'EMPTY', value: '' }, testStorePath);
|
|
232
|
+
expect(envman.get('EMPTY', testStorePath)).toBe('');
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
//# sourceMappingURL=envman.test.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI Build Environment Variable Manager (envman)
|
|
3
|
+
*
|
|
4
|
+
* A tool for managing environment variables between CI/CD pipeline steps.
|
|
5
|
+
* Similar to Bitrise's envman, this allows scripts to register outputs
|
|
6
|
+
* that subsequent steps can use as environment variables.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // In a script step:
|
|
10
|
+
* // envman add --key BUILD_VERSION --value '1.2.3'
|
|
11
|
+
* // envman add --key APK_PATH --valuefile ./build/output/path.txt
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Programmatic usage:
|
|
15
|
+
* import { add, getAll, run } from './envman/index.js';
|
|
16
|
+
*
|
|
17
|
+
* add({ key: 'BUILD_VERSION', value: '1.2.3' });
|
|
18
|
+
* const envs = getAll();
|
|
19
|
+
* await run(['gradle', 'assembleRelease']);
|
|
20
|
+
*/
|
|
21
|
+
export * from './envman.js';
|
|
22
|
+
export * from './types.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/envman/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI Build Environment Variable Manager (envman)
|
|
3
|
+
*
|
|
4
|
+
* A tool for managing environment variables between CI/CD pipeline steps.
|
|
5
|
+
* Similar to Bitrise's envman, this allows scripts to register outputs
|
|
6
|
+
* that subsequent steps can use as environment variables.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // In a script step:
|
|
10
|
+
* // envman add --key BUILD_VERSION --value '1.2.3'
|
|
11
|
+
* // envman add --key APK_PATH --valuefile ./build/output/path.txt
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Programmatic usage:
|
|
15
|
+
* import { add, getAll, run } from './envman/index.js';
|
|
16
|
+
*
|
|
17
|
+
* add({ key: 'BUILD_VERSION', value: '1.2.3' });
|
|
18
|
+
* const envs = getAll();
|
|
19
|
+
* await run(['gradle', 'assembleRelease']);
|
|
20
|
+
*/
|
|
21
|
+
export * from './envman.js';
|
|
22
|
+
export * from './types.js';
|
|
23
|
+
//# sourceMappingURL=index.js.map
|