Skip to content
Merged
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
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

### Changed

### Deprecated

### Removed

### Fixed

### Security

## [0.3.0] - 2026-02-12

### Added
- GitHub Actions step summary with ModularGuard analysis results

## [0.2.0] - 2026-02-12

### Fixed
- Enhanced pull request detection by extracting info from event payload ([#2](https://github.com/n2jsoft-public-org/ModularGuard-action/pull/2))

## [0.1.0] - 2026-02-11

### Added
- Initial release of ModularGuard GitHub Action
- Automatic architecture analysis in CI/CD workflows
- Cross-platform support (Linux, macOS, Windows)
- JSON output parsing and formatting
- Integration with GitHub's annotation system

## [0.0.0] - 2026-02-11

### Added
- Initial project setup ([#1](https://github.com/n2jsoft-public-org/ModularGuard-action/pull/1))

[Unreleased]: https://github.com/n2jsoft-public-org/ModularGuard-action/compare/v0.3.0...HEAD
[0.3.0]: https://github.com/n2jsoft-public-org/ModularGuard-action/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/n2jsoft-public-org/ModularGuard-action/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/n2jsoft-public-org/ModularGuard-action/compare/v0.0.0...v0.1.0
[0.0.0]: https://github.com/n2jsoft-public-org/ModularGuard-action/releases/tag/v0.0.0
81 changes: 81 additions & 0 deletions src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,84 @@ function mapSeverityToLevel(severity: string): 'failure' | 'warning' | 'notice'
return 'notice'
}
}

/**
* Write ModularGuard results to GitHub Actions step summary
*/
export async function writeStepSummary(result: ModularGuardResult, runUrl?: string): Promise<void> {
try {
const { summary, violations } = result
const hasErrors = summary.errorCount > 0
const hasWarnings = summary.warningCount > 0

// Add heading
core.summary.addHeading('ModularGuard Analysis Results', 2)

// Status badge
if (hasErrors) {
core.summary.addRaw('❌ **Analysis Failed**\n\n')
} else if (hasWarnings) {
core.summary.addRaw('⚠️ **Analysis Passed with Warnings**\n\n')
} else {
core.summary.addRaw('✅ **Analysis Passed**\n\n')
}

// Summary statistics
core.summary.addHeading('Summary', 3)
core.summary.addRaw(`- **Total Modules:** ${summary.totalModules}\n`)
core.summary.addRaw(`- **Total Projects:** ${summary.totalProjects}\n`)
core.summary.addRaw(`- **Errors:** ${summary.errorCount}\n`)
core.summary.addRaw(`- **Warnings:** ${summary.warningCount}\n\n`)

// Violations table
if (violations.length > 0) {
core.summary.addHeading('Violations', 3)

// Prepare table data
const tableData = [
[
{ data: 'Severity', header: true },
{ data: 'File:Line', header: true },
{ data: 'Project', header: true },
{ data: 'Invalid Reference', header: true },
{ data: 'Description', header: true },
],
...violations.map((violation) => {
const severityIcon = violation.severity === 'Error' ? '🔴' : '⚠️'
const fileLocation = `${violation.filePath}:${violation.lineNumber}`
const description = violation.description.replace(/\n/g, ' ').substring(0, 100)

return [
`${severityIcon} ${violation.severity}`,
fileLocation,
violation.projectName,
violation.invalidReference,
description,
]
}),
]

core.summary.addTable(tableData)

// Suggestions section if any violations have suggestions
const violationsWithSuggestions = violations.filter((v) => v.suggestion)
if (violationsWithSuggestions.length > 0) {
core.summary.addRaw('\n<details>\n<summary>💡 Suggestions</summary>\n\n')
for (const violation of violationsWithSuggestions) {
core.summary.addRaw(`**${violation.projectName} → ${violation.invalidReference}**\n`)
core.summary.addRaw(`${violation.suggestion}\n\n`)
}
core.summary.addRaw('</details>\n\n')
}
}

if (runUrl) {
core.summary.addRaw(`---\n\n[View detailed results](${runUrl})\n`)
}

// Write the summary
await core.summary.write()
} catch (error) {
core.warning(`Failed to write step summary: ${error instanceof Error ? error.message : String(error)}`)
}
}
5 changes: 5 additions & 0 deletions src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
formatComment,
getPullRequestFromPayload,
toWorkspaceRelativePath,
writeStepSummary,
} from './github.js'

type Inputs = {
Expand Down Expand Up @@ -129,6 +130,10 @@ export const run = async (inputs: Inputs, octokit: Octokit, context: Context): P
// Print violations to console
printViolationsToConsole(resultWithRelativePaths)

// Write step summary
core.info('Writing step summary...')
await writeStepSummary(resultWithRelativePaths, runUrl)

if (isInPRContext) {
core.info('Creating check run with annotations...')
await createCheckRun(octokit, context.repo.owner, context.repo.repo, context.sha, resultWithRelativePaths)
Expand Down