Skip to content
Closed
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
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ When a team edits their `devops-maturity.yml` assessment file the action will:
3. Update the `README.md` badge in-place (or prepend one if none exists).
4. Open (or update) a pull request containing the badge change for review.

Set `report: true` to also generate a human-readable maturity report in the
workflow run summary (see [Reports](#reports)).

## Usage

### Minimal setup
Expand Down Expand Up @@ -80,6 +83,7 @@ D202: false # Functional Testing (must have)
| `pr-title` | no | `chore: update devops-maturity badges` | Title of the pull request. |
| `pr-body` | no | *(auto-generated)* | Body text of the pull request. |
| `cli-version` | no | *(latest)* | Pin a specific CLI version for reproducible results (e.g. `0.1.0`). |
| `report` | no | `false` | When `true`, write a maturity report (score, category breakdown, recommendations) to the run summary. |

## Outputs

Expand All @@ -89,6 +93,7 @@ D202: false # Functional Testing (must have)
| `level` | Maturity level: `WIP`, `PASSING`, `BRONZE`, `SILVER`, or `GOLD`. |
| `badge-url` | shields.io badge URL for the current maturity level. |
| `badge-markdown` | Ready-to-paste Markdown snippet for the badge. |
| `report-path` | Path to the generated Markdown report (only when `report: true`). |
| `pull-request-number`| Number of the created (or updated) pull request. |
| `pull-request-url` | HTML URL of the created (or updated) pull request. |

Expand All @@ -107,6 +112,37 @@ D202: false # Functional Testing (must have)
echo "PR : ${{ steps.maturity.outputs.pull-request-url }}"
```

## Reports

Set `report: true` to generate a human-readable maturity report — the overall
score and level, a per-category breakdown, and the list of unmet criteria with
improvement recommendations. The report is written to the workflow run's
[job summary](https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary),
so it shows up directly on the Actions run page — no artifact download needed.

```yaml
- uses: devops-maturity/devops-maturity-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
report: true
```

The same Markdown is also written to a file, exposed via the `report-path`
output, so you can upload it as an artifact if you want to keep it:

```yaml
- id: maturity
uses: devops-maturity/devops-maturity-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
report: true

- uses: actions/upload-artifact@v4
with:
name: devops-maturity-report
path: ${{ steps.maturity.outputs.report-path }}
```

## Permissions

The workflow job must have the following permissions:
Expand Down
86 changes: 86 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ inputs:
required: false
default: ''

report:
description: >
When 'true', generate a human-readable maturity report (score, level,
category breakdown, and improvement recommendations) and write it to the
GitHub Actions job summary. The same Markdown is written to a file whose
path is exposed via the 'report-path' output, so it can be uploaded as an
artifact.
required: false
default: 'false'

outputs:
score:
description: 'Overall DevOps maturity score as a percentage (e.g. "72.3%").'
Expand All @@ -77,6 +87,12 @@ outputs:
description: 'Ready-to-paste Markdown snippet for the badge.'
value: ${{ steps.assessment.outputs.badge_markdown }}

report-path:
description: >
Filesystem path to the generated Markdown report. Only set when the
'report' input is 'true'.
value: ${{ steps.report.outputs.report_path }}

pull-request-number:
description: 'Number of the created (or updated) pull request.'
value: ${{ steps.create-pr.outputs.pull-request-number }}
Expand Down Expand Up @@ -134,6 +150,76 @@ runs:
echo "badge_url=${BADGE_URL}" >> "$GITHUB_OUTPUT"
echo "badge_markdown=${BADGE_MD}" >> "$GITHUB_OUTPUT"

# Persist the full JSON so the (optional) report step can reuse it.
printf '%s' "$JSON_OUTPUT" > "$RUNNER_TEMP/devops-maturity.json"

# ── 2b. Generate maturity report (optional) ──────────────────────────────
- name: Generate maturity report
id: report
if: ${{ inputs.report == 'true' }}
shell: python
env:
DM_JSON: ${{ runner.temp }}/devops-maturity.json
run: |
import json
import os

with open(os.environ["DM_JSON"], encoding="utf-8") as fh:
result = json.load(fh)

def bar(pct: float) -> str:
filled = int(round(pct / 10))
return "█" * filled + "░" * (10 - filled)

passed = result.get("passed", [])
failed = result.get("failed", [])
total = len(passed) + len(failed)

lines = [
f"# DevOps Maturity Report — {result.get('project_name', 'project')}",
"",
f"**Score:** {result.get('score')}% · **Level:** {result.get('level')}",
"",
result.get("badge_markdown", ""),
"",
"## Category breakdown",
"",
"| Category | Score | |",
"|---|---:|:--|",
]
for category, cat_score in result.get("category_scores", {}).items():
lines.append(f"| {category} | {cat_score:.0f}% | `{bar(cat_score)}` |")

lines += ["", f"## Met ({len(passed)}/{total})", ""]
lines.append(", ".join(f"`{c['id']}`" for c in passed) if passed else "_None yet._")

lines += ["", f"## Improvement recommendations ({len(failed)})", ""]
if failed:
for c in failed:
desc = c.get("description", "")
suffix = f" — {desc}" if desc else ""
lines.append(f"- **{c['id']} · {c['criteria']}**{suffix}")
else:
lines.append("_All criteria met. 🎉_")

report_md = "\n".join(lines) + "\n"

# Render into the Actions run summary (visible in the workflow UI).
summary_path = os.environ.get("GITHUB_STEP_SUMMARY")
if summary_path:
with open(summary_path, "a", encoding="utf-8") as fh:
fh.write(report_md)

# Write to a file outside the repo so it is not committed to the PR.
report_path = os.path.join(os.environ["RUNNER_TEMP"], "devops-maturity-report.md")
with open(report_path, "w", encoding="utf-8") as fh:
fh.write(report_md)

with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh:
fh.write(f"report_path={report_path}\n")

print(f"Maturity report written to the job summary and {report_path}")

# ── 3. Update README badge ────────────────────────────────────────────────
- name: Update README badge
shell: python
Expand Down