Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions src/components/docs/versions/build-status-dashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React from 'react';
import { useFirestore, useFirestoreCollectionData } from 'reactfire';
import Spinner from '@site/src/components/molecules/spinner';

interface Props {
selectedRepoVersion: string | undefined;
}

const BuildStatusDashboard = ({ selectedRepoVersion }: Props) => {
if (!selectedRepoVersion) return null;

const ciBuilds = useFirestore()
.collection('ciBuilds')
.where('buildInfo.repoVersion', '==', selectedRepoVersion);

const { status, data } = useFirestoreCollectionData<{ [key: string]: any }>(ciBuilds);
Comment on lines +9 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

React hooks rule violation: early return before hooks.

The conditional return on line 10 occurs before the useFirestore and useFirestoreCollectionData hooks are called on lines 12 and 16. This violates React's rules of hooks—hooks must be called unconditionally and in the same order on every render.

🐛 Proposed fix: move early return after hooks
 const BuildStatusDashboard = ({ selectedRepoVersion }: Props) => {
-  if (!selectedRepoVersion) return null;
-
   const ciBuilds = useFirestore()
     .collection('ciBuilds')
     .where('buildInfo.repoVersion', '==', selectedRepoVersion);

   const { status, data } = useFirestoreCollectionData<{ [key: string]: any }>(ciBuilds);

+  if (!selectedRepoVersion) return null;
+
   if (status === 'loading') {

Note: You may also need to handle the case where selectedRepoVersion is undefined in the Firestore query, or conditionally skip the query entirely using a pattern like passing a dummy value when undefined.

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

In `@src/components/docs/versions/build-status-dashboard.tsx` around lines 9 - 16,
Move the hook calls out of the early-return path in BuildStatusDashboard so
useFirestore() and useFirestoreCollectionData(...) are invoked unconditionally;
create ciBuilds based on selectedRepoVersion after calling useFirestore (e.g.,
build a query variable that is null/placeholder when selectedRepoVersion is
undefined, or use a Firestore “skip” pattern) and pass that into
useFirestoreCollectionData so the hooks are always called in the same order;
then perform the early return (or render a loading/empty state) if
selectedRepoVersion is falsy or if the query was skipped.


if (status === 'loading') {
return (
<div style={{ padding: '8px 0', display: 'flex', alignItems: 'center', gap: 8 }}>
<Spinner type="slow" /> Loading build stats...
</div>
);
}

const builds = data || [];
const started = builds.filter((b) => b.status === 'started').length;
const failed = builds.filter((b) => b.status === 'failed').length;
const published = builds.filter((b) => b.status === 'published').length;
const maxedOut = builds.filter(
(b) => b.status === 'failed' && (b.meta?.failureCount || 0) >= 15,
).length;
const total = builds.length;

const statStyle = (color: string): React.CSSProperties => ({
display: 'inline-flex',
alignItems: 'center',
gap: 6,
padding: '4px 12px',
borderRadius: 6,
border: `1px solid ${color}33`,
background: `${color}11`,
fontSize: '0.85em',
fontWeight: 500,
});

return (
<div
style={{
display: 'flex',
flexWrap: 'wrap',
gap: 8,
padding: '12px 0',
alignItems: 'center',
}}
>
<span style={statStyle('#666')}>
Total: <strong>{total}</strong>
</span>
<span style={statStyle('#22c55e')}>
Published: <strong>{published}</strong>
</span>
<span style={statStyle('#3b82f6')}>
In progress: <strong>{started}</strong>
</span>
<span style={statStyle('#ef4444')}>
Failed: <strong>{failed}</strong>
</span>
{maxedOut > 0 && (
<span style={statStyle('#b45309')}>
Stuck (15+): <strong>{maxedOut}</strong>
</span>
)}
<span
style={{
marginLeft: 'auto',
fontSize: '0.75em',
opacity: 0.6,
display: 'inline-flex',
alignItems: 'center',
gap: 4,
}}
>
<span
style={{
width: 6,
height: 6,
borderRadius: '50%',
background: '#22c55e',
display: 'inline-block',
animation: 'pulse 2s infinite',
}}
/>
Live
</span>
Comment on lines +84 to +95
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for `@keyframes` pulse definition in the codebase
rg -n '@keyframes\s+pulse' --type=css --type=scss

Repository: game-ci/documentation

Length of output: 93


🏁 Script executed:

#!/bin/bash
# Search for `@keyframes` pulse in all files
rg -n '@keyframes\s+pulse' .

# Also search for pulse animation in CSS/SCSS files
echo "=== Searching in .css and .scss files ==="
rg -n 'pulse' --type-list | grep -E 'css|style'

Repository: game-ci/documentation

Length of output: 513


🏁 Script executed:

#!/bin/bash
# Search for CSS/style related files
fd -e css -e scss -e module.css

# Check the reviewed file for imports
echo "=== Checking imports in build-status-dashboard.tsx ==="
head -20 src/components/docs/versions/build-status-dashboard.tsx

# Search for animation definitions in global styles or Tailwind
echo "=== Searching for global CSS files ==="
fd -E node_modules -e css -e scss | grep -E '(global|tailwind|index)'

Repository: game-ci/documentation

Length of output: 1066


🏁 Script executed:

#!/bin/bash
# Check if Tailwind is used and if pulse is a Tailwind animation
rg -n 'class=".*pulse' . --type-list | head -20

# Search broadly for "pulse" in the codebase
rg -n '"pulse"' . -A 2 -B 2 | head -50

Repository: game-ci/documentation

Length of output: 910


🏁 Script executed:

#!/bin/bash
# Check the Spinner component and its styles
echo "=== spinner.module.scss ==="
cat src/components/molecules/spinner.module.scss

echo -e "\n=== Spinner component source ==="
cat src/components/molecules/spinner.tsx

# Also check custom.css for global animations
echo -e "\n=== custom.css ==="
cat src/css/custom.css | head -100

Repository: game-ci/documentation

Length of output: 3763


CSS animation pulse is not defined and will not work.

The inline style references animation: 'pulse 2s infinite' but there is no @keyframes pulse definition in the codebase. Add the keyframe animation to a global stylesheet or CSS module, or replace 'pulse' with an existing animation such as 'spin'.

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

In `@src/components/docs/versions/build-status-dashboard.tsx` around lines 84 -
95, The span element using inline style animation: 'pulse 2s infinite'
references a non-existent keyframes animation; to fix, either add a matching
`@keyframes` pulse definition to your global CSS or component CSS module (so the
inline animation name resolves), or change the inline animation to an existing
animation name (e.g., 'spin 2s linear infinite') that is already defined; locate
the offending inline style on the span with animation: 'pulse 2s infinite' in
the build-status-dashboard component and update it accordingly.

</div>
);
};

export default BuildStatusDashboard;
19 changes: 19 additions & 0 deletions src/components/docs/versions/builds/build-failure-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
}: Props) => {
const { editorVersion, baseOs, targetPlatform } = ciBuild.buildInfo;
const { major, minor, patch } = repoVersionInfo;
const buildRepoVersion = ciBuild.buildInfo.repoVersion;

Check failure on line 21 in src/components/docs/versions/builds/build-failure-details.tsx

View workflow job for this annotation

GitHub Actions / Code styles

Use destructured variables over properties
const jobRepoVersion = repoVersionInfo.version;

Check failure on line 22 in src/components/docs/versions/builds/build-failure-details.tsx

View workflow job for this annotation

GitHub Actions / Code styles

Use destructured variables over properties
const hasRepoVersionDrift = jobRepoVersion !== buildRepoVersion;
Comment on lines 19 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Lint: use destructured variables over property access.

Static analysis flags lines 21-22. Since buildInfo is already destructured from ciBuild, and repoVersionInfo is available, prefer extracting these values via destructuring.

🔧 Proposed fix
-  const { editorVersion, baseOs, targetPlatform } = ciBuild.buildInfo;
-  const { major, minor, patch } = repoVersionInfo;
-  const buildRepoVersion = ciBuild.buildInfo.repoVersion;
-  const jobRepoVersion = repoVersionInfo.version;
+  const { editorVersion, baseOs, targetPlatform, repoVersion: buildRepoVersion } = ciBuild.buildInfo;
+  const { major, minor, patch, version: jobRepoVersion } = repoVersionInfo;
   const hasRepoVersionDrift = jobRepoVersion !== buildRepoVersion;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { editorVersion, baseOs, targetPlatform } = ciBuild.buildInfo;
const { major, minor, patch } = repoVersionInfo;
const buildRepoVersion = ciBuild.buildInfo.repoVersion;
const jobRepoVersion = repoVersionInfo.version;
const hasRepoVersionDrift = jobRepoVersion !== buildRepoVersion;
const { editorVersion, baseOs, targetPlatform, repoVersion: buildRepoVersion } = ciBuild.buildInfo;
const { major, minor, patch, version: jobRepoVersion } = repoVersionInfo;
const hasRepoVersionDrift = jobRepoVersion !== buildRepoVersion;
🧰 Tools
🪛 GitHub Check: Code styles

[failure] 22-22:
Use destructured variables over properties


[failure] 21-21:
Use destructured variables over properties

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

In `@src/components/docs/versions/builds/build-failure-details.tsx` around lines
19 - 23, The code accesses repoVersion and version via property access even
though buildInfo and repoVersionInfo are available; destructure repoVersion from
ciBuild.buildInfo alongside editorVersion/baseOs/targetPlatform and destructure
version from repoVersionInfo alongside major/minor/patch, then replace
buildRepoVersion and jobRepoVersion assignments to use those destructured
variables so hasRepoVersionDrift compares the destructured values (references:
ciBuild.buildInfo, repoVersionInfo, buildRepoVersion, jobRepoVersion,
hasRepoVersionDrift).


const reducer = (state, action) => {
const { tag, value } = action;
Expand Down Expand Up @@ -72,6 +75,22 @@

return (
<div {...rest}>
<h4>Operational diagnostics</h4>
<CodeBlock language="json">
{JSON.stringify(
{
jobRepoVersion,
buildRepoVersion,
hasRepoVersionDrift,
recommendedAction: hasRepoVersionDrift
? 'Do not keep retrying this build as-is. Inspect stale older-version jobs and supersede them before retrying current jobs.'
: 'Retry/reset/cleanup actions on this page are safe to use if the failure is still active.',
},
null,
2,
)}
</CodeBlock>
<br />
<h4>CI Job identification</h4>
<CodeBlock language="json">{JSON.stringify(ciJob, null, 2)}</CodeBlock>
<br />
Expand Down
Loading
Loading