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

Rework our version matching algorithm #217

Merged
merged 20 commits into from
Jul 21, 2023
Merged

Rework our version matching algorithm #217

merged 20 commits into from
Jul 21, 2023

Conversation

paulo-ferraz-oliveira
Copy link
Collaborator

@paulo-ferraz-oliveira paulo-ferraz-oliveira commented Jun 23, 2023

This:

  • bumps dependencies' versions to their latest, where appropriate
  • trims GitHub Actions' workflows, where appropriate
  • trims package.json, where appropriate
  • tweaks getVersionFromSpec/2 to improve on version matching
  • adapts test and CI

- run: npm install
- run: npm run build
- run: npm run format
- run: npm install -g markdownlint-cli
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was moved to package.json which means this whole npm ... pipeline can simply be as it is proposed here.

Comment on lines -106 to -116
- elixir-version: '1.10.3'
otp-version: '22.3.4.1'
os: 'ubuntu-20.04'
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We find this above, already, with version-type: strict.

Comment on lines -16 to -20
"husky": {
"hooks": {
"pre-commit": "npm run format -- --check && npm run build && git add dist/"
}
},
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not really used, I guess. npm run build-dist does it all.

Comment on lines -32 to -35
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsx-a11y": "6.6.1",
"eslint-plugin-react": "7.31.10",
"husky": "8.0.1",
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not really used, so we can trim down a few deps.

