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

Update SPDX Expression Parsing #719

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open

Update SPDX Expression Parsing #719

wants to merge 20 commits into from

Conversation

febuiles
Copy link
Contributor

@febuiles febuiles commented Mar 21, 2024

Closes #263
Closes #670
Closes #575
Closes #635

Context

Since we introduced SPDX licenses around 2022, we've had issues dealing with SPDX expression validations due to the library we use for checking whether one expression satisfies another one.

Folks reached out to the maintainer in 2022 to fix some of these changes, but set a clear direction that does not fit our purposes anymore. The @onebeyond/spdx-license-satisfies is a fork of the original project, created by people who encountered the same issues as us.

Changes

This PR moves the Action away from spdx-satisfies.js and uses @onebeyond/spdx-license-satisfies instead to check whether an SPDX license satisfies an expression or not: The MIT license satisfies the expression MIT OR GPL-2.0, but it does not satisfy MIT AND GPL-2.0.

In the process of making these changes I:

  • Moved all the SPDX-related logic to spdx.ts.
  • Added a few TODOs to spdx.ts noting the things we still need to support.
  • Updated the tests that were using invalid SPDX identifiers.
  • Removed unnecessary stubs for SPDX license validation.
  • Updated tsconfig.json to fix a duplicate entry in the compiler options.

@febuiles febuiles self-assigned this Mar 21, 2024
@febuiles febuiles marked this pull request as ready for review March 22, 2024 13:37
@febuiles febuiles requested a review from a team as a code owner March 22, 2024 13:37
src/config.ts Outdated Show resolved Hide resolved
src/config.ts Outdated Show resolved Hide resolved
@@ -197,7 +209,7 @@ function parseConfigFile(configData: string): ConfigurationOptionsPartial {
}
return data
} catch (error) {
throw error
throw new Error(`error validating config: ${error}`)
Copy link

Choose a reason for hiding this comment

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

Suggested change
throw new Error(`error validating config: ${error}`)
throw new Error(`error validating config: ${(error as Error).message}`)

Worth casting to get the message here? Not sure what the output would be if this is an object.

Copy link
Contributor Author

@febuiles febuiles Mar 23, 2024

Choose a reason for hiding this comment

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

The reason to cast is to please the TS type checker, because error is only defined inside the catch we need to give it some hints so it knows it can call message to get the error body.

Copy link
Contributor

Choose a reason for hiding this comment

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

☝️ I think what Mitchell is pointing out is that we're missing the message call after the cast there?

const config = await readConfig()
expect(config.fail_on_severity).toEqual('critical')
})

test('it raises an error when given an unknown severity in an external config file', async () => {
setInput('config-file', './__tests__/fixtures/invalid-severity-config.yml')
setInput('config-file', '../__tests__/fixtures/invalid-severity-config.yml')
await expect(readConfig()).rejects.toThrow()
Copy link
Contributor

Choose a reason for hiding this comment

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

🤔 do these paths require the ../__tests__/ prefix or would a fixtures/ prefix work too?

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 entirely sure why (maybe jest?), but the path needs to be relative to src/, hence the change from ./ to ../:

[FAIL] it accepts an external configuration filename

    Unable to fetch or parse config file: ENOENT: no such file or directory, open '/Users/febuiles/w/dr-action/src/fixtures/no-licenses-config.yml'

Copy link
Contributor

Choose a reason for hiding this comment

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

cc @hmaurer @bteng22 thoughts on this? if its nothing, feel free to ignore 👍


expect(spdx.satisfies(license, expr)).toBe(false)
})
})
Copy link
Contributor

Choose a reason for hiding this comment

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

😍

// usually means a discrepancy in ESM/CJS.
if (e instanceof TypeError) {
throw new Error('spdx: invalid expression parser')
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🤔 should the error message instead be spdx: invalid expression or something? the parser isn't the problem here, it's the inputs right?

Also under which error conditions is it safe to swallow the error and message here and just return false as in line 22?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

should the error message instead be spdx: invalid expression or something? the parser isn't the problem here, it's the inputs right?

It's the parser in the sense that TypeError is what's raised when there's an error loading the parser. I have not seen these errors outside of local development, where they're common if you forget to npm i after bootstrapping the project.

Also under which error conditions is it safe to swallow the error

None, if this fails we should abort the run.

Copy link
Contributor

Choose a reason for hiding this comment

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

☝️ same here does that sync with your understanding @hmaurer ? we just bail if we can't parse a license, even if there may be vuln pkgs etc. found in this run?

again, I have little context/depth on DR Action at present, so if this is a non-concern, feel free to ignore 👍

@elireisman
Copy link
Contributor

Couple questions, but this is looking good so far, thanks! 🍻

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