Created
March 24, 2025 09:39
-
-
Save 825i/8d068a1e77cedaf6a02318d255b6a0e8 to your computer and use it in GitHub Desktop.
[Github Actions] - Automatic Workflow Step Expander
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name GitHub Actions Workflow Step Expander | |
// @namespace http://tampermonkey.net/ | |
// @version 1.3 | |
// @description Automatically expands all steps in GitHub Actions workflow runs | |
// @author You | |
// @match https://github.com/*/*/actions/runs/* | |
// @match https://github.com/*/*/actions/workflows/* | |
// @grant none | |
// @run-at document-idle | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
console.log('GitHub Actions Expander: Script started'); | |
// Counter to limit expansion attempts | |
let expansionAttempts = 0; | |
const MAX_ATTEMPTS = 5; | |
// Flag to track if expansion is in progress | |
let isExpanding = false; | |
// Function to check if an element is a gear/options button | |
function isGearButton(element) { | |
if (element.tagName === 'SUMMARY') { | |
return element.classList.contains('Button--iconOnly') || | |
element.querySelector('.octicon-gear') !== null; | |
} | |
return false; | |
} | |
// Function to expand all steps | |
function expandAllSteps() { | |
// Avoid running multiple instances simultaneously | |
if (isExpanding) return; | |
isExpanding = true; | |
// Increment attempt counter | |
expansionAttempts++; | |
console.log(`GitHub Actions Expander: Expansion attempt ${expansionAttempts}/${MAX_ATTEMPTS}`); | |
// First, try to find all collapsed details elements | |
const collapsedDetails = Array.from(document.querySelectorAll('details:not([open])')); | |
// Filter out the gear buttons and expand the rest | |
collapsedDetails.forEach(details => { | |
const summary = details.querySelector('summary'); | |
if (summary && !isGearButton(summary)) { | |
details.setAttribute('open', 'true'); | |
} | |
}); | |
// Also look for specifically collapsed step elements | |
const collapsedSteps = Array.from(document.querySelectorAll('.js-step.collapsed, .ActionList-item.collapsed, .js-workflow-step[aria-expanded="false"]')); | |
collapsedSteps.forEach(step => { | |
const expandBtn = step.querySelector('.js-step-expand-collapse-btn') || | |
step.querySelector('.ActionList-content') || | |
step.querySelector('button[aria-controls]'); | |
if (expandBtn && !expandBtn.closest('summary') && !isGearButton(expandBtn)) { | |
expandBtn.click(); | |
} | |
}); | |
// Check if there are still collapsed elements | |
const stillCollapsed = document.querySelectorAll('details:not([open]):not(.ActionMenu), .js-step.collapsed, .ActionList-item.collapsed'); | |
const collapsedCount = stillCollapsed.length; | |
// Reset expanding flag | |
isExpanding = false; | |
// Only continue if there are still collapsed elements and we haven't exceeded max attempts | |
if (collapsedCount > 0 && expansionAttempts < MAX_ATTEMPTS) { | |
console.log(`GitHub Actions Expander: Still found ${collapsedCount} collapsed elements, trying again soon`); | |
setTimeout(expandAllSteps, 1000); | |
} else { | |
console.log('GitHub Actions Expander: Finished expanding elements'); | |
// Reset counter for potential future expansions | |
expansionAttempts = 0; | |
// Disconnect observer after a short delay to allow for any final changes | |
setTimeout(() => { | |
observer.disconnect(); | |
console.log('GitHub Actions Expander: Observer disconnected'); | |
}, 2000); | |
} | |
} | |
// Initial run with a delay to ensure page is loaded | |
setTimeout(expandAllSteps, 2000); | |
// Flag to track navigation | |
let lastUrl = location.href; | |
// Handle dynamically loaded content and URL changes | |
const observer = new MutationObserver((mutations) => { | |
// Check if URL has changed (user navigated to a different workflow) | |
if (lastUrl !== location.href) { | |
lastUrl = location.href; | |
expansionAttempts = 0; // Reset counter | |
console.log('GitHub Actions Expander: URL changed, starting expansion'); | |
setTimeout(expandAllSteps, 1000); | |
return; | |
} | |
// Check for significant DOM changes that might indicate new steps loaded | |
let hasRelevantChanges = false; | |
for (const mutation of mutations) { | |
if (mutation.addedNodes.length > 0) { | |
for (const node of mutation.addedNodes) { | |
if (node.nodeType === Node.ELEMENT_NODE && | |
(node.querySelector('details') || | |
node.querySelector('.js-step') || | |
node.classList?.contains('js-step'))) { | |
hasRelevantChanges = true; | |
break; | |
} | |
} | |
} | |
if (hasRelevantChanges) break; | |
} | |
// Only run expansion if relevant changes detected and not currently expanding | |
if (hasRelevantChanges && !isExpanding && expansionAttempts < MAX_ATTEMPTS) { | |
console.log('GitHub Actions Expander: Detected new workflow elements'); | |
setTimeout(expandAllSteps, 500); | |
} | |
}); | |
// Start observing changes to the DOM | |
observer.observe(document.body, { | |
childList: true, | |
subtree: true, | |
attributes: false, | |
characterData: false | |
}); | |
// Re-attach observer when user navigates | |
window.addEventListener('popstate', () => { | |
if (lastUrl !== location.href) { | |
lastUrl = location.href; | |
expansionAttempts = 0; | |
observer.observe(document.body, { | |
childList: true, | |
subtree: true, | |
attributes: false, | |
characterData: false | |
}); | |
setTimeout(expandAllSteps, 1000); | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This script automatically expands all workflow stages/steps on a workflow page for Github Actions.
I need this because the "search" bar at the top right does not properly search through all workflow steps for search strings eg. "warning", "error" unless a stage has been expanded. I found it frustrating to expand each of the steps manually as some workflows have many steps. Going from bottom to top was the fastest but still annoying when debugging many workflows in a row.
This script takes care of that issue and expands all stages immediately, allowing me to search the entire workflow for strings.
The script also still allows you to collapse steps if you want after they have been expanded (without expanding them again).