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
159 changes: 0 additions & 159 deletions .github/actions/github-housekeeping/Invoke-PowerForgeHousekeeping.ps1

This file was deleted.

53 changes: 50 additions & 3 deletions .github/actions/github-housekeeping/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ Reusable composite action that runs the config-driven `powerforge github houseke

- Loads housekeeping settings from a repo config file, typically `.powerforge/github-housekeeping.json`
- Runs artifact cleanup, cache cleanup, and optional runner cleanup from one C# entrypoint
- Writes a workflow summary with the requested sections plus before/after cleanup stats
- Writes a rich workflow summary with requested sections, storage deltas, and item details
- Persists a machine-readable JSON report plus a Markdown report artifact for later review

## Recommended usage

Use the reusable workflow for the leanest repo wiring:
Use the public reusable workflow for the leanest repo wiring:

```yaml
permissions:
Expand All @@ -19,12 +20,54 @@ permissions:

jobs:
housekeeping:
uses: EvotecIT/PSPublishModule/.github/workflows/reusable-github-housekeeping.yml@main
uses: EvotecIT/PSPublishModule/.github/workflows/powerforge-github-housekeeping.yml@main
with:
config-path: ./.powerforge/github-housekeeping.json
powerforge-ref: main
secrets: inherit
```

For immutable pinning, use the same PSPublishModule commit SHA for both the reusable workflow ref and `powerforge-ref`.

The reusable workflow uploads the generated JSON and Markdown reports as an artifact by default.

For self-hosted runner disk cleanup, use the dedicated reusable workflow entrypoint:

```yaml
jobs:
housekeeping:
uses: EvotecIT/PSPublishModule/.github/workflows/powerforge-github-runner-housekeeping.yml@main
with:
config-path: ./.powerforge/runner-housekeeping.json
powerforge-ref: main
runner-labels: '["self-hosted","ubuntu"]'
```

Minimal config:

```json
{
"$schema": "https://raw.githubusercontent.com/EvotecIT/PSPublishModule/main/Schemas/github.housekeeping.schema.json",
"repository": "EvotecIT/YourRepo",
"tokenEnvName": "GITHUB_TOKEN",
"artifacts": {
"enabled": true,
"keepLatestPerName": 10,
"maxAgeDays": 7,
"maxDelete": 200
},
"caches": {
"enabled": true,
"keepLatestPerKey": 2,
"maxAgeDays": 14,
"maxDelete": 200
},
"runner": {
"enabled": false
}
}
```

## Direct action usage

```yaml
Expand All @@ -47,4 +90,8 @@ jobs:

- Cache and artifact deletion need `actions: write`.
- Set `apply: "false"` to preview without deleting anything.
- Prefer letting the workflow decide apply vs dry-run; omit `dryRun` from checked-in repo config unless you have a non-workflow caller that truly needs a local default.
- A dry-run can still report large cache or artifact totals with `0 eligible` deletes when current keep/latest and age rules retain everything; the Markdown summary explains that breakdown.
- Hosted-runner repos should usually keep `runner.enabled` set to `false` in config.
- The public reusable workflow entrypoint is `powerforge-github-housekeeping.yml`.
- The composite action exposes `report-path` and `summary-path` outputs for callers that want to publish the generated reports elsewhere.
55 changes: 51 additions & 4 deletions .github/actions/github-housekeeping/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,78 @@ inputs:
description: Optional token override for remote GitHub cleanup.
required: false
default: ""
runner-min-free-gb:
description: Optional runner free-disk threshold override in GiB.
required: false
default: ""
report-path:
description: Optional JSON report output path relative to the workspace.
required: false
default: ".powerforge/_reports/github-housekeeping.json"
summary-path:
description: Optional Markdown summary output path relative to the workspace.
required: false
default: ".powerforge/_reports/github-housekeeping.md"

outputs:
report-path:
description: Resolved JSON report output path.
value: ${{ steps.housekeeping.outputs.report-path }}
summary-path:
description: Resolved Markdown summary output path.
value: ${{ steps.housekeeping.outputs.summary-path }}

runs:
using: composite
steps:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
global-json-file: ${{ github.action_path }}/../../global.json
global-json-file: ${{ github.action_path }}/../../../global.json

- name: Build PowerForge CLI
shell: pwsh
run: |
$repoRoot = (Resolve-Path (Join-Path $env:GITHUB_ACTION_PATH "../..")).Path
$repoRoot = (Resolve-Path (Join-Path $env:GITHUB_ACTION_PATH "../../..")).Path
$project = Join-Path $repoRoot "PowerForge.Cli/PowerForge.Cli.csproj"
dotnet build $project -c Release
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1

- name: Run GitHub housekeeping
id: housekeeping
shell: pwsh
run: ${{ github.action_path }}/Invoke-PowerForgeHousekeeping.ps1
run: |
$ErrorActionPreference = 'Stop'
$repoRoot = (Resolve-Path (Join-Path $env:GITHUB_ACTION_PATH "../../..")).Path
$project = Join-Path $repoRoot "PowerForge.Cli/PowerForge.Cli.csproj"
$configPath = $env:INPUT_CONFIG_PATH
if ([string]::IsNullOrWhiteSpace($configPath)) {
throw "Housekeeping config path is required."
}

if (-not (Test-Path -LiteralPath $configPath)) {
throw "Housekeeping config not found: $configPath"
}

# Keep this framework in sync with the runnable TFM in PowerForge.Cli.csproj.
$dotnetArgs = @('run', '--project', $project, '-c', 'Release', '--no-build', '--framework', 'net10.0', '--', 'github', 'housekeeping', '--config', $configPath)
if (-not [string]::IsNullOrWhiteSpace($env:INPUT_RUNNER_MIN_FREE_GB)) {
$dotnetArgs += '--runner-min-free-gb'
$dotnetArgs += $env:INPUT_RUNNER_MIN_FREE_GB
}
if ($env:INPUT_APPLY -eq 'true') { $dotnetArgs += '--apply' } else { $dotnetArgs += '--dry-run' }
& dotnet @dotnetArgs
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: 1
INPUT_CONFIG_PATH: ${{ inputs['config-path'] }}
INPUT_APPLY: ${{ inputs.apply }}
POWERFORGE_GITHUB_TOKEN: ${{ inputs['github-token'] != '' && inputs['github-token'] || github.token }}
INPUT_RUNNER_MIN_FREE_GB: ${{ inputs['runner-min-free-gb'] }}
GITHUB_TOKEN: ${{ inputs['github-token'] != '' && inputs['github-token'] || github.token }}
POWERFORGE_GITHUB_HOUSEKEEPING_REPORT_PATH: ${{ inputs['report-path'] }}
POWERFORGE_GITHUB_HOUSEKEEPING_SUMMARY_PATH: ${{ inputs['summary-path'] }}
6 changes: 3 additions & 3 deletions .github/workflows/github-housekeeping.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
apply:
description: 'Apply deletions (true/false)'
required: false
default: 'true'
default: 'false'

permissions:
actions: write
Expand All @@ -20,10 +20,10 @@ concurrency:

jobs:
housekeeping:
uses: ./.github/workflows/reusable-github-housekeeping.yml
uses: ./.github/workflows/powerforge-github-housekeeping.yml
with:
config-path: ./.powerforge/github-housekeeping.json
apply: ${{ github.event_name == 'workflow_dispatch' && inputs.apply == 'true' || github.event_name != 'workflow_dispatch' }}
apply: ${{ (github.event_name == 'workflow_dispatch' && inputs.apply == 'true') || (github.event_name != 'workflow_dispatch' && vars.POWERFORGE_GITHUB_HOUSEKEEPING_APPLY == 'true') }}
powerforge-ref: ${{ github.sha }}
secrets:
github-token: ${{ secrets.GITHUB_TOKEN }}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Reusable GitHub Housekeeping
name: PowerForge GitHub Housekeeping

on:
workflow_call:
Expand All @@ -18,6 +18,21 @@ on:
required: false
default: "main"
type: string
report-path:
description: Optional JSON report path relative to the caller workspace.
required: false
default: ".powerforge/_reports/github-housekeeping.json"
type: string
summary-path:
description: Optional Markdown summary path relative to the caller workspace.
required: false
default: ".powerforge/_reports/github-housekeeping.md"
type: string
report-artifact-name:
description: Artifact name used when uploading housekeeping reports.
required: false
default: "powerforge-github-housekeeping-reports"
type: string
secrets:
github-token:
required: false
Expand All @@ -41,8 +56,21 @@ jobs:
path: .powerforge/pspublishmodule

- name: Run PowerForge housekeeping
id: housekeeping
uses: ./.powerforge/pspublishmodule/.github/actions/github-housekeeping
with:
config-path: ${{ inputs['config-path'] }}
apply: ${{ inputs.apply && 'true' || 'false' }}
github-token: ${{ secrets['github-token'] != '' && secrets['github-token'] || github.token }}
report-path: ${{ inputs['report-path'] }}
summary-path: ${{ inputs['summary-path'] }}

- name: Upload housekeeping reports
if: always()
uses: actions/upload-artifact@v4
with:
name: ${{ inputs['report-artifact-name'] }}
path: |
${{ steps.housekeeping.outputs.report-path }}
${{ steps.housekeeping.outputs.summary-path }}
if-no-files-found: ignore
Loading
Loading