@@ -184,13 +185,16 @@ async function getElixirVersion(exSpec0, otpVersion0, hexMirrors) {
const otpVersion = otpVersion0.match(/^([^-]+-)?(.+)$/)[2]
const otpVersionMajor = otpVersion.match(/^([^.]+).*$/)[1]
const elixirVersions = await getElixirVersions(hexMirrors)
const semverVersions = Array.from(elixirVersions.keys()).sort()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is now done inside getVersionFromSpec/2, for all consumer functions, as to centralised behaviour and make it more consistent.

Comment on lines -232 to +233
return maybePrependWithV(gleamVersion, gleamVersion)
return maybePrependWithV(gleamVersion)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The 2nd argument had no value, as it wasn't accepted, in any case.

@@ -300,7 +309,7 @@ async function getElixirVersions(hexMirrors) {
.forEach((line) => {
const elixirMatch =
line.match(/^v?(.+)-otp-([^ ]+)/) || line.match(/^v?([^ ]+)/)
const elixirVersion = maybePrependWithV(elixirMatch[1])
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is no longer required, since internally all versions will be stripped of v and it'll only be added when required for external requests.

return rebar3VersionsListing
}

function isStrictVersion() {
return getInput('version-type', false) === 'strict'
}

function getVersionFromSpec(spec, versions, maybePrependWithV0) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Most of the big changes are in this function... and maybeCoerced/1 below.

}

return v
return version || null
}

function maybeCoerced(v) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Most of the big changes are in this function... and getVersionFromSpec/2 above.

@starbelly
Copy link
Member

It is my experience that it's rare the development community at large targets versions like 25.3.2.1, preferring to stay at the 25.3.x level.

Yeah, I agree with that, but the fact remains still that even 25.3.1 is not semver in the case of OTP. However, I think it's fair to say it can be treated like that. I would agree this is a breaking change. So, we're thinking this would result in a new major version then, is that correct?

@paulo-ferraz-oliveira
Copy link
Collaborator Author

paulo-ferraz-oliveira commented Jun 24, 2023

It'd probably result in a breaking change, yes, depending on:

  • whether we consider it to be a bug (which it is since we've not been handling it properly), or
  • we consider it to be a new feature we want the action to present.

I "think" I can try to fit the x.y.z.a versions in the mix (maybe?), but I tried the other day and the solution got so convoluted I rolled back some decisions: I also don't like that I'm forced to write 25.3.2.2, strict, because my consumer's expectation is 25.3.2 is whatever is before 25.4.0, but... Now I got (merge) conflicts, I got solve those and we can continue discussing this to see what our common expectation is.

Edit: Ok, so I'm trying a new approach where I compare version suffixes to a fixed version.

@paulo-ferraz-oliveira paulo-ferraz-oliveira changed the title Restrict input to SemVer, unless version-type: strict Rework our version matching algorithm Jun 24, 2023
@paulo-ferraz-oliveira
Copy link
Collaborator Author

paulo-ferraz-oliveira commented Jun 25, 2023

I rebased to resolve merge conflict and increased complexity for getVersionFromSpec/2 (hopefully not by much) so we can keep previous behaviour but make the code easier to maintain, also...

Edit: also, since the last commit, I moved back most changes in the .test.js module, so we make sure whatever was there works as-was, but we have new behaviour working properly too.

Comment on lines -170 to -172
if (isVersion(otpSpec0)) {
otpSpec = `OTP-${otpSpec0}` // ... it's a version!
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The result of this block was never used. I don't know why static analysis wouldn't find this...

Copy link
Member

Choose a reason for hiding this comment

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

Needs hank.

Comment on lines 530 to 560
function xyzabVer(pref, suf) {
// This accounts for stuff like 6.0.2.0.1.0, as proposed by Erlang's
// https://www.erlang.org/doc/system_principles/versions.html
const dd = '\\.?(\\d+)?'
return new RegExp(
`${pref}v?(\\d+)${dd}${dd}${dd}${dd}${dd}(?:-rc\\.?\\d+)?(?:-otp-\\d+)?${suf}`,
)
}

Copy link
Collaborator Author

@paulo-ferraz-oliveira paulo-ferraz-oliveira Jun 25, 2023

Choose a reason for hiding this comment

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

This function, and its callers, will probably be the "most difficult bits" to maintain, but the regexps here are pretty relaxed, too...

@paulo-ferraz-oliveira paulo-ferraz-oliveira requested review from starbelly and removed request for starbelly July 10, 2023 21:26
@paulo-ferraz-oliveira
Copy link
Collaborator Author

@starbelly?

@starbelly
Copy link
Member

Oof! Conflicts @paulo-ferraz-oliveira

Copy link
Member

@starbelly starbelly left a comment

Choose a reason for hiding this comment

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

@paulo-ferraz-oliveira This LGTM. I'd be in favor of merging and a delay on the release, sound good?

@paulo-ferraz-oliveira
Copy link
Collaborator Author

Sure. We can merge and delay release. That'll give me a chance to update the other pull request I have opened.

We want the most important things to fail first and prevent the
other ones from executing

e.g. if your dist/ is not updated, there's no point seeing the tests fail
We'll deal with all this in a centralized place to make
it easier to reason on the code
1. stop accepting maybePrependWithV0, since this is only used in specialized
   cases
2. sort versions internally (don't expect it to come sorted)
3. compare rc/strict and .includes in a single go (don't separate these)
4. don't expect already coerced version arrays, coerce them when required
   (the maybeCoerced version had changed already, which means we're smarter
   at putting stuff inside the version array)
5. raise an exception if a semver-invalid version is not flagged as strict
We cheat on the semver matching:
1. we keep an ordered list of versions that respect e.g. 22.3.4
2. if we match 22.3.4 when fetching a version, we get the last value
   from the list of versions that respect it, e.g. 22.3.4.2.1.0
   (since this is ordered, it should work as previously expected)

This increases code complexity for getVersionFromSpec,
but hopefully not by much...

We also remove throw-based test cases (non-versions will fail later,
with null), and add some tests to prove our need code.
But still keep them useful
@paulo-ferraz-oliveira
Copy link
Collaborator Author

Force-pushing to resolve merge conflicts. If no actions show issues I'm squash-merging.

@paulo-ferraz-oliveira paulo-ferraz-oliveira merged commit f6a73a7 into erlef:main Jul 21, 2023
@paulo-ferraz-oliveira paulo-ferraz-oliveira deleted the feature/minor-tweaks branch July 21, 2023 19:56
@josevalim
Copy link

Thank you @paulo-ferraz-oliveira! It seems this PR removed support for maint/master from OTP git, which Elixir relies on. Was it intentional?

@josevalim
Copy link

Nevermind, PR sent here: #241 :)

@paulo-ferraz-oliveira
Copy link
Collaborator Author

It seems this PR removed support for maint/master from OTP git, which Elixir relies on. Was it intentional?

👋 It wasn't. I'll look at the pull request.

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.

3 participants