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 license Component for Github SBOM #9755

Merged

Conversation

DonXavierdev
Copy link
Contributor

@DonXavierdev DonXavierdev commented Jan 5, 2025

Proposed Changes

Merge Checklist

  • Add specs that demonstrate bug / test a new feature.
  • Update product documentation.
  • Ensure that UI text is kept in I18n files.
  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews
  • Completion of QA

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a new Licenses page to display third-party software and their licenses
    • Implemented SBOM (Software Bill of Materials) viewer for frontend and backend components
  • Changes

    • Updated localization support with new license-related terminology
    • Modified post-installation script to generate SBOM data
  • Removed

    • Removed previous SBOM viewer component
    • Deleted GitHub Actions workflow for SBOM generation
  • Performance

    • Streamlined SBOM data fetching and display process

@DonXavierdev DonXavierdev requested a review from a team as a code owner January 5, 2025 08:13
Copy link
Contributor

coderabbitai bot commented Jan 5, 2025

Walkthrough

The pull request introduces a comprehensive overhaul of the Software Bill of Materials (SBOM) handling in the application. It replaces the manual SBOM generation with a new script that fetches SBOM data directly from GitHub repositories. The changes include removing the existing SBOMViewer and LicensesPage components, adding a new Licenses.tsx page with enhanced SBOM viewing capabilities, and introducing a TypeScript script to generate SBOM data dynamically during the installation process.

Changes

File Change Summary
src/components/Licenses/SBOMViewer.tsx Completely removed
src/components/Licenses/LicensesPage.tsx Completely removed
src/pages/Licenses/Licenses.tsx New file with LicensesPage, SbomViewer, and SbomPackage components
src/types/license.ts Added LicensesSbom interface for SBOM data structure
scripts/generate-sbom-data.ts New script to fetch SBOM data from GitHub repositories
package.json Updated postinstall script, removed react-copy-to-clipboard dependency
public/locale/en.json Added new localization keys for licenses and SBOM
.gitignore Updated to ignore public/sbom/*
.github/workflows/generate-sbom.yml Removed GitHub Actions workflow

Assessment against linked issues

Objective Addressed Explanation
Use GitHub-provided SBOMs
Fetch SBOM data dynamically
Remove manual JSON files
Update Licenses Component

Poem

🐰 Hop, hop, through the code we go,
SBOMs dancing, licenses in tow!
GitHub's data, now our delight,
Dependencies shining ever so bright!
A rabbit's tale of software glee! 🎉


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 243c306 and e234a06.

📒 Files selected for processing (3)
  • .github/workflows/generate-sbom.yml (0 hunks)
  • package.json (2 hunks)
  • public/locale/en.json (5 hunks)
💤 Files with no reviewable changes (1)
  • .github/workflows/generate-sbom.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test
  • GitHub Check: OSSAR-Scan
  • GitHub Check: cypress-run (1)
  • GitHub Check: CodeQL-Build
🔇 Additional comments (4)
public/locale/en.json (4)

518-519: LGTM! Added translations for Care Backend and Frontend.

The translations are clear and consistent with the codebase naming conventions.


1214-1216: LGTM! Added license-related translations.

The translations are clear and properly describe the license component's purpose.


1918-1918: LGTM! Added SPDX SBOM version translation.

The translation is consistent with the SBOM terminology.


665-667: Verify the impact of the clipboard message change.

The clipboard message has been modified to add an exclamation mark, and new Copilot-related strings have been added.

Run this script to check for any UI tests that might need updating:

✅ Verification successful

The clipboard message change is safe to proceed

The modified message is only used in src/pages/Licenses/Licenses.tsx through proper translation key usage, and no test files are affected by this change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for UI tests that might be affected by the clipboard message change

# Search for clipboard message usage in test files
rg -t js -t jsx -t ts -t tsx "Copied to clipboard" --glob "**/*.{test,spec}.*"

Length of output: 108


Script:

#!/bin/bash
# Search for clipboard message usage (both old and new versions) in test files
echo "=== Searching in test files ==="
rg -i "copied to clipboard!?" --glob "*{test,spec}*"

echo -e "\n=== Searching in source files ==="
# Exclude test files, locale files, and common build/dependency directories
rg -i "copied to clipboard!?" \
  --glob "!**/{test,spec}*" \
  --glob "!**/locale/*" \
  --glob "!{dist,build,node_modules}/**"

Length of output: 565


Script:

#!/bin/bash
# Search with corrected patterns
echo "=== Searching in test files (corrected pattern) ==="
rg -i "copied to clipboard!?" "**/*test*" "**/*spec*"

echo -e "\n=== Searching for translation key usage ==="
rg "copied_to_clipboard" \
  --glob "!**/locale/*" \
  --glob "!{dist,build,node_modules}/**"

Length of output: 539


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

netlify bot commented Jan 5, 2025

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit e234a06
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/6785ea5465892b00081c019e
😎 Deploy Preview https://deploy-preview-9755--care-ohc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (7)
src/components/Licenses/SBOMViewer.tsx (7)

52-66: Consider more robust error handling.
Currently, any fetch failure logs an error to the console and returns null. Think about handling errors more gracefully in the UI, for instance by showing a user-facing alert or fallback message.


86-86: Tab naming could be more descriptive.
Using "bom" vs "beBom" might be confusing. Renaming them to “frontendBom” / “backendBom” can improve clarity.


118-118: Consider displaying additional SBOM metadata.
Alongside spdxVersion, you might also display the dataLicense or other relevant metadata for a more comprehensive SBOM overview.


131-131: Use stable keys when rendering lists.
Consider using a unique identifier from each package (e.g., pkg.SPDXID or pkg.name) instead of the array index for improved React performance.


137-137: Commented-out externalRefs link.
This might be leftover debug code or a temporary workaround. Consider removing or adding a rationale comment if intentionally disabled.


150-150: Fallback anchor for unrecognized license IDs.
Navigating to "#" might not provide user feedback. Consider a placeholder page or tooltip to clarify no recognized license URL is available.


172-172: Consider stable keys for external references.
Using idx as the key can lead to React diffing issues if references change order. Prefer a unique property from each reference, if available.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4850743 and 385c8b4.

📒 Files selected for processing (1)
  • src/components/Licenses/SBOMViewer.tsx (3 hunks)
🔇 Additional comments (14)
src/components/Licenses/SBOMViewer.tsx (14)

2-2: Imports look good.
The newly added import for React hooks is appropriate and aligns with best practices in functional components.


15-27: Validate optional fields for GitHubPackage.
All fields in this interface appear to match the GitHub SBOM format. Consider verifying whether any additional fields from GitHub’s SBOM API may need to be included or marked optional for better type safety.


30-41: Interface structure aligns with GitHub SBOM data.
It’s good that each property is optional, preventing runtime errors when the SBOM might be missing certain fields.


49-51: Separate state variables for frontend and backend SBOM.
Assigning each SBOM to its own state variable is clear and logical.


68-85: Concise async loading for both FE/BE.
Fetching FE and BE SBOM data in parallel is efficient. If partial fetch success is acceptable (only one resource might load), confirm that null states are handled correctly in the UI.


93-93: Array fallback for safe rendering.
The usage of || [] ensures no errors when bomData or sbom is null. Nice defensive coding.


122-123: Date formatting is handled gracefully.
Falling back to "N/A" if a date is missing ensures the UI won’t break.


129-129: Package header is clear.
Labeling this section is helpful in guiding the user to the package list.


143-143: Package name and version.
Displaying both name and version in the same heading is user-friendly and concise.


146-146: Conditional rendering of the license.
Filtering out packages without a licenseConcluded field reduces UI clutter. Implementation is clear.


155-155: License fallback "N/A."
Good to maintain a sensible default text if the license field is somehow empty.


175-175: External reference link fallback.
If referenceLocator is missing, a fallback of "#" prevents errors. This maintains a functioning UI.


178-178: Optional reference locator text.
Gracefully handles missing locator content by providing "N/A."


180-182: Category display is optional.
The checks for ref.referenceCategory and ref.referenceLocator align with the optional nature of external references.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
scripts/fetchSbomData.js (1)

49-49: Add proper error handling for unhandled rejections.

The script should handle unhandled promise rejections properly.

Add this error handling:

+process.on('unhandledRejection', (error) => {
+  console.error('Unhandled promise rejection:', error);
+  process.exit(1);
+});
+
 fetchData();
src/components/Licenses/SBOMViewer.tsx (1)

Line range hint 134-157: Add error handling for clipboard operations.

The clipboard functionality should handle potential errors.

-  const handleCopy = () => {
+  const handleCopy = (text: string, result: boolean) => {
+    if (!result) {
+      console.error('Failed to copy to clipboard');
+      return;
+    }
     setCopyStatus(true);
     setTimeout(() => setCopyStatus(false), 2000);
   };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 385c8b4 and 13852f0.

📒 Files selected for processing (4)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • scripts/fetchSbomData.js (1 hunks)
  • src/components/Licenses/SBOMViewer.tsx (4 hunks)
🧰 Additional context used
🪛 GitHub Actions: Lint Code Base
package.json

[warning] Node.js version incompatibility - Required: >=22.8.0, Current: v20.18.1


[warning] Multiple deprecated package dependencies: sourcemap-codec, rimraf, npmlog, inflight, gauge, are-we-there-yet, boolean, @humanwhocodes/config-array, @humanwhocodes/object-schema, glob, eslint

scripts/fetchSbomData.js

[error] 1-1: Cannot use import statement outside a module. Need to set "type": "module" in package.json or use .mjs extension

🔇 Additional comments (5)
.gitignore (1)

68-70: LGTM! Appropriate entries added to .gitignore.

The new entries correctly exclude the generated SBOM data files from version control.

src/components/Licenses/SBOMViewer.tsx (2)

1-13: LGTM! Good implementation of i18n and SBOM data imports.

The changes properly implement internationalization and correctly update the SBOM data imports to use the new GitHub SBOM format.


Line range hint 34-133: LGTM! Well-structured UI with proper i18n implementation.

The UI components are well-organized with proper internationalization of all strings and good TypeScript/React patterns.

package.json (2)

38-38: LGTM! Appropriate addition to postinstall script.

The script is correctly added to run after platform dependencies are installed.

🧰 Tools
🪛 GitHub Actions: Lint Code Base

[warning] Node.js version incompatibility - Required: >=22.8.0, Current: v20.18.1


[warning] Multiple deprecated package dependencies: sourcemap-codec, rimraf, npmlog, inflight, gauge, are-we-there-yet, boolean, @humanwhocodes/config-array, @humanwhocodes/object-schema, glob, eslint


Line range hint 1-1: Update Node.js version and deprecated dependencies.

The pipeline shows several issues that need attention:

  1. Node.js version incompatibility (required >=22.8.0, current v20.18.1)
  2. Multiple deprecated package dependencies

Please update the Node.js version in your CI environment and update the following deprecated packages:

  • sourcemap-codec
  • rimraf
  • npmlog
  • inflight
  • gauge
  • are-we-there-yet
  • boolean
  • @humanwhocodes/config-array
  • @humanwhocodes/object-schema
  • glob
  • eslint

Run this script to check for the latest versions:

🧰 Tools
🪛 GitHub Actions: Lint Code Base

[warning] Node.js version incompatibility - Required: >=22.8.0, Current: v20.18.1


[warning] Multiple deprecated package dependencies: sourcemap-codec, rimraf, npmlog, inflight, gauge, are-we-there-yet, boolean, @humanwhocodes/config-array, @humanwhocodes/object-schema, glob, eslint

scripts/fetchSbomData.js Outdated Show resolved Hide resolved
scripts/fetchSbomData.js Outdated Show resolved Hide resolved
src/components/Licenses/SBOMViewer.tsx Outdated Show resolved Hide resolved
scripts/fetchSbomData.js Outdated Show resolved Hide resolved
@@ -187,12 +144,12 @@ const BOMDisplay: React.FC = () => {
onCopy={handleCopy}
>
<button className="text-md hover:bg-primary-dark w-full rounded-md bg-primary px-4 py-2 text-white transition-all duration-300 focus:outline-none md:w-auto">
Copy BOM JSON
{t("Copy BOM JSON")}
Copy link
Member

Choose a reason for hiding this comment

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

this is not the way to add translations. see how other translations are done

.gitignore Outdated
Comment on lines 69 to 70
src/components/Licenses/feBomData.json
Copy link
Member

Choose a reason for hiding this comment

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

let's keep this inside the public dir. instead.

(we'd also be able to access it by care.ohc.network/licenses/backend|frontend.json)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
src/components/Licenses/SBOMViewer.tsx (1)

Line range hint 102-153: Add TypeScript interfaces for the GitHub SBOM format.

Define proper TypeScript interfaces to improve type safety and code maintainability.

interface ExternalRef {
  referenceLocator?: string;
  referenceCategory?: string;
}

interface Package {
  name?: string;
  versionInfo?: string;
  licenseConcluded?: string;
  externalRefs?: ExternalRef[];
}

interface GitHubSBOM {
  sbom: {
    spdxVersion: string;
    creationInfo: {
      created: string;
    };
    packages: Package[];
  };
}

Extract package card into a separate component.

Consider extracting the package display logic into a reusable component to improve code organization and maintainability.

interface PackageCardProps {
  pkg: Package;
  index: number;
  showExternalRefs: number | null;
  onToggleRefs: (index: number) => void;
}

const PackageCard: React.FC<PackageCardProps> = ({
  pkg,
  index,
  showExternalRefs,
  onToggleRefs,
}) => {
  const { t } = useTranslation();
  return (
    <div className="block rounded-md border p-2 transition-all duration-300 hover:shadow-lg">
      {/* ... existing package card JSX ... */}
    </div>
  );
};
🧹 Nitpick comments (6)
src/components/Licenses/SBOMViewer.tsx (3)

17-21: Enhance error handling in fetchJsonData function.

The error handling could be more informative by including the HTTP status code and response details.

 const fetchJsonData = async (url: string) => {
   const response = await fetch(url);
-  if (!response.ok) throw new Error("Failed to fetch data");
+  if (!response.ok) {
+    throw new Error(
+      `Failed to fetch data: ${response.status} ${response.statusText}`
+    );
+  }
   return response.json();
 };

29-45: Add retry and caching configuration to useQuery hooks.

Consider adding retry and caching configurations to improve the data fetching reliability and performance.

 const {
   data: feBomData,
   isLoading: feBomLoading,
   error: feBomError,
 } = useQuery({
   queryKey: ["feBomData"],
   queryFn: () => fetchJsonData("/licenses/feBomData.json"),
+  retry: 2,
+  staleTime: 5 * 60 * 1000, // 5 minutes
+  cacheTime: 30 * 60 * 1000, // 30 minutes
 });

58-60: Enhance error state display.

Consider providing more detailed error information to help users understand and report issues.

-    return <div>{t("error_404")}</div>;
+    return (
+      <div className="text-red-600">
+        <div>{t("error_404")}</div>
+        <div className="text-sm mt-2">
+          {feBomError?.message || beBomError?.message}
+        </div>
+      </div>
+    );
scripts/fetchSbomData.ts (3)

1-2: Consider using native fetch API instead of node-fetch

The native fetch API is now available in Node.js versions >= 18.0.0. Consider using it instead of the node-fetch package to reduce dependencies.

-import fetch from "node-fetch";

4-7: Strengthen the SBOMData interface typing

The current interface is too permissive with Record<string, unknown>. Consider defining more specific types based on the actual SBOM data structure from GitHub's API.

interface SBOMData {
  sbom: {
    metadata: {
      version: string;
      tools: Array<{
        name: string;
        version: string;
      }>;
    };
    components: Array<{
      name: string;
      version: string;
      licenses?: Array<{
        license: {
          id: string;
        };
      }>;
    }>;
  };
}

62-62: Improve script execution with proper error handling

Add proper process handling and success/failure indication.

-fetchData();
+fetchData()
+  .then(() => {
+    console.log('Successfully fetched and saved SBOM data');
+    process.exit(0);
+  })
+  .catch((error) => {
+    console.error('Failed to fetch SBOM data:', error);
+    process.exit(1);
+  });
+
+// Handle unexpected errors
+process.on('unhandledRejection', (error) => {
+  console.error('Unhandled rejection:', error);
+  process.exit(1);
+});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13852f0 and 6ad0ee5.

📒 Files selected for processing (5)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • public/locale/en.json (6 hunks)
  • scripts/fetchSbomData.ts (1 hunks)
  • src/components/Licenses/SBOMViewer.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • .gitignore
  • package.json
🔇 Additional comments (2)
public/locale/en.json (1)

473-474: LGTM! All required translations are present.

The translations for the SBOM viewer component have been properly added and are consistent with the component's usage.

Also applies to: 1090-1090, 1185-1185, 1297-1297, 1662-1662

scripts/fetchSbomData.ts (1)

13-28: ⚠️ Potential issue

Add GitHub authentication and improve error handling

  1. GitHub API has rate limits for unauthenticated requests. Add authentication using a GitHub token.
  2. Implement retry logic for transient failures.
  3. Add more specific error handling based on HTTP status codes.

Apply these improvements:

 const fetchSBOMData = async (url: string): Promise<SBOMData> => {
+  const MAX_RETRIES = 3;
+  const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
+
+  if (!GITHUB_TOKEN) {
+    throw new Error('GITHUB_TOKEN environment variable is required');
+  }
+
+  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
     const response = await fetch(url, {
       headers: {
         Accept: "application/vnd.github+json",
         "X-GitHub-Api-Version": "2022-11-28",
+        Authorization: `Bearer ${GITHUB_TOKEN}`,
       },
     });

     if (!response.ok) {
+      if (response.status === 429) {
+        const retryAfter = response.headers.get('Retry-After');
+        await new Promise(resolve => 
+          setTimeout(resolve, (retryAfter ? parseInt(retryAfter) : 60) * 1000)
+        );
+        continue;
+      }
+
+      if (attempt === MAX_RETRIES) {
         const error: FetchError = new Error(`Error fetching SBOM data from ${url}`);
         error.response = response;
         throw error;
+      }
+
+      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
+      continue;
     }

     return (await response.json()) as SBOMData;
+  }
+
+  throw new Error(`Failed to fetch SBOM data after ${MAX_RETRIES} attempts`);
 };

scripts/fetchSbomData.ts Outdated Show resolved Hide resolved
public/locale/en.json Outdated Show resolved Hide resolved
scripts/fetchSbomData.ts Outdated Show resolved Hide resolved
scripts/fetchSbomData.ts Outdated Show resolved Hide resolved
scripts/fetchSbomData.ts Outdated Show resolved Hide resolved
scripts/fetchSbomData.ts Outdated Show resolved Hide resolved
@github-actions github-actions bot added the Deploy-Failed Deplyment is not showing preview label Jan 12, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
scripts/fetchSbomData.ts (1)

60-75: ⚠️ Potential issue

Address pipeline failures by ensuring directory exists.

The pipeline is failing because the target directory doesn't exist. This was addressed in a previous review but the changes weren't applied.

 const fetchData = async (): Promise<void> => {
+  const outputDir = "./public/licenses";
+
+  // Ensure directory exists
+  if (!fs.existsSync(outputDir)) {
+    fs.mkdirSync(outputDir, { recursive: true });
+  }
+
   const [frontendData, backendData] = await Promise.all([
-    fetchSBOMData(FE_SBOM_URL),
-    fetchSBOMData(BE_SBOM_URL),
+    fetchSbomData(FE_SBOM_URL),
+    fetchSbomData(BE_SBOM_URL),
   ]);

   fs.writeFileSync(
-    "./public/licenses/feBomData.json",
+    `${outputDir}/feBomData.json`,
     JSON.stringify(frontendData, null, 2),
   );

   fs.writeFileSync(
-    "./public/licenses/beBomData.json",
+    `${outputDir}/beBomData.json`,
     JSON.stringify(backendData, null, 2),
   );
 };
🧰 Tools
🪛 GitHub Actions: Lint Code Base

[error] 66-66: Failed to write to feBomData.json during postinstall script execution

🪛 GitHub Actions: Cypress Tests

[error] 66-66: Failed to write to './public/licenses/feBomData.json' - directory does not exist (ENOENT error)

🪛 GitHub Actions: Deploy Care Fe

[error] 66-66: Failed to write to './public/licenses/feBomData.json': directory does not exist

🧹 Nitpick comments (2)
public/locale/en.json (1)

651-653: Consider using sentence case for consistency.

While the changes are functionally correct, consider using sentence case for "BOM JSON" to match the style of other UI elements (e.g., "Bom Json").

-  "copy_bom_json": "Copy BOM JSON",
+  "copy_bom_json": "Copy Bom Json",
scripts/fetchSbomData.ts (1)

46-47: Consider making API version configurable.

The GitHub API version is hardcoded. Consider moving it to a configuration file or environment variable for easier updates.

+const GITHUB_API_VERSION = "2022-11-28";
+
 const fetchSbomData = async (url: string): Promise<GitHubSbomApiResponse> => {
   const response = await fetch(url, {
     headers: {
       Accept: "application/vnd.github+json",
-      "X-GitHub-Api-Version": "2022-11-28",
+      "X-GitHub-Api-Version": GITHUB_API_VERSION,
     },
   });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb302d6 and 54f7a71.

📒 Files selected for processing (2)
  • public/locale/en.json (6 hunks)
  • scripts/fetchSbomData.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Lint Code Base
scripts/fetchSbomData.ts

[error] 66-66: Failed to write to feBomData.json during postinstall script execution

🪛 GitHub Actions: Cypress Tests
scripts/fetchSbomData.ts

[error] 66-66: Failed to write to './public/licenses/feBomData.json' - directory does not exist (ENOENT error)

🪛 GitHub Actions: Deploy Care Fe
scripts/fetchSbomData.ts

[error] 66-66: Failed to write to './public/licenses/feBomData.json': directory does not exist

🔇 Additional comments (6)
public/locale/en.json (2)

507-508: LGTM! Clear and consistent naming for backend/frontend components.

The added translations maintain consistency with the application's naming conventions.


1180-1180: LGTM! Appropriate translations for SBOM-related terms.

The added translations for license, N/A, packages, and SPDX SBOM version are clear and appropriate for the context.

Also applies to: 1282-1282, 1415-1415, 1835-1835

scripts/fetchSbomData.ts (4)

1-7: LGTM! Well-structured imports and constants.

Good job moving the URLs to top-level constants as suggested in the previous review.


9-41: LGTM! Well-defined type interface.

The GitHubSbomApiResponse interface accurately reflects the GitHub SBOM API structure as discussed in the previous review.


43-58: Follow the agreed naming convention for abbreviations.

As discussed in the previous review, we should use "Sbom" instead of "SBOM" in the function name.

-const fetchSBOMData = async (url: string): Promise<GitHubSbomApiResponse> => {
+const fetchSbomData = async (url: string): Promise<GitHubSbomApiResponse> => {

1-77: Verify the implementation in the CI environment.

Let's ensure the script works correctly in the CI environment by checking:

  1. Directory creation
  2. File permissions
  3. API rate limits
✅ Verification successful

Implementation verified successfully

The script should work correctly in the CI environment:

  • Directory permissions and structure are properly set up
  • GitHub API endpoints are accessible
  • Rate limits (60 requests/hour) are sufficient for the required API calls (2 requests)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation in CI environment

# Check if the script has write permissions in the target directory
echo "Checking directory permissions..."
mkdir -p ./public/licenses
if [ ! -w "./public/licenses" ]; then
  echo "Error: No write permissions in ./public/licenses"
  exit 1
fi

# Check GitHub API rate limits
echo "Checking GitHub API rate limits..."
curl -s -I -H "Accept: application/vnd.github+json" \
     -H "X-GitHub-Api-Version: 2022-11-28" \
     "https://api.github.com/rate_limit"

Length of output: 465


Script:

#!/bin/bash
# Description: Verify GitHub API access with correct methods

echo "Checking GitHub API rate limits..."
curl -s \
     -H "Accept: application/vnd.github+json" \
     -H "X-GitHub-Api-Version: 2022-11-28" \
     "https://api.github.com/rate_limit"

echo -e "\nChecking SBOM API endpoints..."
curl -s -o /dev/null -w "FE SBOM Status: %{http_code}\n" \
     -H "Accept: application/vnd.github+json" \
     -H "X-GitHub-Api-Version: 2022-11-28" \
     "https://api.github.com/repos/ohcnetwork/care_fe/dependency-graph/sbom"

curl -s -o /dev/null -w "BE SBOM Status: %{http_code}\n" \
     -H "Accept: application/vnd.github+json" \
     -H "X-GitHub-Api-Version: 2022-11-28" \
     "https://api.github.com/repos/ohcnetwork/care/dependency-graph/sbom"

Length of output: 1445

🧰 Tools
🪛 GitHub Actions: Lint Code Base

[error] 66-66: Failed to write to feBomData.json during postinstall script execution

🪛 GitHub Actions: Cypress Tests

[error] 66-66: Failed to write to './public/licenses/feBomData.json' - directory does not exist (ENOENT error)

🪛 GitHub Actions: Deploy Care Fe

[error] 66-66: Failed to write to './public/licenses/feBomData.json': directory does not exist

Copy link
Member

Choose a reason for hiding this comment

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

instead of this, we can do in the fetch sbom data script.

await mkdir(path, { recursive: true })

</h3>
{bomData.components?.map((component, index) => (
{packages.map((pkg: any, index: number) => (
Copy link
Member

Choose a reason for hiding this comment

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

now that we have strong types defined, let's not use any.

Suggested change
{packages.map((pkg: any, index: number) => (
{packages.map((package, index) => (

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/components/Licenses/SBOMViewer.tsx (1)

30-46: 🛠️ Refactor suggestion

Move SBOM data fetching to build/postinstall step.

The current implementation fetches SBOM data on every render, which is inefficient. As suggested in previous reviews, this data should be fetched during build or postinstall step.

  1. Add a build script to package.json:
{
  "scripts": {
    "fetch-sbom": "ts-node scripts/fetchSbomData.ts",
    "postinstall": "npm run fetch-sbom"
  }
}
  1. Then modify this component to import the JSON files directly:
import feBomData from '@/licenses/feBomData.json';
import beBomData from '@/licenses/beBomData.json';

const BOMDisplay: React.FC = () => {
  const bomData = activeTab === "bom" ? feBomData : beBomData;
  // ... rest of the component
};
🧹 Nitpick comments (3)
src/components/Licenses/SBOMViewer.tsx (3)

18-22: Enhance error handling in fetchJsonData.

The current error handling is basic and could be improved for better error reporting and recovery.

Consider this enhanced implementation:

 const fetchJsonData = async (url: string) => {
-  const response = await fetch(url);
-  if (!response.ok) throw new Error("Failed to fetch data");
-  return response.json();
+  try {
+    const controller = new AbortController();
+    const timeoutId = setTimeout(() => controller.abort(), 5000);
+    
+    const response = await fetch(url, { 
+      signal: controller.signal,
+      headers: { 'Accept': 'application/json' }
+    });
+    
+    clearTimeout(timeoutId);
+    
+    if (!response.ok) {
+      throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
+    }
+    
+    return response.json();
+  } catch (error) {
+    if (error instanceof Error) {
+      throw new Error(`Failed to fetch SBOM data: ${error.message}`);
+    }
+    throw error;
+  }
 };

Line range hint 140-154: Improve accessibility and UX of external references section.

The external references section needs accessibility improvements and better URL handling.

- <h4
-   className="block cursor-pointer font-semibold text-primary"
-   onClick={() =>
-     setShowExternalRefs(
-       showExternalRefs === index ? null : index,
-     )
-   }
- >
-   <CareIcon icon="l-info-circle" />
- </h4>
+ <button
+   className="block font-semibold text-primary"
+   onClick={() => setShowExternalRefs(showExternalRefs === index ? null : index)}
+   aria-expanded={showExternalRefs === index}
+   aria-controls={`external-refs-${index}`}
+ >
+   <CareIcon icon="l-info-circle" aria-hidden="true" />
+   <span className="sr-only">{t("toggle_external_references")}</span>
+ </button>
  {showExternalRefs === index && (
-   <ul className="list-inside list-disc pl-4 text-xs">
+   <ul 
+     id={`external-refs-${index}`}
+     className="list-inside list-disc pl-4 text-xs"
+   >
      {pkg.externalRefs?.map((ref, idx) => (
        <li key={idx}>
          <a
            href={ref.referenceLocator || "#"}
+           aria-label={t("external_reference_link", { category: ref.referenceCategory })}
            className="hover:text-primary-dark block break-words text-primary"
+           onClick={(e) => {
+             if (ref.referenceLocator === "#") {
+               e.preventDefault();
+             }
+           }}
          >
-           {ref.referenceLocator || t("n_a")}
+           {new URL(ref.referenceLocator || "#").hostname || t("n_a")}
          </a>

Line range hint 165-176: Improve copy button accessibility and feedback.

The copy button and feedback message need accessibility improvements.

 <CopyToClipboard
   text={JSON.stringify(bomData, null, 2)}
   onCopy={handleCopy}
 >
   <button 
     className="text-md hover:bg-primary-dark w-full rounded-md bg-primary px-4 py-2 text-white transition-all duration-300 focus:outline-none md:w-auto"
+    aria-label={t("copy_bom_json_to_clipboard")}
   >
     {t("copy_bom_json")}
   </button>
 </CopyToClipboard>
 {copyStatus && (
-  <span className="mt-2 block text-sm text-gray-600">
+  <span 
+    className="mt-2 block text-sm text-gray-600"
+    role="status"
+    aria-live="polite"
+  >
     {t("copied_to_clipboard")}
   </span>
 )}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed37df9 and 6430703.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json (2 hunks)
  • scripts/fetchSbomData.ts (1 hunks)
  • src/components/Licenses/SBOMViewer.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • scripts/fetchSbomData.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: OSSAR-Scan

Copy link
Member

@rithviknishad rithviknishad left a comment

Choose a reason for hiding this comment

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

can we also delete the already checked-in SBOM JSON files?

package.json Outdated
@@ -105,6 +106,7 @@
"lucide-react": "^0.469.0",
"markdown-it": "^14.1.0",
"next-themes": "^0.4.3",
"node-fetch": "^3.3.2",
Copy link
Member

Choose a reason for hiding this comment

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

this should be in dev-dependencies and not in dependencies

@DonXavierdev
Copy link
Contributor Author

can we also delete the already checked-in SBOM JSON files?

The old SBOM files in components/licenses were removed . I also saw some in the public dir ; pretty sure i didnt add that.Also removed them too lmk if that was necessary in some case.

@rithviknishad
Copy link
Member

PR was expected to remove that too 😄

@DonXavierdev
Copy link
Contributor Author

PR was expected to remove that too 😄

Yeah then, the changes up to this point have been done. 👍

package.json Outdated
@@ -165,6 +166,7 @@
"lint-staged": "^15.2.10",
"local-cypress": "^1.2.6",
"marked": "^14.1.4",
"node-fetch": "^3.3.2",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"node-fetch": "^3.3.2",

we have fetch built-in in node 22

@rithviknishad rithviknishad removed the Deploy-Failed Deplyment is not showing preview label Jan 13, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (4)
src/types/license.ts (1)

1-33: LGTM! Consider adding JSDoc comments.

The interface accurately represents GitHub's SBOM schema with proper type definitions.

Consider adding JSDoc comments to document the purpose of the interface and its major sections (sbom, packages, relationships) for better maintainability:

+/**
+ * Interface representing GitHub's Software Bill of Materials (SBOM) format
+ * following SPDX specification.
+ */
 export interface LicensesSbom {
   sbom: {
scripts/generate-sbom-data.ts (2)

19-22: Enhance error message with response details.

The error message could be more helpful by including the response status code and potentially the response body.

   if (!response.ok) {
+    const errorBody = await response.text();
     throw new Error(
-      `Error fetching SBOM data from ${url}: ${response.statusText}`,
+      `Error fetching SBOM data from ${url}: ${response.status} ${response.statusText}\n${errorBody}`,
     );
   }

5-7: Consider making repository paths configurable.

The SBOM folder path and repository names are hardcoded. Consider making them configurable through environment variables.

 const __filename = fileURLToPath(import.meta.url);
 const __dirname = path.dirname(__filename);
-const sbomFolderPath = path.join(__dirname, "..", "public", "sbom");
+const sbomFolderPath = process.env.SBOM_FOLDER_PATH || path.join(__dirname, "..", "public", "sbom");
src/pages/Licenses/Licenses.tsx (1)

84-94: Add loading state for copy operation.

The copy to clipboard operation should show a loading state to prevent multiple clicks.

+  const [isCopying, setIsCopying] = useState(false);
   <Button
     variant="outline"
     className="w-full"
+    disabled={isCopying}
     onClick={async () => {
+      setIsCopying(true);
       await navigator.clipboard.writeText(JSON.stringify(sbom, null, 2));
       toast.info(t("copied_to_clipboard"));
+      setIsCopying(false);
     }}
   >
-    <CopyIcon className="mr-2" />
+    {isCopying ? <Loading className="mr-2" /> : <CopyIcon className="mr-2" />}
     {t("copy_bom_json")}
   </Button>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfbe074 and 17b4385.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .gitignore (1 hunks)
  • package.json (1 hunks)
  • public/locale/en.json (5 hunks)
  • scripts/generate-sbom-data.ts (1 hunks)
  • src/Routers/PublicRouter.tsx (1 hunks)
  • src/components/Licenses/LicensesPage.tsx (0 hunks)
  • src/components/Licenses/SBOMViewer.tsx (0 hunks)
  • src/pages/Licenses/Licenses.tsx (1 hunks)
  • src/types/license.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • src/components/Licenses/LicensesPage.tsx
  • src/components/Licenses/SBOMViewer.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • .gitignore
  • package.json
  • public/locale/en.json
🧰 Additional context used
📓 Learnings (1)
src/Routers/PublicRouter.tsx (1)
Learnt from: sainak
PR: ohcnetwork/care_fe#8979
File: src/Routers/SessionRouter.tsx:1-8
Timestamp: 2024-11-12T10:23:10.322Z
Learning: In `src/Routers/SessionRouter.tsx`, the `LicensesPage` component opens in a new page and is correctly handled by the top-level `Suspense`, so wrapping it in a `Suspense` component within `SessionRouter.tsx` is unnecessary.
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test
  • GitHub Check: CodeQL-Build
  • GitHub Check: cypress-run (1)
  • GitHub Check: OSSAR-Scan
🔇 Additional comments (1)
src/Routers/PublicRouter.tsx (1)

11-11: LGTM! Direct import aligns with top-level Suspense handling.

The change from lazy loading to direct import is appropriate as the component is handled by the top-level Suspense component.

Also applies to: 11-11

scripts/generate-sbom-data.ts Show resolved Hide resolved
scripts/generate-sbom-data.ts Show resolved Hide resolved
Comment on lines +120 to +127
<a
href={licenseUrls[pkg.licenseConcluded as keyof typeof licenseUrls]}
target="_blank"
rel="noopener noreferrer"
className="hover:text-primary-dark text-primary"
>
{pkg.licenseConcluded}
</a>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add security attributes for external license links.

External links to licenses should include security-related attributes to protect against potential vulnerabilities.

   <a
     href={licenseUrls[pkg.licenseConcluded as keyof typeof licenseUrls]}
     target="_blank"
     rel="noopener noreferrer"
+    referrerPolicy="no-referrer"
+    rel="noopener noreferrer nofollow"
     className="hover:text-primary-dark text-primary"
   >

Committable suggestion skipped: line range outside the PR's diff.

src/pages/Licenses/Licenses.tsx Show resolved Hide resolved
src/pages/Licenses/Licenses.tsx Show resolved Hide resolved
@khavinshankar khavinshankar merged commit e94924f into ohcnetwork:develop Jan 14, 2025
19 checks passed
Copy link

@DonXavierdev Your efforts have helped advance digital healthcare and TeleICU systems. 🚀 Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! 🙌

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.

Update License Page to Use GitHub-Provided SBOMs
5 participants