Skip to content

feat(scorecard): File level checks - all providers#2913

Merged
djanickova merged 38 commits intoredhat-developer:mainfrom
djanickova:scorecard-file-level-checks-scm
Apr 27, 2026
Merged

feat(scorecard): File level checks - all providers#2913
djanickova merged 38 commits intoredhat-developer:mainfrom
djanickova:scorecard-file-level-checks-scm

Conversation

@djanickova
Copy link
Copy Markdown
Member

Hey, I just made a Pull Request!

This is the second version of the new filecheck scorecard. The implementation is now provider agnostic and works for all SCMs. It contains mostly the same functionality as #2751, but the logic was moved from the github module into a new filecheck module.

This PR introduces a new type of scorecard: file level checks (RHDHPLAN-397). This adds ability for Scorecard to verify if a list of required files (one or more) is present (such as a license, CODEOWNERS, dockerfile, .gitignore, etc). The paths to these files are configurable.

Example of these scorecards on the entity page:

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

Signed-off-by: Diana Janickova <djanicko@redhat.com>

test:  implement and update unit tests

Assisted-By: Cursor
Signed-off-by: Diana Janickova <djanicko@redhat.com>

chore: generate api reports

Signed-off-by: Diana Janickova <djanicko@redhat.com>

ref: use metricId instead of providerId

Signed-off-by: Diana Janickova <djanicko@redhat.com>

ref: Apply suggestions from code review

Co-authored-by: Ihor Mykhno <imykhno@redhat.com>

fix: run prettier

Signed-off-by: Diana Janickova <djanicko@redhat.com>

fix: update expected string in test

Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>

feat: implement aggregated card and update test

Signed-off-by: Diana Janickova <djanicko@redhat.com>

feat: include aggregated card in App.tsx

Signed-off-by: Diana Janickova <djanicko@redhat.com>

fix: pass logger as param

Signed-off-by: Diana Janickova <djanicko@redhat.com>

ref: remove default boolean tresholds, edit translation

Signed-off-by: Diana Janickova <djanicko@redhat.com>

chore: generate api reports

Signed-off-by: Diana Janickova <djanicko@redhat.com>

test: e2e test scenario for file checks

Signed-off-by: Diana Janickova <djanicko@redhat.com>

fix: selectors in test

Signed-off-by: Diana Janickova <djanicko@redhat.com>

feat: include file check section in app-config.yaml

Signed-off-by: Diana Janickova <djanicko@redhat.com>

fix: aggregated permission card title and desc

Signed-off-by: Diana Janickova <djanicko@redhat.com>

ref: move tresholds from scorecard-common

Signed-off-by: Diana Janickova <djanicko@redhat.com>

fix: off center icon and treshold imports

Signed-off-by: Diana Janickova <djanicko@redhat.com>

feat: add new translations

Signed-off-by: Diana Janickova <djanicko@redhat.com>

ref: implement resolveMetricTranslation

Signed-off-by: Diana Janickova <djanicko@redhat.com>

fix: resolve translations correctly

Signed-off-by: Diana Janickova <djanicko@redhat.com>

ref: use useMemo in EmptyStatePanel

Signed-off-by: Diana Janickova <djanicko@redhat.com>

fix: use translations in test

Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
@rhdh-gh-app
Copy link
Copy Markdown

rhdh-gh-app Bot commented Apr 24, 2026

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
app-legacy workspaces/scorecard/packages/app-legacy none v0.0.0
backend workspaces/scorecard/packages/backend none v0.0.0
@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-filecheck workspaces/scorecard/plugins/scorecard-backend-module-filecheck minor v0.0.0
@red-hat-developer-hub/backstage-plugin-scorecard-backend workspaces/scorecard/plugins/scorecard-backend minor v2.5.2
@red-hat-developer-hub/backstage-plugin-scorecard-node workspaces/scorecard/plugins/scorecard-node minor v2.5.2
@red-hat-developer-hub/backstage-plugin-scorecard workspaces/scorecard/plugins/scorecard minor v2.5.2

Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
Signed-off-by: Diana Janickova <djanicko@redhat.com>
@djanickova
Copy link
Copy Markdown
Member Author

