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: add access, fix provenance if new & unscoped #305

Merged
merged 18 commits into from
May 25, 2023

Conversation

AlanSl
Copy link
Contributor

@AlanSl AlanSl commented May 23, 2023

closes #301

This follows on from #302 (I started a new branch and PR based on that one as we're both on personal forks) and does two related things:

  • Allows users to manually set the access control of their package in the input options, like access: public or access: restricted
  • Fixes Can't release a newly created package with provenance #301 and allows never-published unscoped packages to be published with provenance in their first release, by inserting --access: public if and only if:
    • the user hasn't specified access control in any way, and
    • the package is unscoped (therefore, inherently public and cannot be private / restricted), and
    • the package hasn't been published before (so NPM's provenance feature would fail to see it as public unless we do this)

This would be a minor version bump on the action: the access control is a new feature, there's no breaking change or requirement to use the new feature because the provenance fix only has an affect when the package would have been public anyway.

Here's an example of an unscoped package published for the first time with provenance using this, without explicitly (redundantly) specifying the package to be public: https://www.npmjs.com/package/alansl-new-release-tester-2/v/0.1.0


@simoneb looks like I can't add you via "assign reviews" so I'll ping you here

src/utils/packageInfo.js Show resolved Hide resolved
@@ -90,15 +100,18 @@ tap.test(
'pack',
'--dry-run',
])
t.pass('npm pack called')
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 added a lot of these as without at least one test, Tap's output doesn't say which test in a file failed

Copy link
Member

Choose a reason for hiding this comment

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

mhh interesting, I wasn't aware of that actually and I'm somewhat surprised, but ok tap does have some weird behaviors and I never quite found the output very readable, so I'm good with this change

Copy link
Member

@simoneb simoneb left a comment

Choose a reason for hiding this comment

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

A few minor code changes if you don't mind, approving to avoid blocking. Overall LGTM, thanks for all the work and testing

src/release.js Outdated Show resolved Hide resolved
src/release.js Outdated Show resolved Hide resolved
src/release.js Outdated Show resolved Hide resolved
src/utils/provenance.js Outdated Show resolved Hide resolved
@AlanSl
Copy link
Contributor Author

AlanSl commented May 24, 2023

Comments all make sense, I've simplified the options overrides and moved that fixed array to const.js with other constants

Copy link
Member

@simoneb simoneb left a comment

Choose a reason for hiding this comment

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

A few more comments. Would you mind testing the weird tap behavior in isolation to make sure we're not looking at a red herring? I would be surprised if an exception being thrown in a test (and not caused by a failing tap assertion) resulted in tap not printing the test where it occurred.

src/release.js Outdated
@@ -100,22 +100,41 @@ module.exports = async function ({ github, context, inputs }) {
const opticToken = inputs['optic-token']
const npmToken = inputs['npm-token']
const provenance = /true/i.test(inputs['provenance'])
const access = inputs['access']

// Can't limit custom action inputs to fixed options like "choice" type in a manual action
Copy link
Member

Choose a reason for hiding this comment

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

I think this comment is somewhat redundant as it's fairly obvious that you can't restrict what inputs are provided to an action

Comment on lines 86 to 88
const optionAdjustments = await getAccessAdjustment(publishOptions)

return optionAdjustments ?? {}
Copy link
Member

Choose a reason for hiding this comment

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

can we simplify this logic (no need to return an empty object) and rename the function to reflect better what it's doing (it's returning provenance-related publish options)


const packageInfo = await getPublishedInfo()
const packageName = packageInfo?.name
// Package has not been published before
if (!packageName) {
Copy link
Member

Choose a reason for hiding this comment

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

nit: can we make this condition depend on packageInfo instead of packageInfo?.name? then, inside this conditional, we can confidently say that packageInfo.name exists

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤔 it's probably impossible in real life fornpm view --json to return an object that had no name property, but if it did and we did this, further down we'd exec npm --view undefined@x.y.x.

Can simplify it to if (!packageInfo?.name) return true(and ${packageInfo.name}@${version} below) I guess, that'd still be type safe for what the external service returns.

Copy link
Member

Choose a reason for hiding this comment

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

fair enough

error: new Error('code E418 - unexpected teapot'),
})

t.rejects(mocks.getPublishedInfo, /teapot/)
Copy link
Member

Choose a reason for hiding this comment

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

when you make async assertions (such as .rejects or .resolves), you need to either return or (preferably, in my opinion) await the result of the assertion, otherwise the assertion will be a noop

Copy link
Contributor Author

@AlanSl AlanSl May 24, 2023

Choose a reason for hiding this comment

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

Makes sense.

While mopping up my own instances of this, I've found a few pre-existing examples where I think tests aren't behaving as intended, e.g. there's several with a pattern like this in the execWithOutput tests from a few months ago:

    t.resolves(execWithOutputModule.execWithOutput('ls', ['-al']), output)
    execStub.calledWith('ls', ['-al'])

I think these are intended to be like this:

    await t.resolves(execWithOutputModule.execWithOutput('ls', ['-al']), output)
    t.ok(execStub.calledWith('ls', ['-al']))

...because as previously written, the execStub.calledWith will fire before the async exec actually happens, and just returns false into the void with no effect? I might fix these in a small separate PR.

There are also quite a lot of preexisting tests that end with unawaited unreturned t.rejects or t.resolves like the one above did.

Copy link
Member

Choose a reason for hiding this comment

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

yes please, any async tap assertions need to be awaited for them to have any effect

async t => {
t.throws(
() => checkProvenanceViability(),
t.rejects(
Copy link
Member

Choose a reason for hiding this comment

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

same as previous comment. you've turned a sync assertion into an async one, hence you have to await the promise it returns

@@ -90,15 +100,18 @@ tap.test(
'pack',
'--dry-run',
])
t.pass('npm pack called')
Copy link
Member

Choose a reason for hiding this comment

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

mhh interesting, I wasn't aware of that actually and I'm somewhat surprised, but ok tap does have some weird behaviors and I never quite found the output very readable, so I'm good with this change

test/publishToNpm.test.js Outdated Show resolved Hide resolved
@AlanSl AlanSl requested a review from simoneb May 24, 2023 15:15
@AlanSl
Copy link
Contributor Author

AlanSl commented May 24, 2023

@simoneb I think I responded to all the comments, ready for re-review / merge (I don't have access to merge it myself)

@simoneb simoneb merged commit 71aae61 into nearform-actions:main May 25, 2023
@github-actions github-actions bot mentioned this pull request Jun 2, 2023
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.

Can't release a newly created package with provenance
2 participants