Conversation
any announcements new ALKiln versions have even if ALKilnInThePlayground isn't itself updated. Closes #1014 Co-authored-by: will-morningstar <mxwillmorningstar@gmail.com>
…n into 1014_breaking_news_2
tobynorth
left a comment
There was a problem hiding this comment.
Looks good to me! Didn't find any major issues. One high-level, almost certainly out of scope question for my own understanding: it seems like the need for this PR arose out of ALKiln and ALKiP being separate packages -- why is that? (would you ever want to install ALKiP without wanting to install ALKiln?)
And a general question: how are all the logging changes (artifacts.js, validate.js, Log.js) and path changes (files.js, session_vars.js, set_sources_path.js, scope.js) related to the new notifications feature? For clarity, I'd suggest either putting something about these changes in the PR description or moving them to separate PR(s).
| const argv = require(`minimist`)( process.argv.slice(2) ); | ||
| const artifacts_path = files.make_artifacts_folder( argv.path ); | ||
|
|
||
| const artifacts_path = files.make_artifacts_folder(); |
There was a problem hiding this comment.
nit: argv is no longer used -- consider either cleaning it up or (if this was accidental) restoring it as an arg to make_artifacts_folder
There was a problem hiding this comment.
Great point, thank you!
I realize you have no context, but I'm going to think about this "out loud", so if you do have thoughts I'd appreciate them. tl;dr: I think I could bring it back to add flexibility without any particular downside. [I think I should remove argv considering how session_vars finds the config path now, though I'm still not sure I'm a fan.]
If I recall correctly, I had meant to remove it. I think the caller is now meant to make sure the root of the command is where the artifacts folder should be. In ALKiP (a project that uses this lib), for example, the cwd argument for subprocess ensures the root is in /tmp. I'm actually not sure I like it as the behavior is a bit hidden. I remember having trouble wrangling the root of the path for ALKiP for some reason, though, and landing on this solution. Seems to me like I could have both without a problem. [Going to keep using cwd for now, though, since session_vars is strictly using cwd with no other arguments. It makes sense I suppose. We'd otherwise have to manage an additional env var. See session_vars.get_runtime_config_path().]
[Note to self: Worth adding some of these notes to the docs.]
| // Save Scenario data in Scenario folder | ||
| // '@alkiln @generated' | ||
| // console.log( JSON.stringify( scenario ) ); |
There was a problem hiding this comment.
question/nit: did you mean to commit these comments?
There was a problem hiding this comment.
Nice catch!
| // Save Scenario data in Scenario folder | |
| // '@alkiln @generated' | |
| // console.log( JSON.stringify( scenario ) ); |
| { | ||
| "name": "@suffolklitlab/alkiln", | ||
| "version": "5.15.4", | ||
| "version": "5.15.0-feat-news-17", |
There was a problem hiding this comment.
question (non-blocking): just to satisfy my own curiosity, what's going on with the version number here? (in particular, why did the patch version number drop from 4 to 0?)
There was a problem hiding this comment.
No problem: I just manage branch versions based off of their base branch. When I first diverged from the default branch, the version was 5.15.0, that's all. I'm curious to hear if you've seen other methods!
| scope.paths.scenario_report = `${ scope.paths.scenario }/report.txt`; | ||
| // If it's a generated Scenario, save the `.feature` file in here | ||
| // GENERATED_FILES_FOLDER_NAME | ||
| if ( scenario.gherkinDocument.uri.includes("_alkiln_generated") ) { |
There was a problem hiding this comment.
nit: _alkiln_generated is a magic string, ideally would be defined in a more maintainable location. (Where did it come from, anyway? I don't see any other references to it in this PR)
There was a problem hiding this comment.
Good catch here too. The name is already in globals.js and I should be using that instead. I made a variable for it and everything! Looks like I don't need a separate variable for that atm anyway.
| if ( scenario.gherkinDocument.uri.includes("_alkiln_generated") ) { | |
| if ( scenario.gherkinDocument.uri.includes(globals.generated_files_folder_name) ) { |
| * Note that the function prints the value to the console before returning the | ||
| * value. This is the only way ALKilnInThePlayground can get the value. |
There was a problem hiding this comment.
question: why is this? Seems cleaner to use a temp file; is that not feasible for some reason?
| for ( let subhead of shuffled_subheads ) { | ||
|
|
||
| if ( subhead.includes(`!`) && used_exclamation ) { continue; } | ||
| if ( subhead.includes(`?`) && used_question ) { continue; } | ||
| if ( subhead.includes(`"`) && used_quotes ) { continue; } | ||
| if ( subheads_used[ subhead ]) { continue; } | ||
|
|
||
| if ( subhead.includes(`!`)) { used_exclamation = true; } | ||
| if ( subhead.includes(`?`)) { used_question = true; } | ||
| if ( subhead.includes(`"`)) { used_quotes = true; } | ||
|
|
||
| final_subhead = subhead; | ||
| subheads_used[ subhead ] = true; | ||
| } |
There was a problem hiding this comment.
suggestion: it feels like it would be a little cleaner to refactor this into get_shuffled_subheads by just ensuring that a max of 1 subhead with each checked char (and no duplicate subheads) are added to the return array. Then in this function, you could just pop or shift an element off the array to pass to get_one_articles_parts
| let html_paragraphs = []; | ||
| for ( let one_paragraph of paragraphs ) { | ||
| html_paragraphs.push(`<p class="body_copy">${ one_paragraph }</p>`); | ||
| } | ||
| return html_paragraphs; |
There was a problem hiding this comment.
suggestion: this could be simplified to:
| let html_paragraphs = []; | |
| for ( let one_paragraph of paragraphs ) { | |
| html_paragraphs.push(`<p class="body_copy">${ one_paragraph }</p>`); | |
| } | |
| return html_paragraphs; | |
| return paragraphs.map(paragraph => `<p class="body_copy">${ paragraph }</p>`); |
| if ( typeof list_or_str === `string` ) { | ||
| indent_str = ` `.repeat( indent ); | ||
| return [ indent_str + list_or_str ]; | ||
| } | ||
|
|
||
| let flattened = []; | ||
| for ( let nested_str_or_list of list_or_str ) { | ||
| let result = indent_and_flatten_html_list( | ||
| nested_str_or_list, | ||
| indent + 1 | ||
| ); | ||
| // // .concat() feels evil because it accepts a string as well | ||
| // flattened = flattened.concat( result ); | ||
| flattened.push( ...result ); | ||
| } | ||
|
|
||
| return flattened; |
There was a problem hiding this comment.
suggestion: I think this could be simplified to:
| if ( typeof list_or_str === `string` ) { | |
| indent_str = ` `.repeat( indent ); | |
| return [ indent_str + list_or_str ]; | |
| } | |
| let flattened = []; | |
| for ( let nested_str_or_list of list_or_str ) { | |
| let result = indent_and_flatten_html_list( | |
| nested_str_or_list, | |
| indent + 1 | |
| ); | |
| // // .concat() feels evil because it accepts a string as well | |
| // flattened = flattened.concat( result ); | |
| flattened.push( ...result ); | |
| } | |
| return flattened; | |
| return list_or_str.flatMap(nested_str_or_list => | |
| Array.isArray(nested_str_or_list) | |
| ? indent_and_flatten_html_list(nested_str_or_list, indent + 1) | |
| : ` `.repeat(indent) + nested_str_or_list | |
| ); |
| } | ||
|
|
||
|
|
||
| function get_semver_parts( version_str ) { |
There was a problem hiding this comment.
suggestion: Consider using a 3rd party library to replace all your semver-related functions if you haven't already (example). Since this is neither related to the core ALKiln logic nor (it seems) something ALKiln needs to go outside the semver spec for, probably better to let someone else maintain it
| // If we switch to module (import) instead of common (require), use | ||
| // https://nodejs.org/api/esm.html#importmetafilename for file path | ||
| let most_recent_file_sha = execSync( | ||
| `git rev-list -1 HEAD -- "${ __filename }"` |
There was a problem hiding this comment.
question: this is running on users' servers, right? Is it safe to assume they have git installed and have cloned the ALKiln repo locally?...
| const log = new Log({ path: artifacts_path, context: `artifacts` }); | ||
| log.info({ code: `ALK0284`, context: `artifacts`,}, | ||
| `Created the artifacts folder at "${ artifacts_path }"` | ||
| ); | ||
|
|
||
| // This is just for artifacts, not any other config values. Leave the config | ||
| // Project name value as it is. Local developers find it useful to re-use it. |
There was a problem hiding this comment.
What does "This" mean, Past Self? I think it meant that saving the artifacts path name here is unique in some way. Maybe because it's updated with every run of the tests. If so, we should write documentation about which config values get changed and when they get changed. Suggestion:
Changing config values:
- Artifacts folder: name is different with each test run since artifacts are unique to each test run.
- Project name: the env vars determine the Project name. Local devs often re-use the same Project. Other environments, like GitHub or ALKiP are one-use and manage their own Project name value.
Remove comment from code here:
| const log = new Log({ path: artifacts_path, context: `artifacts` }); | |
| log.info({ code: `ALK0284`, context: `artifacts`,}, | |
| `Created the artifacts folder at "${ artifacts_path }"` | |
| ); | |
| // This is just for artifacts, not any other config values. Leave the config | |
| // Project name value as it is. Local developers find it useful to re-use it. | |
| const log = new Log({ path: artifacts_path, context: `artifacts` }); | |
| log.info({ code: `ALK0284`, context: `artifacts`,}, | |
| `Created the artifacts folder at "${ artifacts_path }"` | |
| ); | |
| // Store path name for this Scenario's individualized report | ||
| scope.paths.scenario_report = `${ scope.paths.scenario }/report.txt`; | ||
| // If it's a generated Scenario, save the `.feature` file in here | ||
| // GENERATED_FILES_FOLDER_NAME |
There was a problem hiding this comment.
| // GENERATED_FILES_FOLDER_NAME |
|
|
||
| const GENERATED_FILES_FOLDER_NAME = globals.generated_files_folder_name; |
There was a problem hiding this comment.
| const GENERATED_FILES_FOLDER_NAME = globals.generated_files_folder_name; |
|
Thanks for the excellent and detailed review! I've finally started in on this, though it'll stay here a while longer (see below).
Good insticts! The logging and path changes were indeed meant to be in a separate PR and I'll move them there and deal with those first before addressing the notification feature, so this PR is going to end up sitting on the back burner a little while longer unfortunately. And will probably run into merge conflicts unless I make a whole new PR, which I won't because I don't want to lose this awesome review. Some days you can't have it both ways
I think it's understandable without too much further context. There are 4 environments in which ALKiln can run and ALKiP is just one of those. As such, though you'd never want to install ALKiP without ALKiln, you may very well want to install ALKiln without ALKiP. At least, we have some users who do that. |
In this PR, I have:
TODO:
Reason for this PR
[Early PR for quick top-level sanity check review, failing tests are fine for now.]
Summary: Add notifications to ALKilnInThePlayground (ALKiP) for ALKiln changes
Details:
This is a testing framework. One of the environments in which it runs is on a test author's own server. ALKiP is a package of mine that helps authors runs these tests on their server. I work hard to ensure backwards compatibility, but it can be useful to keep both up to date with the other and sometimes to notify authors of other changes to their server that might affect how ALKiP is running. It's hard for authors to tell which versions match up with each other and when to update in general.
This ALKiln PR generates HTML that ALKiP can use to add notifications about relevant changes to ALKiln, to the author's server, or about whatever else ALKiln thinks is helpful. We will use notifications sparingly.
Demo of the visual appearance of a notification. Visual preview:
Links to any solved or related issues
Closes #1014
Any manual testing I have done to ensure my PR is working
Publishing to npm and testing on ALKiP