Skip to content

Conversation

o-l-a-v
Copy link
Contributor

@o-l-a-v o-l-a-v commented Sep 19, 2025

Description

  1. Reordered properties in schema.json so it matches the wanted order.
  2. Created new function in json.ps1 named Sort-ScoopManifestRootProperties that:
    • Sorts root properties according to schema.json properties.
    • Sorts one level deep child properties alphabetically if the parent property is of type PSCustomObject.
  3. Made formatjson.ps1 use this new function.

Motivation and Context

Closes #6491.

How Has This Been Tested?

# Path to formatjson.ps1 in branch "formatjson-sort-root-properties"
$FunctionPath = [string] 'D:\git\ScoopInstaller--Scoop\bin\formatjson.ps1'

# Path to main bucket in branch "master" pulled 2025-09-19T12:25:00+02:00
$Directory = [string] 'D:\git\ScoopInstaller--Main\bucket'

# Run format json, look at git afterwards
$ErrorActionPreference = 'Stop'
. $FunctionPath -Dir $Directory -App '*'
image

Checklist:

@o-l-a-v o-l-a-v marked this pull request as draft September 19, 2025 10:00
@o-l-a-v o-l-a-v marked this pull request as ready for review September 19, 2025 10:30
@o-l-a-v
Copy link
Contributor Author

o-l-a-v commented Sep 19, 2025

@deevus @HUMORCE @rashil2000 @z-Fng: What do you guys think?

Copy link

coderabbitai bot commented Sep 19, 2025

Warning

Rate limit exceeded

@o-l-a-v has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 37 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 04b7ce7 and 37aa459.

📒 Files selected for processing (5)
  • CHANGELOG.md (1 hunks)
  • bin/formatjson.ps1 (2 hunks)
  • lib/json.ps1 (1 hunks)
  • lib/manifest.ps1 (1 hunks)
  • schema.json (3 hunks)
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@o-l-a-v
Copy link
Contributor Author

o-l-a-v commented Sep 19, 2025

@coderabbitai review

# Convert to 4 spaces
$json = [string]($json -replace "`t", ' ')

# Overwrite file content
[System.IO.File]::WriteAllLines($file, $json)
Copy link

Choose a reason for hiding this comment

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

When JSON parsing fails, it will clear the manifest content. Should this behavior be adjusted to prevent contributors from losing their work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, maybe we should add some error handling.

$json = [PSCustomObject](parse_json -path $file)

# Sort JSON root properties
$json = [PSCustomObject](Sort-ScoopManifestRootProperties -JsonAsObject $json)
Copy link

Choose a reason for hiding this comment

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

Is it possible to sort the keys recursively with global/local order?

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

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

I don't fully understand what you're asking for here, about the local/global order.

Recursice ordering keys by the schema.json should be possible. Or just sort child keys alphabetically.

Copy link

Choose a reason for hiding this comment

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

local/global order

My description might be redundant. Jsut ignore it. Focus on recursive sorting.

I thought that when sorting keys like architecture.64bit/32bit , local order are used because the configuration file contains architecture.64bit/32bit. However, when sorting keys like architecture.64bit.url/hash, the configuration file lacks this entry, causing it to fall back to the global order.

As I'm not sure how to describe this, I called it local/global order.

Scoop/schema.json

Lines 217 to 231 in 37aa459

"architecture": {
"type": "object",
"additionalProperties": false,
"properties": {
"32bit": {
"$ref": "#/definitions/autoupdateArch"
},
"64bit": {
"$ref": "#/definitions/autoupdateArch"
},
"arm64": {
"$ref": "#/definitions/autoupdateArch"
}
}
},

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 sorting of first level child keys if parent is of type PSCustomObject. Going even deeper will be more complex. It's doable, but I think what we got now is a good start.

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

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

Maybe there are existing PowerShell or C# projects that can sort a JSON file by schema.json and handle all the complexity of going deeper we can use?

In Python there is: https://github.com/ikonst/jschon-sort.

But as I already said, I think this serves as a very good start for getting more uniform manifests.

$json = [PSCustomObject](Sort-ScoopManifestRootProperties -JsonAsObject $json)

# Beautify
$json = [string](ConvertToPrettyJson -data $json)
Copy link

Choose a reason for hiding this comment

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

I am concerned whether the sort is a stable sort algorithm for keys that are not present in the index list.

Could multiple executions yield different results?

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

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

IMO there could and should be a check for keys we don't want to be present. Doesn't this exist already?

To make formatjson.ps1 safer we could do: If key is not present in the schema.json

  • Optian a) fail execution
  • Option b) remove key

Copy link

@z-Fng z-Fng Sep 20, 2025

Choose a reason for hiding this comment

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

Doesn't this exist already?

Does it? It will fail execution currently.

Sort-Object: D:\Scoop\apps\scoop\current\lib\json.ps1:241:9
Line |
 241 |          Sort-Object -Property @{
     |          ~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot convert value "-1" to type "System.Byte". Error: "Value was either too large or too small for an unsigned byte."

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

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

I was thinking more about that other parts of the validation should catch manifest errors before it gets to formatjson.ps1. Thus validating that the manifest doesn't contain invalid keys is a task that formatjson.ps1 shouldn't try to solve.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems that's what the validator is for?

https://github.com/ScoopInstaller/Scoop/tree/master/supporting/validator

Thus I don't think the new function Sort-ScoopManifestRootProperties should have a lot of validation logic. It's a feature that it throws if manifest does not comply with schema.json IMO.

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 check for parent keys not present in schema.json inside Sort-ScoopManifestRootProperties. Then users will get a better error message than what you posted in #6494 (comment).

Copy link
Contributor Author

@o-l-a-v o-l-a-v Sep 20, 2025

Choose a reason for hiding this comment

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

Or we could write a warning, and just return the object as is / not try to sort the object at all. Instead of throwing.

Copy link

Choose a reason for hiding this comment

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

Seems that's what the validator is for?

Yes, thanks for reminding.

I added a check for parent keys not present in schema.json inside Sort-ScoopManifestRootProperties. Then users will get a better error message than what you posted.

Totally agree. Great.

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.

2 participants