-
Notifications
You must be signed in to change notification settings - Fork 0
⚡ Bolt: Optimize sitemap generation using Promise.all #80
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
base: main
Are you sure you want to change the base?
Changes from 2 commits
3c2e0c7
a633d64
7fd6dd1
69ab2ee
f257780
625fd5c
aae0201
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,24 @@ | ||
| name: AI Harness Scorecard | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| schedule: | ||
| - cron: "0 6 * * 1" | ||
| push: | ||
| branches: [main] | ||
| schedule: | ||
| - cron: "0 6 * * 1" | ||
|
|
||
| jobs: | ||
| scorecard: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: markmishaev76/ai-harness-scorecard@v1 | ||
| id: scorecard | ||
| - name: Commit badge and report | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add scorecard-badge.json scorecard-report.md | ||
| git diff --cached --quiet || git commit -m "chore: update scorecard badge and report" | ||
| git push | ||
| scorecard: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: markmishaev76/ai-harness-scorecard@v1 | ||
| id: scorecard | ||
| - name: Commit badge and report | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add scorecard-badge.json scorecard-report.md | ||
| git diff --cached --quiet || git commit -m "chore: update scorecard badge and report" | ||
| git push | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,56 +28,64 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> { | |
| }); | ||
| } | ||
|
|
||
| for (const year of years) { | ||
| urls.push({ | ||
| url: `${baseUrl}/${year}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "daily", | ||
| priority: 0.9, | ||
| }); | ||
| // ⚡ Bolt: Fetch all years' data in parallel to significantly reduce sitemap generation time | ||
| await Promise.all( | ||
| years.map(async (year) => { | ||
| const yearUrls: MetadataRoute.Sitemap = []; | ||
|
|
||
| const yearPages = ["speakers", "talks", "schedule", "job-offers", "cfp", "diversity", "sponsorship", "travel"]; | ||
| for (const page of yearPages) { | ||
| urls.push({ | ||
| url: `${baseUrl}/${year}/${page}`, | ||
| yearUrls.push({ | ||
| url: `${baseUrl}/${year}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "weekly", | ||
| priority: 0.8, | ||
| changeFrequency: "daily", | ||
| priority: 0.9, | ||
| }); | ||
| } | ||
|
|
||
| const speakers = await getSpeakers(year); | ||
| for (const speaker of speakers) { | ||
| urls.push({ | ||
| url: `${baseUrl}/${year}/speakers/${speaker.id}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "weekly", | ||
| priority: 0.7, | ||
| }); | ||
| } | ||
| const yearPages = ["speakers", "talks", "schedule", "job-offers", "cfp", "diversity", "sponsorship", "travel"]; | ||
| for (const page of yearPages) { | ||
| yearUrls.push({ | ||
| url: `${baseUrl}/${year}/${page}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "weekly", | ||
| priority: 0.8, | ||
| }); | ||
| } | ||
|
|
||
| // Fetch speakers and talks in parallel for each year, gracefully handling failures | ||
| const [speakers, sessionGroups] = await Promise.all([getSpeakers(year).catch(() => []), getTalks(year).catch(() => [])]); | ||
|
|
||
| const sessionGroups = await getTalks(year); | ||
| for (const group of sessionGroups) { | ||
| for (const talk of group.sessions) { | ||
| urls.push({ | ||
| url: `${baseUrl}/${year}/talks/${talk.id}`, | ||
| for (const speaker of speakers) { | ||
| yearUrls.push({ | ||
| url: `${baseUrl}/${year}/speakers/${speaker.id}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "weekly", | ||
| priority: 0.7, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| const companies = getJobOffersByYear(year); | ||
| for (const company of companies) { | ||
| urls.push({ | ||
| url: `${baseUrl}/${year}/job-offers/${slugify(company.name)}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "monthly", | ||
| priority: 0.5, | ||
| }); | ||
| } | ||
| } | ||
| for (const group of sessionGroups) { | ||
| for (const talk of group.sessions) { | ||
| yearUrls.push({ | ||
| url: `${baseUrl}/${year}/talks/${talk.id}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "weekly", | ||
| priority: 0.7, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| const companies = getJobOffersByYear(year); | ||
| for (const company of companies) { | ||
| yearUrls.push({ | ||
| url: `${baseUrl}/${year}/job-offers/${slugify(company.name)}`, | ||
| lastModified: new Date(), | ||
| changeFrequency: "monthly", | ||
| priority: 0.5, | ||
| }); | ||
| } | ||
|
|
||
| urls.push(...yearUrls); | ||
| }) | ||
| ); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While the current implementation with A more robust and functional approach is to have each asynchronous operation return its result, and then aggregate the results once all promises have been resolved. This avoids shared mutable state and makes the data flow more explicit. const yearlyUrls = await Promise.all(
years.map(async (year) => {
const yearUrls: MetadataRoute.Sitemap = [];
yearUrls.push({
url: `${baseUrl}/${year}`,
lastModified: new Date(),
changeFrequency: "daily",
priority: 0.9,
});
const yearPages = ["speakers", "talks", "schedule", "job-offers", "cfp", "diversity", "sponsorship", "travel"];
for (const page of yearPages) {
yearUrls.push({
url: `${baseUrl}/${year}/${page}`,
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.8,
});
}
// Fetch speakers and talks in parallel for each year, gracefully handling failures
const [speakers, sessionGroups] = await Promise.all([getSpeakers(year).catch(() => []), getTalks(year).catch(() => [])]);
for (const speaker of speakers) {
yearUrls.push({
url: `${baseUrl}/${year}/speakers/${speaker.id}`,
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.7,
});
}
for (const group of sessionGroups) {
for (const talk of group.sessions) {
yearUrls.push({
url: `${baseUrl}/${year}/talks/${talk.id}`,
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.7,
});
}
}
const companies = getJobOffersByYear(year);
for (const company of companies) {
yearUrls.push({
url: `${baseUrl}/${year}/job-offers/${slugify(company.name)}`,
lastModified: new Date(),
changeFrequency: "monthly",
priority: 0.5,
});
}
return yearUrls;
})
);
urls.push(...yearlyUrls.flat()); |
||
|
|
||
| return urls; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: anyulled/devbcn-nextjs
Length of output: 99
🏁 Script executed:
Repository: anyulled/devbcn-nextjs
Length of output: 894
🌐 Web query:
GitHub Actions security hardening pin third-party actions commit SHA💡 Result:
To harden GitHub Actions against supply‑chain attacks, pin any third‑party action (and reusable workflow) to an immutable reference—preferably a full commit SHA rather than a mutable tag like
@v1or a branch like@main. GitHub explicitly notes that pinning to a full‑length commit SHA is currently the only way to use an action as an immutable release. [1]Why pin to a commit SHA (vs tags)
uses: owner/action@v1may execute different code later without changing your workflow file. GitHub recommends SHA pinning to reduce impact of compromised dependencies. [1][2]How to pin (example)
Instead of:
Use the exact commit:
(Replace with the commit that corresponds to the release you reviewed.) [1][3]
Enforce SHA pinning
Keeping pinned SHAs updated safely
Sources
Pin the third-party action to an immutable commit SHA.
This workflow grants
contents: writepermission to a third-party action and then commits and pushes back to the repository. GitHub's security guidance recommends pinning all third-party actions to a full-length commit SHA because tags like@v1are mutable and can be retagged; a compromised action could exploit write access to introduce malicious code into your repository. Commit SHAs are the only immutable reference for actions.🔒 Suggested hardening
🤖 Prompt for AI Agents