@suffolklitlab/alkiln 5.4.0 → 5.4.1-feat-github-server-15
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/.github/workflows/github_server.yml +85 -0
- package/CHANGELOG.md +5 -0
- package/action.yml +33 -10
- package/github_server/action.yml +165 -0
- package/lib/docassemble/docassemble_api_REST.js +10 -2
- package/lib/docassemble/docassemble_api_interface.js +15 -10
- package/lib/docassemble/get_base_interview_url.js +13 -3
- package/lib/docassemble/server_install.js +40 -0
- package/lib/docassemble/setup.js +1 -1
- package/lib/run_cucumber.js +67 -34
- package/lib/scope.js +38 -47
- package/lib/utils/log.js +1 -1
- package/lib/utils/session_vars.js +157 -7
- package/npm-shrinkwrap.json +24 -2583
- package/package.json +4 -1
- package/setup.py +2 -2
package/lib/scope.js
CHANGED
|
@@ -46,6 +46,9 @@ let printable_var_value = function(row) {
|
|
|
46
46
|
/* `row` might be a row, a source row, or an original row. */
|
|
47
47
|
let original = get_original_row(row);
|
|
48
48
|
if ( is_secret_var(original) ) {
|
|
49
|
+
if ( session_vars.get_dangerous_debug() ) {
|
|
50
|
+
return `alkiln_dangerous ${ row.value }`;
|
|
51
|
+
}
|
|
49
52
|
return original.flags.secret_name;
|
|
50
53
|
}
|
|
51
54
|
return row.value;
|
|
@@ -1681,75 +1684,52 @@ module.exports = {
|
|
|
1681
1684
|
}, // Ends scope.today_to_date()
|
|
1682
1685
|
|
|
1683
1686
|
findFiles: async function( scope, {to_find_names}) {
|
|
1687
|
+
/** Returns a list of paths to the sources folder associated
|
|
1688
|
+
* with the given list of file names.
|
|
1689
|
+
*
|
|
1690
|
+
* @param to_find_names { [str] } List of file names
|
|
1691
|
+
*
|
|
1692
|
+
* @returns { [str] } sources folder paths
|
|
1693
|
+
*/
|
|
1684
1694
|
// First make sure the list of files was defined. Don't remove spaces yet -
|
|
1685
1695
|
// allow a typo where someone forgot to include a space after a comma.
|
|
1696
|
+
// TODO: wish we had the var name here that folks are trying to set
|
|
1686
1697
|
if ( to_find_names.length === 0 ) {
|
|
1687
|
-
reports.addToReport( scope, {
|
|
1688
|
-
type: `error`,
|
|
1689
|
-
value: `Your list of files to find is empty.`
|
|
1690
|
-
});
|
|
1691
|
-
return [];
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
|
-
let dirs = [];
|
|
1695
|
-
if ( session_vars.get_origin() === `playground` ) {
|
|
1696
|
-
let files_playground = fg.sync(
|
|
1697
|
-
[ `/usr/share/docassemble/files/playgroundsources/${session_vars.get_user_id()}/${session_vars.get_user_project_name()}` ],
|
|
1698
|
-
{ onlyFiles: false, suppressErrors: true }
|
|
1699
|
-
);
|
|
1700
|
-
let files_s3 = fg.sync(
|
|
1701
|
-
[ `/tmp/playgroundsources/${session_vars.get_user_id()}/${session_vars.get_user_project_name()}` ],
|
|
1702
|
-
{ onlyFiles: false, suppressErrors: true }
|
|
1703
|
-
);
|
|
1704
|
-
|
|
1705
|
-
dirs = files_playground.concat( files_s3 );
|
|
1706
|
-
} else {
|
|
1707
|
-
dirs = fg.sync(
|
|
1708
|
-
[ `**/docassemble/**/data/sources` ],
|
|
1709
|
-
{ onlyFiles: false, suppressErrors: true }
|
|
1710
|
-
);
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1713
|
-
if ( session_vars.get_debug() ) {
|
|
1714
|
-
console.log( `All discovered dirs to find files from:`, dirs );
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
// Make sure sources directory exists and has files in it
|
|
1718
|
-
if ( dirs.length === 0 ) {
|
|
1719
1698
|
reports.addToReport( scope, {
|
|
1720
1699
|
type: `warning`,
|
|
1721
|
-
value: `
|
|
1722
|
-
+ `but ALKiln couldn't find the directory or it was empty.`
|
|
1700
|
+
value: `Your Step is missing the names of which file(s) to use.`
|
|
1723
1701
|
});
|
|
1724
1702
|
return [];
|
|
1725
1703
|
}
|
|
1726
1704
|
|
|
1727
|
-
|
|
1705
|
+
let sources_dirs = session_vars.get_sources_paths();
|
|
1706
|
+
// Get the full paths of all the existing files
|
|
1728
1707
|
let paths = [];
|
|
1729
1708
|
let missing_files = []; // For any user warnings
|
|
1730
|
-
for ( let name of to_find_names) {
|
|
1731
|
-
|
|
1709
|
+
for ( let name of to_find_names ) {
|
|
1710
|
+
|
|
1732
1711
|
let trimmed_name = name.trim();
|
|
1733
1712
|
let matching_paths = [];
|
|
1734
|
-
|
|
1735
|
-
for ( let one_dir of
|
|
1736
|
-
|
|
1737
|
-
|
|
1713
|
+
// Look for the file in all "sources" folders
|
|
1714
|
+
for ( let one_dir of sources_dirs ) {
|
|
1715
|
+
let new_paths = fg.sync(
|
|
1716
|
+
[ `${ one_dir }/${ trimmed_name }` ],
|
|
1717
|
+
{ suppressErrors: true }
|
|
1718
|
+
);
|
|
1738
1719
|
matching_paths.push( ...new_paths );
|
|
1739
|
-
}
|
|
1720
|
+
}
|
|
1740
1721
|
|
|
1741
1722
|
if ( matching_paths.length === 0 ) {
|
|
1742
1723
|
missing_files.push( trimmed_name );
|
|
1743
1724
|
} else {
|
|
1744
1725
|
paths.push( ...matching_paths );
|
|
1745
1726
|
}
|
|
1746
|
-
|
|
1747
1727
|
} // ends for each file
|
|
1748
1728
|
|
|
1749
1729
|
if ( missing_files.length > 0 ) {
|
|
1750
1730
|
reports.addToReport( scope, {
|
|
1751
1731
|
type: `warning`,
|
|
1752
|
-
value: `ALKiln could not find "${ missing_files.join('", "') }" in
|
|
1732
|
+
value: `ALKiln could not find "${ missing_files.join('", "') }" in the folder(s) at "${ sources_dirs.join('", "') }".`
|
|
1753
1733
|
});
|
|
1754
1734
|
}
|
|
1755
1735
|
|
|
@@ -1758,7 +1738,7 @@ module.exports = {
|
|
|
1758
1738
|
return [];
|
|
1759
1739
|
}
|
|
1760
1740
|
return paths;
|
|
1761
|
-
},
|
|
1741
|
+
}, // Ends scope.findFiles()
|
|
1762
1742
|
|
|
1763
1743
|
uploadFiles: async function ( scope, { handle, answer }) {
|
|
1764
1744
|
/* Try to upload one or more files to a file-type input field.
|
|
@@ -1999,7 +1979,7 @@ module.exports = {
|
|
|
1999
1979
|
}
|
|
2000
1980
|
if ( num_unused_rows > 0 ) {
|
|
2001
1981
|
let { id } = await scope.examinePageID( scope, 'none to match' );
|
|
2002
|
-
let msg = `
|
|
1982
|
+
let msg = `Error on page "${id}". See screenshot and see text above for more details.`;
|
|
2003
1983
|
reports.addToReport(scope, { type: `error`, value: msg });
|
|
2004
1984
|
expect( num_unused_rows, msg ).to.equal( 0 );
|
|
2005
1985
|
}
|
|
@@ -2460,6 +2440,10 @@ module.exports = {
|
|
|
2460
2440
|
/** Sets a non-story table variable to a "secret" value (i.e. an env var) */
|
|
2461
2441
|
// Prevent pictures of a screen with a secret.
|
|
2462
2442
|
scope.disable_error_screenshot = true;
|
|
2443
|
+
if ( session_vars.get_dangerous_debug() ) {
|
|
2444
|
+
scope.disable_error_screenshot = false;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2463
2447
|
let var_data = await scope.normalizeTable( scope, {
|
|
2464
2448
|
var_data: [{
|
|
2465
2449
|
var: var_name,
|
|
@@ -2629,7 +2613,10 @@ module.exports = {
|
|
|
2629
2613
|
*/
|
|
2630
2614
|
// Don't take a picture of a failed login in case one of the inputs is correct
|
|
2631
2615
|
scope.disable_error_screenshot = true;
|
|
2632
|
-
|
|
2616
|
+
if ( session_vars.get_dangerous_debug() ) {
|
|
2617
|
+
scope.disable_error_screenshot = false;
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2633
2620
|
// If there is no browser open, start a new one
|
|
2634
2621
|
if (!scope.browser) {
|
|
2635
2622
|
scope.browser = await scope.driver.launch({ headless: !session_vars.DEBUG });
|
|
@@ -2662,6 +2649,10 @@ module.exports = {
|
|
|
2662
2649
|
let email = process.env[ email_secret_name ];
|
|
2663
2650
|
let password = process.env[ password_secret_name ];
|
|
2664
2651
|
|
|
2652
|
+
if ( session_vars.get_dangerous_debug() ) {
|
|
2653
|
+
log.debug({ type: `unsafe`, data: `login: ${ email }, ${ password }` });
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2665
2656
|
// Give as many useful messages to the user as possible if the env vars
|
|
2666
2657
|
// aren't defined. Eventually, just provide a link to the docs because
|
|
2667
2658
|
// this is complex
|
package/lib/utils/log.js
CHANGED
|
@@ -42,7 +42,7 @@ log.error = function ({ type='', pre='', data='', post='' }) {
|
|
|
42
42
|
|
|
43
43
|
log.debug = function ({ type='', pre='', data='', post='' }) {
|
|
44
44
|
/* If debugging is turned on, log a message that includes `ALKiln` and `debug` */
|
|
45
|
-
if ( session_vars.get_debug() ) {
|
|
45
|
+
if ( session_vars.get_debug() || session_vars.get_dangerous_debug() ) {
|
|
46
46
|
let start = create_msg_start([ type, 'debug' ], pre );
|
|
47
47
|
// Log them each on a separate line
|
|
48
48
|
console.log( `ALKiln ${ type } debug: ${ pre }` );
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const fg = require('fast-glob');
|
|
2
3
|
const path = require('path');
|
|
3
4
|
require('dotenv').config();
|
|
4
5
|
|
|
@@ -23,6 +24,11 @@ module.exports = session_vars;
|
|
|
23
24
|
// These default to null
|
|
24
25
|
// TODO: How to isolate debug elsewhere so this file can use the logger?
|
|
25
26
|
session_vars.get_debug = function () { return process.env.DEBUG || null; };
|
|
27
|
+
session_vars.get_dangerous_debug = function () {
|
|
28
|
+
/** Note this will cause failure of tests that reassure the user about
|
|
29
|
+
* security precautions we took, like not taking a screenshot. */
|
|
30
|
+
return process.env._ALKILN_DANGEROUS_DEBUG || null;
|
|
31
|
+
};
|
|
26
32
|
session_vars.is_dev_env = function () { return process.env.DEV || null; }
|
|
27
33
|
|
|
28
34
|
session_vars.get_dev_api_key = function () { return process.env.DOCASSEMBLE_DEVELOPER_API_KEY || null; };
|
|
@@ -37,13 +43,6 @@ session_vars.get_origin = function () {
|
|
|
37
43
|
};
|
|
38
44
|
session_vars.get_user_project_name = function () { return process.env._PROJECT_NAME || null; };
|
|
39
45
|
session_vars.get_user_id = function () { return process.env._USER_ID || null; };
|
|
40
|
-
session_vars.get_tags = function () {
|
|
41
|
-
if ( process.env._TAGS ) {
|
|
42
|
-
return process.env._TAGS.split(` `);
|
|
43
|
-
} else {
|
|
44
|
-
return [];
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
46
|
|
|
48
47
|
// More complex logic
|
|
49
48
|
session_vars.get_server_reload_timeout = function () {
|
|
@@ -210,6 +209,124 @@ session_vars.get_artifacts_path_name = function () {
|
|
|
210
209
|
}
|
|
211
210
|
}; // Ends get_artifacts_path_name()
|
|
212
211
|
|
|
212
|
+
|
|
213
|
+
const install_type_key = `da_install_type`;
|
|
214
|
+
session_vars.save_install_type = function (install_type) {
|
|
215
|
+
/* Save a key with the name of the current artifacts folder in case it doesn't exist. */
|
|
216
|
+
|
|
217
|
+
// Ensure artifacts path file exists
|
|
218
|
+
if ( !fs.existsSync( runtime_config_path ) ) {
|
|
219
|
+
// If the file doesn't exist, make one because next we need to read it
|
|
220
|
+
fs.writeFileSync( runtime_config_path, JSON.stringify( {}, null, 2 ) );
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Get the json, changing it, and re-write the file from scratch
|
|
224
|
+
let json = JSON.parse( fs.readFileSync( runtime_config_path ) );
|
|
225
|
+
json[ install_type_key ] = install_type;
|
|
226
|
+
let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
227
|
+
|
|
228
|
+
return file;
|
|
229
|
+
}; // Ends save_install_type()
|
|
230
|
+
|
|
231
|
+
session_vars.get_install_type = function () {
|
|
232
|
+
/* Get the name of the current artifacts path. */
|
|
233
|
+
try {
|
|
234
|
+
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
235
|
+
let install_type = json[ install_type_key ];
|
|
236
|
+
|
|
237
|
+
return install_type;
|
|
238
|
+
} catch ( error ) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}; // Ends get_install_type()
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
const repo_folder_key = `da_repo_folder_name`;
|
|
245
|
+
session_vars.save_repo_folder_name = function (repo_folder_name) {
|
|
246
|
+
/** Save a key with the name of the main package folder in the repository. */
|
|
247
|
+
|
|
248
|
+
// Ensure runtime config file exists
|
|
249
|
+
if ( !fs.existsSync( runtime_config_path ) ) {
|
|
250
|
+
// If the file doesn't exist, make one because next we need to read it
|
|
251
|
+
fs.writeFileSync( runtime_config_path, JSON.stringify( {}, null, 2 ) );
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Get the json, changing it, and re-write the file from scratch
|
|
255
|
+
let json = JSON.parse( fs.readFileSync( runtime_config_path ) );
|
|
256
|
+
json[ da_repo_folder_name ] = repo_folder_name;
|
|
257
|
+
let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
258
|
+
|
|
259
|
+
return file;
|
|
260
|
+
}; // Ends session_vars.save_repo_folder_name()
|
|
261
|
+
|
|
262
|
+
session_vars.get_repo_folder_name = function () {
|
|
263
|
+
/** Get the name of the main folder in the repository. */
|
|
264
|
+
try {
|
|
265
|
+
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
266
|
+
let name = json[ da_repo_folder_name ];
|
|
267
|
+
|
|
268
|
+
return name;
|
|
269
|
+
} catch ( error ) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}; // Ends session_vars.get_repo_folder_name()
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
session_vars.set_sources_paths = function ( paths ) {
|
|
276
|
+
/** Returns whether at least one of the given path exists. Store
|
|
277
|
+
* a list of the existing paths. Warn of any missing paths. Can be
|
|
278
|
+
* used for getting, e.g .feature files, files to upload, etc.
|
|
279
|
+
*
|
|
280
|
+
* Our code should ensure this gets run before cucumber tests get triggered.
|
|
281
|
+
*
|
|
282
|
+
* @param paths { [str] } List of paths to the 'sources' folder.
|
|
283
|
+
*
|
|
284
|
+
* @returns bool
|
|
285
|
+
*/
|
|
286
|
+
|
|
287
|
+
// Check every path, tracking which exist and which are missing
|
|
288
|
+
let existing_paths = [];
|
|
289
|
+
let missing_paths = [];
|
|
290
|
+
for ( let path of paths ) {
|
|
291
|
+
let dirs = fg.sync(
|
|
292
|
+
[ path ],
|
|
293
|
+
{ onlyFiles: false, suppressErrors: true }
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
if ( dirs.length > 0 ) {
|
|
297
|
+
existing_paths.push( ...dirs );
|
|
298
|
+
} else {
|
|
299
|
+
missing_paths.push( path );
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Warn about missing paths
|
|
304
|
+
if ( missing_paths.length > 0 ) {
|
|
305
|
+
console.warn(
|
|
306
|
+
`ALKiln WARNING: ALKiln can't find folders at "${ paths.join(", ") }".`
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// If no paths were valid
|
|
311
|
+
if ( existing_paths.length <= 0 ) {
|
|
312
|
+
session_vars._sources_paths = null;
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Otherwise, store valid paths
|
|
317
|
+
session_vars._sources_paths = existing_paths;
|
|
318
|
+
return true;
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
session_vars.get_sources_paths = function () {
|
|
322
|
+
/** Get the "sources" folder path. Should never be undefined during
|
|
323
|
+
* a run of the test. run_cucumber.js should make sure it has
|
|
324
|
+
* a default value.
|
|
325
|
+
*
|
|
326
|
+
* @returns str || null */
|
|
327
|
+
return session_vars._sources_paths;
|
|
328
|
+
};
|
|
329
|
+
|
|
213
330
|
session_vars.validateEnvironment = function() {
|
|
214
331
|
/** Throw a useful error for the developer if any of the env vars
|
|
215
332
|
* required by absolutely all tests are missing. Gather all
|
|
@@ -274,3 +391,36 @@ session_vars.validateEnvironment = function() {
|
|
|
274
391
|
};
|
|
275
392
|
|
|
276
393
|
session_vars.validateEnvironment();
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
const save_runtime_config_var = function (key, value) {
|
|
397
|
+
/** Save a key and its value in the runtime config file. */
|
|
398
|
+
|
|
399
|
+
// Ensure runtime config file exists
|
|
400
|
+
if ( !fs.existsSync( runtime_config_path ) ) {
|
|
401
|
+
// If the file doesn't exist, make one because next we need to read it
|
|
402
|
+
fs.writeFileSync( runtime_config_path, JSON.stringify( {}, null, 2 ) );
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Get the json, changing it, and re-write the file from scratch
|
|
406
|
+
let json = JSON.parse( fs.readFileSync( runtime_config_path ) );
|
|
407
|
+
json[ key ] = value;
|
|
408
|
+
let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
|
|
409
|
+
|
|
410
|
+
if ( session_vars.get_debug() ) {
|
|
411
|
+
console.log( `ALKiln debug: Stored "${key}" locally as "${value}".` );
|
|
412
|
+
}
|
|
413
|
+
return file;
|
|
414
|
+
}; // Ends save_runtime_config_var()
|
|
415
|
+
|
|
416
|
+
const get_runtime_config_var = function (key) {
|
|
417
|
+
/** Get the value of the given key from the runtime config file. */
|
|
418
|
+
try {
|
|
419
|
+
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
420
|
+
let value = json[ key ];
|
|
421
|
+
|
|
422
|
+
return value;
|
|
423
|
+
} catch ( error ) {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
}; // Ends get_runtime_config_var()
|