-
Notifications
You must be signed in to change notification settings - Fork 208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fully support agoric install <dist-tag>
#4129
Conversation
165916e
to
3d8ff0f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would need to level up my npm / yarn game to feel confident about this.
Maybe @kriskowal could take a look?
scripts/dist-tag.sh
Outdated
@@ -0,0 +1,47 @@ | |||
#! /bin/bash | |||
# dist-tag.sh - manage dist-tags for NPM registry packages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
elaborate a bit on "manage"?
I'm not really fluent in bash. I could use a comment for each clump of lines, actually.
packages/agoric-cli/src/install.js
Outdated
const pj = JSON.parse(packageJSON); | ||
for (const section of ['dependencies', 'devDependencies']) { | ||
const deps = pj[section]; | ||
if (deps) { | ||
for (const pkg of Object.keys(deps)) { | ||
if (versions.has(pkg)) { | ||
if (deps[pkg] === forceSdkVersion) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have thought we need to "invalidate the cache" on a version mismatch.
I can't see where deps
is initialized in this diff, and when I looked at the whole file, I got a little dizzy. (color me lazy)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have thought we need to "invalidate the cache" on a version mismatch.
Actually, yarn
already updates packages that have changed. It's the packages whose version specifier has not changed that we need to first prune the old one, install, add the new one, and install to get it to update correctly.
Does this depend on #4120? |
Actually, no. It's still valuable even if someone has to manually publish packages and dist-tags all the time. |
3d8ff0f
to
0fc3e9b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything in here looks like it does what it says it’s supposed to, but after a couple passes, I’m still fuzzy on why it works. Is the notion that install
does a number of shallow installs and revises the package.jsons for the installed packages in-place? Is this recursive?
Would the effect be comparable to amending the dapp package.json to include resolutions
for all the agoric-sdk packages using a particular dist-tag?
packages/agoric-cli/src/install.js
Outdated
const pjson = `${subdir}/package.json`; | ||
const packageJSON = await fs | ||
.readFile(pjson, 'utf-8') | ||
.catch(_ => undefined); | ||
if (!packageJSON) { | ||
return; | ||
} | ||
const pj = JSON.parse(packageJSON); | ||
const prunedPj = { ...pj }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I struggle with naming variables that all refer to the same thing, but in different forms. My principle is that all the names should have some portion that is the same to reflect that they refer to something common, and a term that varies to indicate what’s different about them. So, for something like this, I’ve been using names like packageDescriptorBytes
, packageDescriptorText
, packageDescriptor
, and packageDescriptorPruned
. I think Json
instead of Descriptor
might be valid but not precise. I personally loathe the case convention conundrum raised by acronyms and initialisms, particularly when they run-on. And, I don’t mind some verbosity, even for local variables where the verbosity is unnecessary.
This is a recommendation.
packages/agoric-cli/src/install.js
Outdated
if (needsPruning) { | ||
pruningTodo.push(async () => { | ||
// Update on exit, in case we are interrupted. | ||
process.on('beforeExit', updatePackageJson); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume you considered and decided against framing this in terms of a finally. I don’t think it would occur to me to use the beforeExit event under any circumstances.
updatePackageJson
returns a promise that the EventEmitter will ignore. That would suggest that any error will be realized as an unhandled rejection warning. I’d consider reframing this to sink the promise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume you considered and decided against framing this in terms of a finally. I don’t think it would occur to me to use the beforeExit event under any circumstances.
It is framed in terms of a pruningP.finally(...)
. It's quite important that these updates are done even if the process is interrupted. Do you have a better mechanism at hand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there’s nothing better in the face of uncaught exceptions.
packages/agoric-cli/src/install.js
Outdated
// After all have settled, try throwing the first rejection. | ||
const firstFailure = results.find( | ||
({ status }) => status !== 'fulfilled', | ||
); | ||
if (firstFailure) { | ||
throw firstFailure.reason; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps consider using AggregateError
. That will of course be impossible inside a Compartment for now, but I do not think this is inside a Compartment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AggregateError
is not available in Node v14. Do you have a better suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the absence of AggregateError, I like to aggregate error messages, e.g.,
new Error(`Cannot x for multiple causes (${causes.map(x => x.message).join('; '))`)
But I won’t press the issue. The first cause is certainly sufficient and indeed all you’d see in a serial causal graph.
); | ||
} | ||
// This open-coding of the above yarn command is quiet and fast. | ||
const linkName = `${linkFolder}/${pjName}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you feel about path.join
? My current personal rule is not hard and fast either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless portability to older versions or Windows failures demand otherwise, I just use slashes and trust that Node.js's fs
module figures out the rest.
scripts/npm-dist-tag.sh
Outdated
# Try: `npm-dist-tag.sh` for usage. | ||
|
||
# Exit on any errors. | ||
set -e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider cargoing set -ueo pipefail
as a matter of style.
scripts/npm-dist-tag.sh
Outdated
@@ -0,0 +1,67 @@ | |||
#! /bin/bash | |||
# npm-dist-tag.sh - manage dist-tags for NPM registry packages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps add/remove/list is more evocative than manage.
priv=$(jq -r .private package.json) | ||
case "$priv" in | ||
true) | ||
echo 1>&2 "Private package, skipping npm-dist-tag.sh" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wherein the reviewer relearns that redirects can be interpolated anywhere in a command.
;; | ||
*) | ||
# Usage instructions. | ||
echo 1>&2 "Usage: $0 [lerna] <add|remove|list> [<tag>]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the distinction that lerna
means to apply in bulk to the workspaces? Would we ever not do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the distinction that lerna means to apply in bulk to the workspaces? Would we ever not do that?
Yes and yes, if we want to add/remove/list the dist-tags for just the package in the cwd.
packages/agoric-cli/src/install.js
Outdated
} | ||
// Create symlinks to the SDK packages. | ||
await Promise.all( | ||
dirPackages.map(async ([dir, pjName]) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not equivalent to packages.entries()? Can these be consolidated?
Promise.allSettled(updatesTodo.map(async update => update())), | ||
); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There’s a hazard on line 157 where a parse error will cause a reference error on 158.
0fc3e9b
to
1634180
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments addressed to the best of my ability.
;; | ||
*) | ||
# Usage instructions. | ||
echo 1>&2 "Usage: $0 [lerna] <add|remove|list> [<tag>]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the distinction that lerna means to apply in bulk to the workspaces? Would we ever not do that?
Yes and yes, if we want to add/remove/list the dist-tags for just the package in the cwd.
pkg=$(jq -r .name package.json) | ||
version=$(jq -r .version package.json) | ||
# echo "$OP $pkg@$version" | ||
|
||
# Get the second argument, if any. | ||
TAG=$2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use TRAIN_CASE
for environment variables and command-line arguments.
); | ||
} | ||
// This open-coding of the above yarn command is quiet and fast. | ||
const linkName = `${linkFolder}/${pjName}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless portability to older versions or Windows failures demand otherwise, I just use slashes and trust that Node.js's fs
module figures out the rest.
packages/agoric-cli/src/install.js
Outdated
// After all have settled, try throwing the first rejection. | ||
const firstFailure = results.find( | ||
({ status }) => status !== 'fulfilled', | ||
); | ||
if (firstFailure) { | ||
throw firstFailure.reason; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AggregateError
is not available in Node v14. Do you have a better suggestion?
packages/agoric-cli/src/install.js
Outdated
if (needsPruning) { | ||
pruningTodo.push(async () => { | ||
// Update on exit, in case we are interrupted. | ||
process.on('beforeExit', updatePackageJson); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume you considered and decided against framing this in terms of a finally. I don’t think it would occur to me to use the beforeExit event under any circumstances.
It is framed in terms of a pruningP.finally(...)
. It's quite important that these updates are done even if the process is interrupted. Do you have a better mechanism at hand?
No, it handles the old-style dapp environment which is a top-level worktree and another worktree with its own This works fine if the When a forced version (like This is the fastest way to trim out the obsolete dependencies from both the workspaces'
I don't think so. The idea is that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot profess to be able to maintain agoric install
based on this review, but the code looks like it should do as advertised. Given that hopefully agoric install
gives way to yarn install
soonish, I’m okay with this.
1634180
to
e852ee5
Compare
const versions = new Map(); | ||
const dirPackages = []; | ||
|
||
const sdkRoot = path.resolve(dirname, `../../..`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this coming from ?
This actually doesn't work for me. The |
closes: #3857
Description
If a dist-tag is specified with
agoric install <dist-tag>
, ensure we refresh the dapp'syarn.lock
dependencies.This makes it possible to build and develop a published dapp without needing the
agoric install
command (justyarn install
suffices). Indeed,npm install -g agoric
oryarn global add agoric
should be able to produce a workingagoric
command that can do everything thatyarn link-cli ~/bin/agoric
does, once this PR's version ofagoric-cli
has been published to NPM.Security Considerations
Documentation Considerations
agoric install beta
will update the workspace'syarn.lock
with the beta dependencies. From that point on, installing the dapp only needsyarn install
(thoughagoric install
will work, too).Testing Considerations
Tested manually on
dapp-oracle
.