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

Automatically infer stable and dev versions based on semver spec #10

Merged
merged 11 commits into from
Sep 12, 2022

Conversation

toebeann
Copy link
Collaborator

@toebeann toebeann commented Sep 6, 2022

Changes in this pull request

  • Builds/depends on Use semver package for handling semantic versioning #9
  • Added the ability to automatically infer whether a version is stable or dev based on the semver spec, i.e.:
  • Changes to the rendered version dropdown (these changes do not affect symlinks):
    • When there are no stable versions with documentation, do not display the stable version in the selector, instead displaying dev at the top of the list
    • When the latest stable version is considered newer than the latest dev version, do not display dev in the selector list
  • It is still possible to expliticly mark a version as stable or dev, but the default behaviour when not explicitly set will be to automatically infer the versions

Reasoning

Building on the work of #9, it should be relatively simple to automatically and reliably infer whether a given version number is stable or dev based on the semver spec, without a user needing to update their typedoc config.

We can also use the previous stable or dev symlinks to infer which is the latest stable version when we are building docs for a dev version, and vice versa.

Also, when a stable version is released with a version number higher than the latest dev version, the dev version can be considerd 'stale' and ignored. The docs for the old dev version will remain available, but the dev symlink should no longer point to them.

This makes for a much simpler experience for the developer building the docs, and a more intuitive version selector for doc readers.

Examples

Note that for all the below examples, all typedoc-plugin-versions options were left at their defaults, i.e. fully automatic.

  • A package that has not yet released a version marked as stable:
    image
    The stable symlink still works as you would expect (pointing to the latest version), it is just not shown in the dropdown
  • A package having just released their first stable version:
    image
    The dev symlink still works as you would expect (pointing to the latest version), it is just not shown in the dropdown.
  • A package with a previously released version 1.0.0, now releasing version 1.1.0-alpha.1
    image
    Here, the stable symlink points to version 1.0.0, and the dev and v1.1 symlinks points to version 1.1.0-alpha.1
  • A package releasing version 1.1.0, which supersedes the prerelease version 1.1.0-alpha.1:
    image
    Now, stable, dev and v1.1 symlinks all point to version 1.1.0
  • A package with a previously released stable version 1.2.0, now releasing the prerelease version 1.2.1-alpha.1:
    image
    Here, stable and v1.2 both point to the previous version 1.2.0, while only dev points to 1.2.1-alpha.1

Implementation details

  • Improved dropdown version selector logic
  • Refactored semver-related functions to take prerelease versions into account
  • makeStableLink and makeDevLink now merged into single function makeAliasLink to be more DRY
  • The default value of the 'stable' and 'dev' options is now 'auto'
  • Updated stubs and tests as necessary

Please note that as this package's version is less than 1.0.0, it will be considered dev only when building docs for it. This also means that the stub for makeJsKeys output will need updating when this package releases an automatically inferred stable version (i.e. >=1.0.0 without a prerelease label), or the tests will fail.

@toebeann toebeann force-pushed the improved-stable-and-dev-links branch from 0ae333f to 136dc7b Compare September 6, 2022 04:35
@toebeann toebeann changed the title Automatically infer 'stable' and 'dev' versions based on semver spec Automatically infer stable and dev versions based on semver spec Sep 6, 2022
@toebeann
Copy link
Collaborator Author

toebeann commented Sep 6, 2022

Addendum to my note:

Please note that as this package's version is less than 1.0.0, it will be considered dev only when building docs for it.

However, if you manually mark a version as stable as you presently do, then it will be considered stable :)

@toebeann
Copy link
Collaborator Author

toebeann commented Sep 6, 2022

It is worth noting that as of the current state of my modifications, if you build a doc for version e.g. 2.0.0, then later decide to rebuild docs for an earlier version e.g. 1.2.0, that earlier version will be marked as stable if you leave everything on auto. This is then fixed by rebuilding the docs for the latest version. I believe this is how it behaves without my modifications, also - I just haven't gotten around to addressing that in this PR as it's only a minor inconvenience, and not the intended use case (where we only ever build versions with higher numbers - except perhaps dev builds vs. stable builds, which behave appropriately in auto mode with this PR).

In a later PR, it should be possible to eliminate the need to rebuild the latest docs in auto mode with some simple additional logic. However, if you like, I could add it as a change in this PR as well - I just tend to prefer to keep my PRs as tightly focused in scope as possible, though I will admit, this PR is quite tightly coupled with #9 😅

@toebeann
Copy link
Collaborator Author

toebeann commented Sep 6, 2022

I have made a PR between the two branches I used for development on my fork to make it easier for you to compare the changes between them: toebeann#1

@citkane
Copy link
Owner

citkane commented Sep 6, 2022

In a later PR, it should be possible to eliminate the need to rebuild the latest docs in auto mode with some simple additional logic.

Yes, I think this quirk will be OK for now and just added somewhere as a @todo, lest we forget...
This PR will move the whole thing into a new level of sophistication, whereas before it was a rather blunt, explicit thing. I am glad that you have stated, and I agree, that the behavior remains explicit when the user sets the 'dev' and 'stable' options.

I can have a better read and understanding of your new code once #9 is merged, and will wait till then. (give me a ping when you are done with the comments) A few things in mind for this with corresponding tests:

  • could there be unforeseen behavior if only 'dev' or 'stable' options are set?
  • will the default behavior behave as expected if a previous document build folder is deleted? (probably yes unless you have introduced some kind of memory)

@toebeann
Copy link
Collaborator Author

toebeann commented Sep 6, 2022

A few things in mind for this with corresponding tests:

  • could there be unforeseen behavior if only 'dev' or 'stable' options are set?

Hmm, I don't believe so, but you're right it would be a nice idea to write tests for this, or at the very least do some testing by hand. I'm not the best when it comes to writing tests for this kind of thing, but I will give it a try. (I confess, as a dev I have had very bad habits when it comes to writing tests in the past i.e. generally avoiding them - finally starting to make a good habit of it now but I'm still more inline with "Test Later Development" than "Test Driven Development" 😅)

  • will the default behavior behave as expected if a previous document build folder is deleted? (probably yes unless you have introduced some kind of memory)

I haven't tested this but I would also expect that probably yes it should behave the same as it currently does.

I had previously considered the idea of introducing a JSON metadata file (i.e. "some kind of memory") that the plugin would produce on each docs build, and store it inside the doc folder for each build, which would mean it would get deleted (and therefore ignored) when deleting that build's folder.

I realised however while developing the branch that it would be much smarter (at least, more efficient) to simply rely on the pre-existing symlinks as the only history we need, since most of the time we only need to know what was considered dev and stable on the previous run, and reading where the corresponding symlinks currently point to will give us that info. It's an upgrade over how it currently behaves, but it isn't perfect. It's "good enough" for most use cases, however.

However, while writing this, I have now also realised that I didn't test whether the path the symlink is pointing to still exists, so that is an edge case not yet addressed in this PR, i.e.:

  • if we e.g. delete the most recent docs folder (which was dev), and then build a new one (which is stable), the dev symlink will potentially still point to the now deleted path, and the only way to address this would be to explicitly set dev for one run (can be removed after)
  • and vice versa if you switch stable and dev

I'll need to test whether this actually happens, but it is a consideration I hadn't thought of so potentially something I let slip through.

I feel like potentially the best way to effectively address this edge case would be to actually introduce the JSON metadata files as I had originally intended, and to make the logic even more "sophisticated" (read: complex and annoying to maintain 😅) than at present.

I'll mark this PR as draft while I address these concerns.

@toebeann toebeann marked this pull request as draft September 6, 2022 18:42
@citkane
Copy link
Owner

citkane commented Sep 7, 2022

No panic on this. I invited you as a collaborator, so feel free to release 0.2.0 with the sorting fixed (and hold this PR) if that helps you with your other projects. I am thinking of implementing a changelog, but not sure sure yet of the best way. Your thoughts are welcome.

My "other job" is as architect (the building kind), so a broad analogy for test driven design is like trying to create a beautiful space by getting the waterproofing details right first... Not happening. But yet - get the waterproofing details wrong and very soon the beautiful space is meaningless. Oh what philosophy this could spawn 😄

My head is elsewhere ATM, and I want to give this PR the attention it deserves. I will come back to it, but work away as you see fit.

My gut instinct is, that if you want the behavior to be able to re-build earlier versions which influence the stable symlink, memory will be required. Probably best if this is one metadata structure in a json at the root doc level (next to the doc folders and the index.html redirect). This way, the user can see and understand what is going on without having to dig down.

The plugin run could kick off by auditing this file to determine how the folder landscape has changed, which would determine further paths of action, and then updating it to the new state.

@toebeann
Copy link
Collaborator Author

toebeann commented Sep 9, 2022

Just wanting to update as timing has been a bit unfortunate; I'm a bit under the weather at the moment so unfortunately put this on hold for now, will hopefully be back at it in a matter of days if not sooner.

@toebeann
Copy link
Collaborator Author

I am thinking of implementing a changelog, but not sure sure yet of the best way. Your thoughts are welcome.

I'm unsure on this - I've not really looked into implementing changelogs before myself, I usually just rely on people to know to look at the releases page if they're on GitHub. I've released a bunch of things on nexus mods, and there they have their own built in changelog feature and I pretty much just copy PR titles over from my GitHub repos.

I wouldn't be surprised to find out that a GitHub action exists to automatically generate a CHANGELOG.md file, but I've not looked into it. Then you could just link to it at the end of the README. In which case, you would want to make sure any important change/bugfix is handled only via PRs and never via direct commits on dev/main.

My gut instinct is, that if you want the behavior to be able to re-build earlier versions which influence the stable symlink, memory will be required. Probably best if this is one metadata structure in a json at the root doc level (next to the doc folders and the index.html redirect). This way, the user can see and understand what is going on without having to dig down.

The plugin run could kick off by auditing this file to determine how the folder landscape has changed, which would determine further paths of action, and then updating it to the new state.

Yeah, I agree with you on this. I'll go ahead and implement as part of this PR.

I have some other ideas for features to implement where it might be an idea to discuss them with you before I start working on them in case you have thoughts. I'll open issues for them so we can discuss them while keeping this PR on-topic.

On a related note, if you have your own feature ideas or a list of things that need to be done before this plugin can reach v1.0, it might be an idea to open issues for them - then when someone has free time, we can work towards v1.0!

@toebeann toebeann self-assigned this Sep 11, 2022
@toebeann toebeann marked this pull request as ready for review September 11, 2022 12:30
@toebeann
Copy link
Collaborator Author

toebeann commented Sep 11, 2022

@citkane, I have updated this PR to take care of the issues that were brought up:

  • metadata is now stored in a .typedoc-plugin-versions, encoded as minified JSON, stored in the docs root, here is sample output from a bunch of test runs:
    {"versions":["v1.2.0","v1.1.0","v1.1.0-alpha.1","v1.0.0","v0.2.0","v0.1.3","v0.0.1"],"stable":"v1.2.0"}
    Note that in this case there is no dev, that is because this was generated with dev set to auto and there is no dev version newer than the stable version. The dev symlink simply mirrors the stable symlink in this case.
  • handles cases where only one of stable or dev are set as you would expect
  • deleting old versions and rebuilding is not an issue, metadata and symlinks are automatically taken care of and updated
  • building old versions works as expected, i.e. building 1.1.0 after 1.2.0 will leave 1.2.0 marked as stable (unless you explicitly set stable in the typedoc versions config)
  • the original examples generated above remain replicable

src/index.ts Outdated Show resolved Hide resolved
Copy link
Owner

@citkane citkane left a comment

Choose a reason for hiding this comment

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

That all works as expected, test coverage is good and style is quality.

It was difficult to get into the nitty gritty when the single PR is so big (that is not criticism - just a statement of fact 😄 ). I like the way you made one big list of all possibilities then filtered, de-duped and sorted it.

Thanks @toebeann , class job.

@citkane citkane merged commit b0dcd33 into citkane:dev Sep 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants