From 64552135a39688e81b97d695bb060556cfd3facf Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 24 Sep 2025 23:39:18 -0400 Subject: [PATCH 1/4] fix: Enhance package sync with archived status and UI improvements Adds support for tracking and displaying repository archived status throughout the sync and package generation process. Updates the UI to show an 'Archived' badge, limits displayed releases to the latest 5 per repository, and provides a link to view additional releases. Also ensures only v-prefixed releases are processed and improves metadata handling in the workflow. --- .github/scripts/generate-packages.js | 19 ++++++-- .github/scripts/sync-assets.js | 11 ++++- .github/workflows/sync-release-assets.yml | 18 +++++++- gh-pages-template/assets/js/app.js | 54 +++++++++++++++-------- 4 files changed, 77 insertions(+), 25 deletions(-) diff --git a/.github/scripts/generate-packages.js b/.github/scripts/generate-packages.js index 8cb31fa8..23e764fd 100644 --- a/.github/scripts/generate-packages.js +++ b/.github/scripts/generate-packages.js @@ -4,13 +4,20 @@ const path = require('path'); /** * Generate packages.json file by scanning the dist directory structure * @param {string} distPath - Path to the dist directory + * @param {Array} repositoryMetadata - Repository metadata from sync process with archived status * @returns {Object} Generated packages data */ -function generatePackagesJson(distPath = '.') { +function generatePackagesJson(distPath = '.', repositoryMetadata = []) { console.log(`Scanning dist directory: ${distPath}`); const repositories = []; + // Create a map of repository metadata for quick lookup + const repoMetadataMap = new Map(); + repositoryMetadata.forEach(repo => { + repoMetadataMap.set(repo.name, repo); + }); + try { // Read the dist directory const distDir = fs.readdirSync(distPath, { withFileTypes: true }); @@ -21,6 +28,12 @@ function generatePackagesJson(distPath = '.') { console.log(`Processing repository: ${dirent.name}`); const repoData = scanRepositoryDirectory(path.join(distPath, dirent.name)); if (repoData) { + // Update archived status from metadata if available + const metadata = repoMetadataMap.get(dirent.name); + if (metadata) { + repoData.archived = metadata.archived; + } + repositories.push(repoData); console.log(` Found ${repoData.releases.length} releases`); } else { @@ -79,7 +92,7 @@ function scanRepositoryDirectory(repoPath) { const repoDirContents = fs.readdirSync(repoPath, { withFileTypes: true }); for (const dirent of repoDirContents) { - if (dirent.isDirectory()) { + if (dirent.isDirectory() && dirent.name.startsWith('v')) { // Only process v-prefixed releases const releaseData = scanReleaseDirectory(path.join(repoPath, dirent.name)); if (releaseData) { releases.push(releaseData); @@ -93,7 +106,7 @@ function scanRepositoryDirectory(repoPath) { if (releases.length > 0) { return { name: repoName, - archived: false, // Default to false, will be updated by sync process + archived: false, // This will be updated by the sync process with actual GitHub data releases: releases }; } diff --git a/.github/scripts/sync-assets.js b/.github/scripts/sync-assets.js index 96137905..98357ab8 100644 --- a/.github/scripts/sync-assets.js +++ b/.github/scripts/sync-assets.js @@ -24,8 +24,12 @@ async function processRepository(github, context, repo, repositoryData, totalAss per_page: 100 }); - // Filter out draft and prerelease - const publishedReleases = releases.filter(release => !release.draft && !release.prerelease); + // Filter out draft and prerelease, and only include releases with v-prefixed tags + const publishedReleases = releases.filter(release => + !release.draft && + !release.prerelease && + release.tag_name.startsWith('v') + ); if (publishedReleases.length === 0) { console.log(`No published releases found for ${repo.name}`); @@ -273,6 +277,9 @@ async function syncReleaseAssets(github, context, isPullRequest = false, maxNewA } else { console.log(`Downloaded ${newAssetsDownloaded} new assets`); } + + // Return repository data with archived status + return repositoryData; } module.exports = { diff --git a/.github/workflows/sync-release-assets.yml b/.github/workflows/sync-release-assets.yml index f2768468..c280ea4d 100644 --- a/.github/workflows/sync-release-assets.yml +++ b/.github/workflows/sync-release-assets.yml @@ -65,7 +65,11 @@ jobs: // Run the asset synchronization with PR limit and asset limit // Change working directory to dist for file operations process.chdir('./dist'); - await syncReleaseAssets(github, context, isPullRequest, maxNewAssets); + const repositoryData = await syncReleaseAssets(github, context, isPullRequest, maxNewAssets); + + // Store repository data for use in next step + const fs = require('fs'); + fs.writeFileSync('repo-metadata.json', JSON.stringify(repositoryData, null, 2)); - name: Generate packages.json uses: actions/github-script@v8 @@ -80,8 +84,18 @@ jobs: // Change to dist directory process.chdir('./dist'); + // Read repository metadata from previous step + const fs = require('fs'); + let repositoryMetadata = []; + try { + const metadataContent = fs.readFileSync('repo-metadata.json', 'utf8'); + repositoryMetadata = JSON.parse(metadataContent); + } catch (error) { + console.log('No repository metadata found, continuing without archived status'); + } + // Generate the packages data - const packagesData = generatePackagesJson('.'); + const packagesData = generatePackagesJson('.', repositoryMetadata); // Write the packages.json file writePackagesJson(packagesData, './packages.json'); diff --git a/gh-pages-template/assets/js/app.js b/gh-pages-template/assets/js/app.js index 218849ad..bbad4bc6 100644 --- a/gh-pages-template/assets/js/app.js +++ b/gh-pages-template/assets/js/app.js @@ -115,26 +115,44 @@ class UIManager { return; } - this.repositoryGrid.innerHTML = repos.map(repo => ` -
-
-
-
${repo.name}
-
    - ${repo.releases ? repo.releases.map(release => ` -
  • - - ${release.tag} - - ${release.assetCount} -
  • - `).join('') : '
  • No releases found
  • '} -
+ this.repositoryGrid.innerHTML = repos.map(repo => { + // Show only the latest 5 releases + const displayReleases = repo.releases ? repo.releases.slice(0, 5) : []; + const hasMoreReleases = repo.releases && repo.releases.length > 5; + const remainingCount = hasMoreReleases ? repo.releases.length - 5 : 0; + + return ` +
+
+
+
+ ${repo.name} + ${repo.archived ? 'Archived' : ''} +
+ +
-
- `).join(''); + `; + }).join(''); } /** From 5f65dbbdf69f29230a9262a190de8a022d8b5794 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 24 Sep 2025 23:50:28 -0400 Subject: [PATCH 2/4] Refactor release pluralization and improve readability Replaces inline ternary for release pluralization with a variable for better readability. Also updates optional chaining usage and clarifies a comment about loading repository data. --- gh-pages-template/assets/js/app.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gh-pages-template/assets/js/app.js b/gh-pages-template/assets/js/app.js index bbad4bc6..920aaed1 100644 --- a/gh-pages-template/assets/js/app.js +++ b/gh-pages-template/assets/js/app.js @@ -84,7 +84,7 @@ class RepositoryDataManager { return filteredRepos.filter(repo => { const repoMatch = repo.name.toLowerCase().includes(searchTerm.toLowerCase()); - const releaseMatch = repo.releases && repo.releases.some(release => + const releaseMatch = repo.releases?.some(release => release.tag.toLowerCase().includes(searchTerm.toLowerCase())); return repoMatch || releaseMatch; }); @@ -121,6 +121,9 @@ class UIManager { const hasMoreReleases = repo.releases && repo.releases.length > 5; const remainingCount = hasMoreReleases ? repo.releases.length - 5 : 0; + // Extract ternary operation for better readability + const releaseText = remainingCount > 1 ? 's' : ''; + return `
@@ -143,7 +146,7 @@ class UIManager {
  • - Show ${remainingCount} more release${remainingCount > 1 ? 's' : ''} + Show ${remainingCount} more release${releaseText}
  • ` : ''} @@ -251,8 +254,8 @@ class LizardByteAssetsApp { // Show loading state this.uiManager.showLoading(); - // Load repository data - const data = await this.dataManager.loadRepositoryData(); + // Load repository data from packages.json + await this.dataManager.loadRepositoryData(); const repositories = this.dataManager.getRepositories(); // Render repositories and update stats From dca1d0ea93940a71183c2ef59834415a0f77ee68 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Wed, 24 Sep 2025 23:55:49 -0400 Subject: [PATCH 3/4] Update error message styling on repository load failure Replaces the error message HTML for failed repository data loading with improved Bootstrap classes for better alignment and styling. --- gh-pages-template/assets/js/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gh-pages-template/assets/js/app.js b/gh-pages-template/assets/js/app.js index 920aaed1..34f05642 100644 --- a/gh-pages-template/assets/js/app.js +++ b/gh-pages-template/assets/js/app.js @@ -270,7 +270,7 @@ class LizardByteAssetsApp { } catch (error) { console.error('Failed to initialize application:', error); this.uiManager.repositoryGrid.innerHTML = - '
    Failed to load repository data. Please try again later.
    '; + '
    Failed to load repository data. Please try again later.
    '; } } } From 7ad76627be245169cb215b0661b99172f2443b0d Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Thu, 25 Sep 2025 00:08:31 -0400 Subject: [PATCH 4/4] Add scripts for asset sync and cleanup, update workflow Introduces new scripts to handle asset synchronization with metadata storage and cleanup of non-v-prefixed release directories. Updates the GitHub Actions workflow to use these scripts for improved automation and reliability. Also fixes a minor formatting issue in the app.js template. --- .github/scripts/cleanup-releases.js | 48 +++++++++++++++++++ .../scripts/generate-packages-with-cleanup.js | 45 +++++++++++++++++ .github/scripts/sync-assets-with-metadata.js | 35 ++++++++++++++ .github/workflows/sync-release-assets.yml | 30 +++--------- gh-pages-template/assets/js/app.js | 2 +- 5 files changed, 136 insertions(+), 24 deletions(-) create mode 100644 .github/scripts/cleanup-releases.js create mode 100644 .github/scripts/generate-packages-with-cleanup.js create mode 100644 .github/scripts/sync-assets-with-metadata.js diff --git a/.github/scripts/cleanup-releases.js b/.github/scripts/cleanup-releases.js new file mode 100644 index 00000000..7ac3571c --- /dev/null +++ b/.github/scripts/cleanup-releases.js @@ -0,0 +1,48 @@ +const fs = require('fs'); +const path = require('path'); + +/** + * Clean up non-v-prefixed release directories from the dist directory + * @param {string} distPath - Path to the dist directory (default: current directory) + */ +function cleanupNonVPrefixedReleases(distPath = '.') { + console.log('Cleaning up non-v-prefixed release directories...'); + + try { + const distContents = fs.readdirSync(distPath, { withFileTypes: true }); + + for (const dirent of distContents) { + if (dirent.isDirectory() && + dirent.name !== '.git' && + dirent.name !== 'packages.json' && + !dirent.name.startsWith('.')) { + + const repoPath = path.join(distPath, dirent.name); + + try { + const repoContents = fs.readdirSync(repoPath, { withFileTypes: true }); + + for (const releaseDir of repoContents) { + if (releaseDir.isDirectory() && !releaseDir.name.startsWith('v')) { + const releasePath = path.join(repoPath, releaseDir.name); + console.log(`Removing non-v-prefixed release directory: ${releasePath}`); + fs.rmSync(releasePath, { recursive: true, force: true }); + } + } + } catch (repoError) { + console.log(`Error processing repository ${dirent.name}:`, repoError.message); + } + } + } + + console.log('Cleanup completed successfully'); + + } catch (error) { + console.error('Error during cleanup:', error.message); + throw error; + } +} + +module.exports = { + cleanupNonVPrefixedReleases +}; diff --git a/.github/scripts/generate-packages-with-cleanup.js b/.github/scripts/generate-packages-with-cleanup.js new file mode 100644 index 00000000..87c5e194 --- /dev/null +++ b/.github/scripts/generate-packages-with-cleanup.js @@ -0,0 +1,45 @@ +const fs = require('fs'); +const { generatePackagesJson, writePackagesJson } = require('./generate-packages.js'); +const { cleanupNonVPrefixedReleases } = require('./cleanup-releases.js'); + +/** + * Main function to generate packages.json with cleanup + * @param {string} distPath - Path to the dist directory (default: current directory) + */ +function generatePackagesWithCleanup(distPath = '.') { + console.log('Starting packages.json generation process...'); + + try { + // Step 1: Clean up non-v-prefixed release directories + cleanupNonVPrefixedReleases(distPath); + + // Step 2: Read repository metadata from previous step + let repositoryMetadata = []; + const metadataPath = 'repo-metadata.json'; + + try { + const metadataContent = fs.readFileSync(metadataPath, 'utf8'); + repositoryMetadata = JSON.parse(metadataContent); + console.log(`Loaded metadata for ${repositoryMetadata.length} repositories`); + } catch (error) { + console.log('No repository metadata found, continuing without archived status'); + } + + // Step 3: Generate the packages data + const packagesData = generatePackagesJson(distPath, repositoryMetadata); + + // Step 4: Write the packages.json file + writePackagesJson(packagesData, './packages.json'); + + console.log('Packages.json generation completed successfully'); + return packagesData; + + } catch (error) { + console.error('Error during packages.json generation:', error); + throw error; + } +} + +module.exports = { + generatePackagesWithCleanup +}; diff --git a/.github/scripts/sync-assets-with-metadata.js b/.github/scripts/sync-assets-with-metadata.js new file mode 100644 index 00000000..dc83b74b --- /dev/null +++ b/.github/scripts/sync-assets-with-metadata.js @@ -0,0 +1,35 @@ +const fs = require('fs'); +const { syncReleaseAssets } = require('./sync-assets.js'); + +/** + * Main function to sync assets and store repository metadata + * @param {Object} github - GitHub API client + * @param {Object} context - GitHub Actions context + * @param {boolean} isPullRequest - Whether this is a pull request event + * @param {number} maxNewAssets - Maximum number of new assets to download + */ +async function syncAssetsWithMetadata(github, context, isPullRequest = false, maxNewAssets = 0) { + console.log('Starting asset synchronization process...'); + + try { + // Run the asset synchronization + const repositoryData = await syncReleaseAssets(github, context, isPullRequest, maxNewAssets); + + // Store repository data for use in next step + const metadataPath = 'repo-metadata.json'; + fs.writeFileSync(metadataPath, JSON.stringify(repositoryData, null, 2)); + + console.log(`Stored metadata for ${repositoryData.length} repositories in ${metadataPath}`); + console.log('Asset synchronization completed successfully'); + + return repositoryData; + + } catch (error) { + console.error('Error during asset synchronization:', error); + throw error; + } +} + +module.exports = { + syncAssetsWithMetadata +}; diff --git a/.github/workflows/sync-release-assets.yml b/.github/workflows/sync-release-assets.yml index c280ea4d..6ec52dd4 100644 --- a/.github/workflows/sync-release-assets.yml +++ b/.github/workflows/sync-release-assets.yml @@ -53,8 +53,8 @@ jobs: with: github-token: ${{ secrets.GH_BOT_TOKEN }} script: | - // Import the sync assets module - const { syncReleaseAssets } = require('./.github/scripts/sync-assets.js'); + // Import the sync assets with metadata module + const { syncAssetsWithMetadata } = require('./.github/scripts/sync-assets-with-metadata.js'); // Check if this is a pull request event const isPullRequest = context.eventName === 'pull_request'; @@ -62,14 +62,11 @@ jobs: // Get the max new assets limit from environment const maxNewAssets = parseInt(process.env.MAX_NEW_ASSETS) || 0; - // Run the asset synchronization with PR limit and asset limit // Change working directory to dist for file operations process.chdir('./dist'); - const repositoryData = await syncReleaseAssets(github, context, isPullRequest, maxNewAssets); - // Store repository data for use in next step - const fs = require('fs'); - fs.writeFileSync('repo-metadata.json', JSON.stringify(repositoryData, null, 2)); + // Run the asset synchronization and store metadata + await syncAssetsWithMetadata(github, context, isPullRequest, maxNewAssets); - name: Generate packages.json uses: actions/github-script@v8 @@ -77,28 +74,15 @@ jobs: github-token: ${{ secrets.GH_BOT_TOKEN }} script: | // Import the packages generation module - const { generatePackagesJson, writePackagesJson } = require('./.github/scripts/generate-packages.js'); + const { generatePackagesWithCleanup } = require('./.github/scripts/generate-packages-with-cleanup.js'); console.log('Generating packages.json from dist directory...'); // Change to dist directory process.chdir('./dist'); - // Read repository metadata from previous step - const fs = require('fs'); - let repositoryMetadata = []; - try { - const metadataContent = fs.readFileSync('repo-metadata.json', 'utf8'); - repositoryMetadata = JSON.parse(metadataContent); - } catch (error) { - console.log('No repository metadata found, continuing without archived status'); - } - - // Generate the packages data - const packagesData = generatePackagesJson('.', repositoryMetadata); - - // Write the packages.json file - writePackagesJson(packagesData, './packages.json'); + // Generate packages.json with cleanup + generatePackagesWithCleanup('.'); - name: Commit and push changes if: github.event_name != 'pull_request' diff --git a/gh-pages-template/assets/js/app.js b/gh-pages-template/assets/js/app.js index 34f05642..1fa4a2ba 100644 --- a/gh-pages-template/assets/js/app.js +++ b/gh-pages-template/assets/js/app.js @@ -144,7 +144,7 @@ class UIManager { `).join('') : '
  • No releases found
  • '} ${hasMoreReleases ? `
  • - Show ${remainingCount} more release${releaseText}