Organize log output in collapsible groups for better readability in workflow logs. This system allows you to structure console output into logical sections that can be expanded or collapsed in the GitHub Actions workflow interface.
Begins a new output group with the specified name. All subsequent log output will be grouped under this name until endGroup() is called.
/**
* Begin an output group
* Output until the next `groupEnd` will be foldable in this group
* @param name - The name of the output group
*/
function startGroup(name: string): void;Usage Examples:
import { startGroup, info } from '@actions/core';
// Start a group for initialization
startGroup('Application Initialization');
info('Loading configuration...');
info('Connecting to database...');
info('Setting up middleware...');
// Group continues until endGroup() is calledEnds the current output group. Any log output after this call will not be part of the group.
/**
* End an output group
*/
function endGroup(): void;Usage Examples:
import { startGroup, endGroup, info } from '@actions/core';
startGroup('Database Migration');
info('Starting migration process...');
info('Running migration 001_create_users...');
info('Running migration 002_add_indexes...');
info('Migration completed successfully');
endGroup();
info('This log line is not part of any group');Wraps an asynchronous function call in a group, automatically handling the start and end of the group even if the function throws an error.
/**
* Wrap an asynchronous function call in a group
* Returns the same type as the function itself
* @param name - The name of the group
* @param fn - The function to wrap in the group
* @returns Promise that resolves to the function's return value
*/
function group<T>(name: string, fn: () => Promise<T>): Promise<T>;Usage Examples:
import { group, info } from '@actions/core';
// Simple grouped operation
const result = await group('Data Processing', async () => {
info('Loading data from API...');
const data = await fetchApiData();
info('Processing data...');
const processed = processData(data);
info('Saving results...');
await saveResults(processed);
return processed;
});
// Group with error handling
try {
const deployResult = await group('Deployment', async () => {
info('Building application...');
await buildApplication();
info('Running tests...');
await runTests();
info('Deploying to production...');
return await deployToProduction();
});
info(`Deployment successful: ${deployResult.url}`);
} catch (error) {
// Group is automatically ended even if error occurs
setFailed(`Deployment failed: ${error.message}`);
}import { startGroup, endGroup, info, error } from '@actions/core';
async function processFiles(files: string[]) {
for (const file of files) {
startGroup(`Processing ${file}`);
try {
info('Reading file...');
const content = await readFile(file);
info('Validating content...');
const isValid = validateContent(content);
if (isValid) {
info('Processing content...');
const result = await processContent(content);
info(`Processing completed: ${result.summary}`);
} else {
error('Content validation failed');
}
} catch (err) {
error(`Error processing file: ${err.message}`);
} finally {
endGroup();
}
}
}import { startGroup, endGroup, info } from '@actions/core';
async function deployApplication() {
startGroup('Application Deployment');
startGroup('Pre-deployment Checks');
info('Checking system requirements...');
info('Validating configuration...');
info('Testing database connection...');
endGroup();
startGroup('Build Process');
info('Installing dependencies...');
info('Compiling TypeScript...');
info('Bundling assets...');
info('Running tests...');
endGroup();
startGroup('Deployment');
info('Uploading files...');
info('Updating configuration...');
info('Restarting services...');
info('Running health checks...');
endGroup();
endGroup(); // End main deployment group
}import { group, info } from '@actions/core';
async function parallelProcessing() {
// Run multiple grouped operations in parallel
const operations = [
group('Database Backup', async () => {
info('Connecting to database...');
info('Creating backup...');
info('Verifying backup integrity...');
return 'backup-completed';
}),
group('Asset Compilation', async () => {
info('Compiling SCSS...');
info('Minifying JavaScript...');
info('Optimizing images...');
return 'assets-compiled';
}),
group('Test Suite', async () => {
info('Running unit tests...');
info('Running integration tests...');
info('Generating coverage report...');
return 'tests-passed';
})
];
const results = await Promise.all(operations);
info(`All operations completed: ${results.join(', ')}`);
}import { group, startGroup, endGroup, info, isDebug } from '@actions/core';
async function conditionalGrouping(enableVerbose: boolean) {
if (enableVerbose || isDebug()) {
// Use detailed grouping for verbose output
startGroup('Detailed Processing');
startGroup('Phase 1: Initialization');
info('Loading modules...');
info('Setting up environment...');
endGroup();
startGroup('Phase 2: Processing');
info('Processing item 1...');
info('Processing item 2...');
endGroup();
endGroup();
} else {
// Use simple grouping for normal output
await group('Processing', async () => {
info('Initializing and processing items...');
await doWork();
info('Processing completed');
});
}
}import { group, info, warning, error } from '@actions/core';
async function robustProcessing() {
const operations = [
'validate-input',
'process-data',
'generate-output',
'cleanup'
];
for (const operation of operations) {
try {
await group(operation, async () => {
switch (operation) {
case 'validate-input':
info('Validating input data...');
await validateInput();
break;
case 'process-data':
info('Processing data...');
await processData();
break;
case 'generate-output':
info('Generating output files...');
await generateOutput();
break;
case 'cleanup':
info('Cleaning up temporary files...');
await cleanup();
break;
}
});
} catch (err) {
if (operation === 'cleanup') {
// Cleanup failures are warnings, not critical errors
warning(`Cleanup failed: ${err.message}`);
} else {
error(`Operation ${operation} failed: ${err.message}`);
throw err; // Re-throw to stop processing
}
}
}
}import { group, info } from '@actions/core';
async function performanceMonitoring() {
const startTime = Date.now();
const result = await group('Performance-Monitored Operation', async () => {
const operationStart = Date.now();
info('Starting time-sensitive operation...');
const data = await fetchLargeDataset();
info(`Data fetch completed in ${Date.now() - operationStart}ms`);
const processStart = Date.now();
const processed = await processLargeDataset(data);
info(`Data processing completed in ${Date.now() - processStart}ms`);
return processed;
});
const totalTime = Date.now() - startTime;
info(`Total operation time: ${totalTime}ms`);
return result;
}Groups appear in the workflow logs as:
Groups help organize complex workflows and make it easier to: