Skip to content

Automate Ironic release version detection#87

Open
elfosardo wants to merge 1 commit intoOpenStackweb:masterfrom
elfosardo:automated-ironic-version
Open

Automate Ironic release version detection#87
elfosardo wants to merge 1 commit intoOpenStackweb:masterfrom
elfosardo:automated-ironic-version

Conversation

@elfosardo
Copy link
Contributor

@elfosardo elfosardo commented Mar 18, 2026

Replace static version hardcoding with fully dynamic fetching from OpenStack
releases repository at build time. The website now automatically displays
the latest Ironic version and handles new release series without any manual
updates.

  • Add dynamic series detection from OpenStack series_status.yaml
  • Implement automatic series-to-version mapping (e.g., gazpacho → 2026.1)
  • Add sourceNodes function to fetch latest release at build time
  • Update index page template to use dynamic release data
  • Add comprehensive fallback mechanisms for API failures
  • Update CMS preview template with mock release data
  • Add test script to verify dynamic detection works
  • Remove all hardcoded series names and version mappings

The system fetches both series list and version mappings dynamically,
making it completely self-maintaining for future OpenStack releases.
Version is fetched once per build and baked into static HTML for optimal
performance.

Assisted-By: Claude 4.6 Opus High

Summary by CodeRabbit

  • New Features

    • Homepage now displays the latest Ironic release (version, publish date, and release notes link) surfaced from site data.
  • Content Changes

    • Homepage header shows a "Loading latest release..." state and links to the Ironic release notes index when data isn't available.
    • Preview mode provides mock latest-release data for content previews.
  • Tests

    • Added a runnable script to validate release-data detection and fetching.
  • Chores

    • Updated project test scripts to run the new release-fetch validation.

@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

📝 Walkthrough

Walkthrough

Adds Gatsby source logic that detects the latest OpenStack Ironic series, fetches and parses deliverable YAML to create an IronicRelease GraphQL node, surfaces that node to the index template and CMS preview, and includes a CLI test script plus npm script entries to validate the detection/fetch flow.

Changes

Cohort / File(s) Summary
Gatsby source & schema
gatsby-node.js
Adds axios usage, createSchemaCustomization with IronicRelease type, and a new exports.sourceNodes that detects series (via series_status.yaml and HEAD probes), fetches deliverables/<series>/ironic.yaml, parses latest - version: x.y.z, optionally resolves publishedAt via commit hash → GitHub commits API, creates IronicRelease node, and provides a hardcoded fallback node on error.
Local test harness
test-release-fetch.js, package.json
New test-release-fetch.js script that replicates detection/fetch/parsing flow with logging and fallbacks; package.json test script changed to node test-release-fetch.js and a new test:release script added.
Index template & query
src/templates/index-page.js
IndexPageTemplate now accepts latestRelease; computes dynamicHeader to override header.bottomtext when latestRelease present; IndexPage pulls data.ironicRelease and passes latestRelease; GraphQL page query extended to request ironicRelease { version releaseNotesUrl publishedAt htmlUrl }; propTypes updated accordingly.
CMS preview
src/cms/preview-templates/IndexPagePreview.js
Adds a mockReleaseData object and passes latestRelease={mockReleaseData} into IndexPageTemplate in the CMS preview path.
Content update
src/pages/index.md
Replaced a hardcoded “31.0.0 release available now” bottomtext and specific release-notes anchor with a generic “Loading latest release...” message and a link to the Ironic release notes index.

Sequence Diagram