Tested this by having both Github and Gitlab components in my catalog, scorecards showed up correctly for both of these.

Example for a Gitlab component (I added one more filecheck locally to app-config compared to what is there by default):
Screenshot 2026-04-24 at 11 10 44

Example of an aggregated card (with custom title) detail when I have 2 entities:
Screenshot 2026-04-24 at 16 22 35

Most of the code (especially for scorecard and scorecard-backend packages) remains unchanged compared to #2751.

Signed-off-by: Diana Janickova <djanicko@redhat.com>
Copy link
Copy Markdown
Member

@christoph-jerolimov christoph-jerolimov left a comment

Choose a reason for hiding this comment

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

Hi @djanickova, great work 👍

I didn't tested this PR myself but wanted drop some thoughts for you, and @dzemanov, @imykhno, @PatAKnight because I'm off next week. You can pick or ignore based on your internal or scorecard meeting discussions on Monday:

Comment on lines +58 to +65
const tree = await this.urlReader.readTree(target, {
etag: cached?.etag,
filter: filePath => pathsSet.has(filePath),
});

const files = await tree.files();
foundPaths = new Set(files.map(f => f.path));
this.cache.set(cacheKey, { etag: tree.etag, foundPaths });
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't say its wrong, but someone should test this with a big repo. It's probably better to make 3 readUrl calls here instead of one big readTree. In the GH implementation it looks like it downloads the complete repo for that. Also if its just downloaded to a tmp folder, it's probably saver (security concerns with cloned git repos into RHDH) to just download the README, LICENSE, and what else file instead of the complete repo.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We have discussed this and came to the conclusion to leave it as it is for now. Both readTree and readUrl have disadvantages and with readTree, there is a smaller chance of hitting rate limits. We can also use etags and caching to further optimize readTree. We can always come back to this if we find out that the current approach is not good :)

Comment on lines +80 to +86
const keys = fileConfig.keys();
if (keys.length !== 1) {
throw new Error(
'Each file config entry must have exactly one key-value pair',
);
}
const id = keys[0];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just as an idea: Why not using then an object?

    filecheck:
      files:
        license: 'LICENSE'
        codeowners: 'CODEOWNERS'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thank you for the suggestion, I think an object would be better and cleaner. I refactored the code to use objects instead

Comment thread workspaces/scorecard/plugins/scorecard-backend-module-filecheck/package.json Outdated
filecheck:
files:
- readme: README.md
- license: LICENSE
Copy link
Copy Markdown
Member

@christoph-jerolimov christoph-jerolimov Apr 24, 2026

Choose a reason for hiding this comment

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

LICENSE, LICENSE.txt, ...

It's fine, but really expect that this will come back that each metric should support multiple filenames.

The time might not be enough anymore, but I would recommend:

scorecard:
  plugins:
    filecheck:
      readme:
        files: README.md
      license:
        files:
          - LICENSE
          - LICENSE.txt

That would also allow you later to add other configurations for a metric. Like caseInsensitivity: true or whatever...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I agree that it will be handy to have the option to define multiple paths per file. However, I would keep the changes now at minimum considering we do not have much time left

Copy link
Copy Markdown
Member

@PatAKnight PatAKnight left a comment

Choose a reason for hiding this comment

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

Thank you for this @djanickova!! Some suggestions

Signed-off-by: Diana Janickova <djanicko@redhat.com>
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Member

@Eswaraiahsapram Eswaraiahsapram left a comment

Choose a reason for hiding this comment

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

Thanks, @djanickova. Reviewed the frontend changes and tested locally. Looks good to me 🎉

Screen.Recording.2026-04-27.at.3.47.53.PM.mov

Copy link
Copy Markdown
Member

@PatAKnight PatAKnight left a comment

Choose a reason for hiding this comment

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

LGTM

@djanickova djanickova merged commit 4ecaacd into redhat-developer:main Apr 27, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants