Skip to content
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

feat!: migrate to ESM #437

Merged
merged 16 commits into from
Oct 17, 2023
Merged

feat!: migrate to ESM #437

merged 16 commits into from
Oct 17, 2023

Conversation

mdonnalley
Copy link
Contributor

@mdonnalley mdonnalley commented Oct 13, 2023

BREAKING CHANGES: ESM and node 18 minimum

Closes #400

Release Notes

Added these env vars:
<CLI>_SKIP_NEW_VERSION_CHECK: Skip the version update check
<CLI>_NEW_VERSION_CHECK_FREQ: the frequency at which the version warning should be shown
<CLI>_NEW_VERSION_CHECK_FREQ_UNIT: the unit of time used to set the frequency. Defaults to minutes (can be days, hours, minutes, seconds, milliseconds)

BREAKING CHANGES: ESM and node 18 minimum
@git2gus
Copy link

git2gus bot commented Oct 13, 2023

This issue has been linked to a new work item: W-14294408

@RealOrangeOne
Copy link
Contributor

This seems to contain my PR, but without reference or attribution. Could you cherry-pick the commit instead?

Fixes #279

This can speed up execution, reduce unnecessary network requests, and clean up log files.
Comment on lines 10 to 13
const readJSON = async <T>(file: string): Promise<{contents: T; stat: Stats}> => ({
contents: JSON.parse(await readFile(file, 'utf8')),
stat: await stat(file),
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perf: promise.all the 2 tasks, then return them in the object.

[small perf nit, but this runs before every command]

authorization = '',
} = (config.pjson.oclif as any)['warn-if-update-available'] || {}
timeoutInDays = 60,
} = config.pjson.oclif['warn-if-update-available'] || {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} = config.pjson.oclif['warn-if-update-available'] || {}
} = config.pjson.oclif['warn-if-update-available'] ?? {}

timeoutInDays = 60,
} = config.pjson.oclif['warn-if-update-available'] || {}

const warningFrequency = (config.scopedEnvVar('NEW_VERSION_CHECK_FREQ') as number | undefined) ?? frequency
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS lets you make ASsertions about what's in somebody's env (lying to the compiler), but that doesn't do any checks or conversions in the real world.

example: if their frequency was ham and the unit was sandwiches then convertToMs is going to have unhandled errors.

Also, envs would be a string anyway, so you'll need to parseInt warningFrequency, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's have some tests for handling of these envs.


// If the file was modified before the timeout, don't show the warning
if (
warningFrequency &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

confirming that if warningFrequency is set to 0 you'd short-circuit the rest of the conditional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that makes sense. Frequency of 0 causes the default behavior of seeing the warning on every command execution.

I guess the alternative is that a frequency of 0 turns the warning off and you never see it again? We already have an env var for that so I don't see a reason to duplicate it

Comment on lines 90 to 91
const {gt} = await import('semver')
if (distTags[tag] && gt(distTags[tag].split('-')[0], config.version.split('-')[0])) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: since you've already got distTags, you could check that and avoid the semver import if it weren't needed


// Update the modified time (mtime) of the version file so that we can track the last time we
// showed the warning. This makes it possible to respect the frequency and frequencyUnit options.
await utimes(file, new Date(), new Date())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the utimes op to wait on the lodash import and warning to happen first? or could it be run in parallel with the import?

].join('/')
const headers = authorization ? {authorization} : {}
await mkdir(dirname(file), {recursive: true})
await writeFile(file, JSON.stringify({current: version, headers})) // touch file with current version to prevent multiple updates
const {body} = await HTTP.get<any>(url, {headers, timeout: 5000})
await writeFile(file, JSON.stringify({...body['dist-tags'], current: version, authorization}))
const {body} = await HTTP.get<{'dist-tags': string[]}>(url, {headers, timeout: 5000})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the http.get need to wait on the mkdir/writeFile?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure - and I don't want to take the risk of changing it, especially since this script is run in a unref'd spawned process. So any performance improvements in there will never be noticed by anyone

}

export function semverGreaterThan(a: string, b: string): boolean {
return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'}) > 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool. I saw the semver removal and wondered what was going to happen here.

@mshanemc
Copy link
Member

QA Notes: created 2.1.2-qa-0 to tet with.

switched to 2.3.8 via udpate --interactive
ran org list.
› Warning: @salesforce/cli update available from 2.3.8 to 2.5.8..
Why prompt me to update to 2.5.8?

ok, let's just go with and update to 2.5.8 to see if it knows about updates beyond that.

ran org list a few times, not update suggestions.
did some debugging...mtime on the cache file is today, so it's not "stale" until Dec 16 (60 days). But the file is already 7 weeks behind.
[I think this is because I usually run things on nightly channel so my file doesn't get updated often? but somehow the mtime is updated?]

deletes the version file, run command again.
✅ version file is now correct
✅ gives correct warning

testing envs:
SF_SKIP_NEW_VERSION_CHECK=true
✅ file is not created

SF_NEW_VERSION_CHECK_FREQ=30 SF_NEW_VERSION_CHECK_FREQ_UNIT=seconds sf org list
✅ running repeatedly seems to display after > 30 seconds.

🔴 potential design flaw:

  • use of the file mtime to mark both the most recent warning emitted AND the file staleness.
    ex: you have you warn freq set to daily. each day, you get a warn and then the file mtime is set.
    File never becomes stale? So you update to an old version instead of current

@mshanemc
Copy link
Member

QA notes (2.1.2-qa.1)

update to 2.8.3
✅ gets warning when RN command is called Warning: @salesforce/cli update available from 2.8.3 to 2.12.9
last-warning file is created

delete file
✅ running a command recreates last-warning

delete both files
✅ recreated files, see warning after a few commands

SF_NEW_VERSION_CHECK_FREQ=30 SF_NEW_VERSION_CHECK_FREQ_UNIT=seconds sf org list
✅ works as expected

set latest to 2.0.0
✅ no warnings

set latest to 2.8.3 (the current version)
✅ no warnings

set latest to 2.8.4 (the very next version)
✅ warning

SF_NEW_VERSION_CHECK_TAG=nigtly SF_FORCE_VERSION_CACHE_UPDATE=true sf org list
✅ updates file

SF_NEW_VERSION_CHECK_TAG=nigtly sf org list (bad tag)
✅ no warnings, no errors

SF_NEW_VERSION_CHECK_TAG=nightly sf org list
✅ shows correct nightly update available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ability to conditionally disable? Display warning less frequently
4 participants