sequenceDiagram
    participant Build as Gatsby Build
    participant GitHub as GitHub Raw Content
    participant Parser as Parser/Regex/YAML
    participant GraphQL as Gatsby GraphQL
    participant Template as Index Template

    Build->>GitHub: GET /releases/.../series_status.yaml
    GitHub-->>Build: series_status.yaml
    Build->>Parser: extract series order & mapping
    loop detect series
        Build->>GitHub: HEAD deliverables/<series>/ironic.yaml
        GitHub-->>Build: 200 / 404
    end
    alt deliverable found
        Build->>GitHub: GET deliverables/<detected>/ironic.yaml
        GitHub-->>Build: ironic.yaml (YAML)
        Build->>Parser: parse versions (- version: x.y.z) & extract release hash
        Parser-->>Build: latest version, hash
        Build->>GitHub: GET commits/<hash> (optional)
        GitHub-->>Build: commit metadata (date)
        Build->>GraphQL: createNode(IronicRelease {version, releaseNotesUrl, publishedAt, htmlUrl})
    else fallback / error
        Build->>GraphQL: createNode(IronicRelease {fallback data})
    end
    Template->>GraphQL: query ironicRelease
    GraphQL-->>Template: return IronicRelease data
    Template->>Template: compute dynamicHeader and render
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped the feeds to fetch the brew,
parsed YAML crumbs and followed the clue,
stitched a node with version bright,
headers now hum the latest sight,
a little hop — releases in view!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly describes the main objective: automating Ironic release version detection. It accurately reflects the core change across all modified files—replacing static version hardcoding with dynamic fetching from the openstack/releases repository at build time.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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

Copy link

@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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@gatsby-node.js`:
- Around line 148-157: The current regex and selection logic (yamlContent,
releaseMatches, latestVersionMatch, version) only capture numeric parts and
blindly picks the last match, which drops prerelease suffixes; change the regex
to capture the full token (e.g., /- version: ([^\s]+)/g) so you get complete
version strings, then build an array of those captured versions and iterate from
newest to oldest to pick the first entry that is not a prerelease (detect
prereleases with a simple pattern like /[A-Za-z-]/ or a semver prerelease check
/-(alpha|beta|rc|dev)|[A-Za-z]/i) and assign that to version; this ensures
prerelease tags (e.g., 34.0.0rc1) aren’t truncated and are skipped in favor of
the latest non-prerelease.
- Around line 139-145: The current catch around the axios.get for the
`ironic.yaml` fetch unconditionally assumes a 404 and switches `releaseSeries`
to 'epoxy' and retries, which misattributes timeouts/5xx/DNS errors and issues
an unbounded second request; update the catch in the try/axios.get for
`ironic.yaml` to check the error's HTTP status (e.g. error.response &&
error.response.status === 404) before setting `releaseSeries = 'epoxy'` and
retrying, otherwise rethrow or surface the original error; also add a bounded
timeout/options object to both axios.get calls (pass a timeout in the config) so
the requests are limited.

In `@package.json`:
- Around line 59-60: Remove the live GitHub/network-dependent check from the
default npm test script so running `npm test` remains deterministic: change the
"test" npm script to a local/deterministic test runner (or a harmless
placeholder) and keep the networked smoke check only under "test:release" which
should run `node test-release-fetch.js`; update the package.json scripts so
"test" does not invoke test-release-fetch.js but "test:release" still does, and
verify test tooling (the "test" script) runs the intended local checks.

In `@test-release-fetch.js`:
- Around line 13-39: The test duplicates parsing and unconditionally fails on
gazpacho instead of using the same fallback logic as gatsby-node.js; update
test-release-fetch.js to import and use the shared helper (or replicate its
behavior) so the code that fetches/parses the YAML uses the same
fallback-from-gazpacho-to-epoxy logic (only fall back on a 404) instead of
immediately throwing. Locate the current fetch/parse variables (response,
yamlContent, releaseMatches, latestVersion and the epoxy equivalents) and
replace their direct axios/get + regex flow with a call to the shared helper
used by gatsby-node.js (or at minimum add a 404 check after the initial
axios.get and only then fetch epoxy) so test behavior matches production.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 63a62524-20e3-4c60-b018-10d96988ee0a

📥 Commits

Reviewing files that changed from the base of the PR and between 11753c7 and ade0c3e.

📒 Files selected for processing (6)
  • gatsby-node.js
  • package.json
  • src/cms/preview-templates/IndexPagePreview.js
  • src/pages/index.md
  • src/templates/index-page.js
  • test-release-fetch.js

Comment on lines +59 to +60
"test": "node test-release-fetch.js",
"test:release": "node test-release-fetch.js"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep the live release smoke check out of the default npm test.

Making npm test depend on a live GitHub request will make local and CI runs flaky on transient network failures or rate limits, even though the site build already has a fallback node. I’d keep this behind npm run test:release and reserve test for deterministic checks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 59 - 60, Remove the live GitHub/network-dependent
check from the default npm test script so running `npm test` remains
deterministic: change the "test" npm script to a local/deterministic test runner
(or a harmless placeholder) and keep the networked smoke check only under
"test:release" which should run `node test-release-fetch.js`; update the
package.json scripts so "test" does not invoke test-release-fetch.js but
"test:release" still does, and verify test tooling (the "test" script) runs the
intended local checks.

@elfosardo elfosardo force-pushed the automated-ironic-version branch from ade0c3e to 60d2d2e Compare March 18, 2026 17:05
Copy link

@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

♻️ Duplicate comments (1)
gatsby-node.js (1)

156-157: ⚠️ Potential issue | 🟠 Major

Bound outbound calls and only skip series on 404.

Line 180 and Line 211 currently swallow all request failures as “try next series”. Timeouts/5xx/DNS issues can silently downgrade to an older series. Also, all these axios calls are unbounded, which can stall builds.

Suggested hardening
+    const requestConfig = { timeout: 10000 }

-      const response = await axios.get('https://api.github.com/repos/openstack/releases/contents/deliverables')
+      const response = await axios.get(
+        'https://api.github.com/repos/openstack/releases/contents/deliverables',
+        requestConfig
+      )

-        await axios.head(`https://raw.githubusercontent.com/openstack/releases/master/deliverables/${series}/ironic.yaml`)
+        await axios.head(
+          `https://raw.githubusercontent.com/openstack/releases/master/deliverables/${series}/ironic.yaml`,
+          requestConfig
+        )
         console.log(`✅ Found Ironic releases in series: ${series}`)
         return series
       } catch (error) {
-        // Series doesn't have ironic.yaml, try next
-        continue
+        if (error.response?.status === 404) continue
+        throw error
       }

-          response = await axios.get(`https://raw.githubusercontent.com/openstack/releases/master/deliverables/${series}/ironic.yaml`)
+          response = await axios.get(
+            `https://raw.githubusercontent.com/openstack/releases/master/deliverables/${series}/ironic.yaml`,
+            requestConfig
+          )
           releaseSeries = series
           break
         } catch (error) {
-          continue
+          if (error.response?.status === 404) continue
+          throw error
         }

-      response = await axios.get(`https://raw.githubusercontent.com/openstack/releases/master/deliverables/${releaseSeries}/ironic.yaml`)
+      response = await axios.get(
+        `https://raw.githubusercontent.com/openstack/releases/master/deliverables/${releaseSeries}/ironic.yaml`,
+        requestConfig
+      )
#!/bin/bash
# Verify outbound request config and catch behavior in gatsby-node.js
rg -n 'axios\.(get|head)\(' gatsby-node.js -C2
rg -n 'catch \(error\)' gatsby-node.js -C3

Also applies to: 176-183, 208-213, 221-221

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gatsby-node.js` around lines 156 - 157, The axios calls (e.g., the const
response = await axios.get(...) that sets discoveredSeries and other
axios.get/axios.head usages) must be bounded and must only treat HTTP 404 as
"skip series" — add a request timeout (via axios.create or per-request timeout)
to avoid unbounded hangs, and in each catch inspect error.response?.status ===
404 to continue, otherwise rethrow or fail the build (for timeouts, 5xx,
DNS/network errors check error.code or missing error.response and propagate).
Update all axios.get/axios.head call sites so they use the timeout-configured
client and the described error handling instead of swallowing all errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@gatsby-node.js`:
- Around line 163-167: The code is incorrectly truncating discoveredSeries to
the first three entries; update the assignment that builds allSeries so it uses
the full discoveredSeries array instead of discoveredSeries.slice(0, 3) (i.e.,
change allSeries = [...discoveredSeries.slice(0, 3), ...knownSeries] to include
all discoveredSeries) and remove the console message truncation so it logs the
full discoveredSeries (or a sensible untruncated representation); apply the same
change in test-release-fetch.js where discoveredSeries is being sliced at entry
41 to ensure consistency.

---

Duplicate comments:
In `@gatsby-node.js`:
- Around line 156-157: The axios calls (e.g., the const response = await
axios.get(...) that sets discoveredSeries and other axios.get/axios.head usages)
must be bounded and must only treat HTTP 404 as "skip series" — add a request
timeout (via axios.create or per-request timeout) to avoid unbounded hangs, and
in each catch inspect error.response?.status === 404 to continue, otherwise
rethrow or fail the build (for timeouts, 5xx, DNS/network errors check
error.code or missing error.response and propagate). Update all
axios.get/axios.head call sites so they use the timeout-configured client and
the described error handling instead of swallowing all errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f64512a-259d-41fc-97b1-5b69505e8d12

📥 Commits

Reviewing files that changed from the base of the PR and between ade0c3e and 60d2d2e.

📒 Files selected for processing (6)
  • gatsby-node.js
  • package.json
  • src/cms/preview-templates/IndexPagePreview.js
  • src/pages/index.md
  • src/templates/index-page.js
  • test-release-fetch.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/pages/index.md
  • package.json
  • test-release-fetch.js

@elfosardo elfosardo force-pushed the automated-ironic-version branch from 60d2d2e to c2bac9b Compare March 19, 2026 14:32
Copy link

@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

♻️ Duplicate comments (1)
test-release-fetch.js (1)

41-44: ⚠️ Potential issue | 🟡 Minor

Fallback series list is inconsistent with gatsby-node.js.

The test's fallback (['gazpacho', 'epoxy', 'dalmatian', 'caracal']) is missing 'hibiscus' and 'flamingo' that are present in gatsby-node.js (lines 165-167). This means the test can fail in scenarios where the build would succeed, defeating the purpose of validating the production code path.

Sync the fallback lists or, better, extract them into a shared module.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test-release-fetch.js` around lines 41 - 44, The test's fallback arrays
(fallbackOrder and fallbackData) are missing series present in the production
list, causing mismatch with gatsby-node.js; update test-release-fetch.js to use
the same canonical fallback series (add 'hibiscus' and 'flamingo' into
fallbackOrder and include their versions in fallbackData) or better yet import
the shared FALLBACK_SERIES/FALLBACK_DATA constant from a common module used by
gatsby-node.js so both test and production use the identical source of truth.
🧹 Nitpick comments (4)
gatsby-node.js (2)

297-304: Fallback version will become stale.

The hardcoded fallback version: '34.0.0' will drift behind actual releases over time. Since this only activates when all network fetches fail, staleness may go unnoticed.

Consider logging a warning at a higher severity level or adding a comment with the date this fallback was last updated to prompt periodic review.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gatsby-node.js` around lines 297 - 304, The hardcoded fallbackData object
(version '34.0.0') in gatsby-node.js will become stale; update the fallback
handling by adding a clear timestamped comment (e.g., "last updated YYYY-MM-DD")
next to the fallbackData declaration and emit a warning-level log (or
throw/report) when the fallback is used so failures are visible; reference the
fallbackData constant and the code path that uses it so the log message includes
context like "using fallbackData version" to prompt periodic review.

135-135: Add request timeouts to all axios calls.

Network requests to GitHub (lines 135, 192, 231, 245) have no timeout configured. A slow or unresponsive upstream can stall the Gatsby build indefinitely.

Suggested fix
+const AXIOS_CONFIG = { timeout: 15000 };
+
 async function getSeriesStatusData() {
   try {
     console.log('📋 Fetching OpenStack series status data...');
-    const response = await axios.get('https://raw.githubusercontent.com/openstack/releases/master/data/series_status.yaml');
+    const response = await axios.get('https://raw.githubusercontent.com/openstack/releases/master/data/series_status.yaml', AXIOS_CONFIG);

Apply the same config to axios.head (line 192) and axios.get calls (lines 231, 245).

Also applies to: 192-192, 231-231, 245-245

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gatsby-node.js` at line 135, The axios calls (e.g., the call assigned to
response: const response = await axios.get(...), the axios.head(...) call, and
the other axios.get(...) calls) lack timeouts and can hang builds; add a timeout
option (for example { timeout: 10000 }) to each axios request or create a shared
axios instance with a default timeout and use that instance for all requests so
every call includes a timeout configuration (apply to the axios.get used for
series_status.yaml, the axios.head call, and the other axios.get calls
referenced).
src/templates/index-page.js (1)

207-212: publishedAt and htmlUrl are fetched but unused.

The GraphQL query retrieves publishedAt and htmlUrl from ironicRelease, but neither is referenced in the template. If these are reserved for future use, that's fine—otherwise remove them to keep the query minimal.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/templates/index-page.js` around lines 207 - 212, The GraphQL selection
set for ironicRelease includes fields publishedAt and htmlUrl that are not used
in the template; either remove these two fields from the ironicRelease selection
in the GraphQL query in index-page.js to keep the query minimal, or if you
intend to display them, wire them into the template where the ironicRelease data
is rendered (e.g., use publishedAt for a release date display and htmlUrl for a
link). Ensure the change targets the ironicRelease selection block so unused
fields are dropped or consumed.
test-release-fetch.js (1)

12-12: Add request timeouts to prevent indefinite hangs.

All axios.get and axios.head calls lack timeouts. If GitHub is slow or unresponsive, the test will hang indefinitely.

Suggested fix
+const REQUEST_CONFIG = { timeout: 15000 };
+
 async function getSeriesStatusData() {
   try {
     console.log('📋 Fetching OpenStack series status data...');
-    const response = await axios.get('https://raw.githubusercontent.com/openstack/releases/master/data/series_status.yaml');
+    const response = await axios.get('https://raw.githubusercontent.com/openstack/releases/master/data/series_status.yaml', REQUEST_CONFIG);

Apply similarly to axios.head (line 62) and axios.get calls (lines 96, 116).

Also applies to: 62-62, 96-96, 116-116

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test-release-fetch.js` at line 12, The axios requests in
test-release-fetch.js (the axios.get that assigns to response and the
axios.head/other axios.get invocations) lack timeouts and can hang; add a
timeout option (e.g., { timeout: 10000 }) to each axios.get and axios.head call
or create an axios instance with a default timeout and use it throughout (locate
the calls where response is assigned from axios.get and the axios.head at line
~62 plus the other axios.get calls around lines ~96 and ~116 and apply the
timeout option or swap to the configured axios instance).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@gatsby-node.js`:
- Line 273: The publishedAt field is being set to the build timestamp
(publishedAt: new Date().toISOString()) which misrepresents the release date;
update the node creation logic (where publishedAt is assigned) to instead: parse
the real release date from the source YAML/frontmatter if present and assign
that value to publishedAt, or if no release date exists set publishedAt to null,
or rename the field to fetchedAt (and update any downstream consumers) to
clearly indicate it's the build fetch time—make the change at the location that
constructs the node/object containing publishedAt so consumers get correct or
explicitly-null/renamed semantics.

---

Duplicate comments:
In `@test-release-fetch.js`:
- Around line 41-44: The test's fallback arrays (fallbackOrder and fallbackData)
are missing series present in the production list, causing mismatch with
gatsby-node.js; update test-release-fetch.js to use the same canonical fallback
series (add 'hibiscus' and 'flamingo' into fallbackOrder and include their
versions in fallbackData) or better yet import the shared
FALLBACK_SERIES/FALLBACK_DATA constant from a common module used by
gatsby-node.js so both test and production use the identical source of truth.

---

Nitpick comments:
In `@gatsby-node.js`:
- Around line 297-304: The hardcoded fallbackData object (version '34.0.0') in
gatsby-node.js will become stale; update the fallback handling by adding a clear
timestamped comment (e.g., "last updated YYYY-MM-DD") next to the fallbackData
declaration and emit a warning-level log (or throw/report) when the fallback is
used so failures are visible; reference the fallbackData constant and the code
path that uses it so the log message includes context like "using fallbackData
version" to prompt periodic review.
- Line 135: The axios calls (e.g., the call assigned to response: const response
= await axios.get(...), the axios.head(...) call, and the other axios.get(...)
calls) lack timeouts and can hang builds; add a timeout option (for example {
timeout: 10000 }) to each axios request or create a shared axios instance with a
default timeout and use that instance for all requests so every call includes a
timeout configuration (apply to the axios.get used for series_status.yaml, the
axios.head call, and the other axios.get calls referenced).

In `@src/templates/index-page.js`:
- Around line 207-212: The GraphQL selection set for ironicRelease includes
fields publishedAt and htmlUrl that are not used in the template; either remove
these two fields from the ironicRelease selection in the GraphQL query in
index-page.js to keep the query minimal, or if you intend to display them, wire
them into the template where the ironicRelease data is rendered (e.g., use
publishedAt for a release date display and htmlUrl for a link). Ensure the
change targets the ironicRelease selection block so unused fields are dropped or
consumed.

In `@test-release-fetch.js`:
- Line 12: The axios requests in test-release-fetch.js (the axios.get that
assigns to response and the axios.head/other axios.get invocations) lack
timeouts and can hang; add a timeout option (e.g., { timeout: 10000 }) to each
axios.get and axios.head call or create an axios instance with a default timeout
and use it throughout (locate the calls where response is assigned from
axios.get and the axios.head at line ~62 plus the other axios.get calls around
lines ~96 and ~116 and apply the timeout option or swap to the configured axios
instance).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5d5132ca-dbc0-47ff-982d-ea1d3732237f

📥 Commits

Reviewing files that changed from the base of the PR and between 60d2d2e and c2bac9b.

📒 Files selected for processing (6)
  • gatsby-node.js
  • package.json
  • src/cms/preview-templates/IndexPagePreview.js
  • src/pages/index.md
  • src/templates/index-page.js
  • test-release-fetch.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/pages/index.md
  • package.json
  • src/cms/preview-templates/IndexPagePreview.js

Replace static version hardcoding with fully dynamic fetching from OpenStack
releases repository at build time. The website now automatically displays
the latest Ironic version with actual release dates and handles new release
series without any manual updates.

- Add dynamic series detection from OpenStack series_status.yaml
- Implement automatic series-to-version mapping (e.g., gazpacho → 2026.1)
- Add sourceNodes function to fetch latest release at build time
- Fetch actual release dates from git commit timestamps via GitHub API
- Update index page template to use dynamic release data
- Add comprehensive fallback mechanisms for API failures
- Update CMS preview template with mock release data
- Add test script to verify dynamic detection and date fetching
- Remove all hardcoded series names and version mappings

The system now fetches series list, version mappings, and actual release
dates dynamically, making it completely self-maintaining for future
OpenStack releases. Version and date are fetched once per build and
baked into static HTML for optimal performance.

Assisted-By: Claude 4.6 Opus High
@elfosardo elfosardo force-pushed the automated-ironic-version branch from c2bac9b to 2f22570 Compare March 19, 2026 15:09
Copy link

@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.

🧹 Nitpick comments (2)
src/cms/preview-templates/IndexPagePreview.js (1)

9-16: Mock data includes releaseSeries which is not in the actual GraphQL query.

The mock includes releaseSeries: "gazpacho", but the ironicRelease GraphQL query in index-page.js doesn't fetch this field. This inconsistency could cause confusion if someone adds code that uses releaseSeries after testing in the CMS preview—it would work in preview but fail in production.

Consider aligning the mock data fields with the actual GraphQL query, or add releaseSeries to the query if it's intended for future use.

♻️ Suggested fix to align with GraphQL query
     const mockReleaseData = {
       version: "34.0.0",
       releaseNotesUrl: "https://docs.openstack.org/releasenotes/ironic/2026.1.html#relnotes-34-0-0",
       publishedAt: null, // Actual release date not available
       htmlUrl: "https://github.com/openstack/releases/blob/master/deliverables/gazpacho/ironic.yaml",
-      releaseSeries: "gazpacho",
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cms/preview-templates/IndexPagePreview.js` around lines 9 - 16, The
mockReleaseData object in IndexPagePreview.js includes releaseSeries which is
not requested by the ironicRelease GraphQL query in index-page.js; either remove
releaseSeries from the mock to match the actual schema or add releaseSeries to
the ironicRelease query (and associated type/resolver) if you intend to use it
in production. Locate mockReleaseData in IndexPagePreview.js and either drop the
releaseSeries property or update the ironicRelease query in index-page.js to
request releaseSeries so both preview and production data shapes match.
src/templates/index-page.js (1)

207-212: publishedAt and htmlUrl are fetched but unused.

The GraphQL query fetches publishedAt and htmlUrl, but only version and releaseNotesUrl are used in the dynamicHeader logic. If these fields are reserved for future features, this is fine. Otherwise, consider removing them to keep the query minimal.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/templates/index-page.js` around lines 207 - 212, The GraphQL query
includes unused fields publishedAt and htmlUrl on the ironicRelease selection
while the dynamicHeader logic only uses version and releaseNotesUrl; remove
publishedAt and htmlUrl from the query (or alternatively use them in
dynamicHeader if intended) so the query only requests necessary fields—locate
the ironicRelease selection in the GraphQL query within index-page.js and delete
publishedAt and htmlUrl (or update dynamicHeader to reference those fields if
they are required).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/cms/preview-templates/IndexPagePreview.js`:
- Around line 9-16: The mockReleaseData object in IndexPagePreview.js includes
releaseSeries which is not requested by the ironicRelease GraphQL query in
index-page.js; either remove releaseSeries from the mock to match the actual
schema or add releaseSeries to the ironicRelease query (and associated
type/resolver) if you intend to use it in production. Locate mockReleaseData in
IndexPagePreview.js and either drop the releaseSeries property or update the
ironicRelease query in index-page.js to request releaseSeries so both preview
and production data shapes match.

In `@src/templates/index-page.js`:
- Around line 207-212: The GraphQL query includes unused fields publishedAt and
htmlUrl on the ironicRelease selection while the dynamicHeader logic only uses
version and releaseNotesUrl; remove publishedAt and htmlUrl from the query (or
alternatively use them in dynamicHeader if intended) so the query only requests
necessary fields—locate the ironicRelease selection in the GraphQL query within
index-page.js and delete publishedAt and htmlUrl (or update dynamicHeader to
reference those fields if they are required).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2357dbfc-0bef-4152-a84c-68636e0b0a7d

📥 Commits

Reviewing files that changed from the base of the PR and between c2bac9b and 2f22570.

📒 Files selected for processing (6)
  • gatsby-node.js
  • package.json
  • src/cms/preview-templates/IndexPagePreview.js
  • src/pages/index.md
  • src/templates/index-page.js
  • test-release-fetch.js
✅ Files skipped from review due to trivial changes (1)
  • test-release-fetch.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/pages/index.md
  • package.json
  • gatsby-node.js

@elfosardo elfosardo requested a review from cardoe March 20, 2026 09:19
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