A repository can have a healthy Actions workflow today and still lose the evidence needed to explain a failed deployment, a changed check, or an approval decision. GitHub announced that, starting 1 October 2026, checks, workflow runs, and statuses will follow the same retention setting that already controls Actions artifacts and logs. Before that change, those records were retained for more than 400 days even when a repository had a shorter artifact and log window.
That makes the repository retention value an operational control rather than a storage preference. A short window can be appropriate for disposable test output. It is a poor fit when the same repository needs to keep a release investigation, an audit trail, or a human approval record available for a defined period. The setting also applies to checks and statuses created by third-party applications, not only jobs written in the repository’s workflow files.
This guide builds a read-only preflight around GitHub’s retention response. The validation used Python 3.13.5 on Linux. A synthetic response with 90 days passed a 30-day policy, a seven-day response failed with a clear diagnostic, and a response using the wrong field name failed as an input error. The same check also accepted the non-sensitive retention responses from two owned repositories. No Actions setting, workflow, artifact, or hosted run was changed.
Decide what evidence must remain available
Start from an investigation or recovery requirement, not from the platform default. Count the time between a deployment and the latest point at which someone could reasonably need to inspect its workflow result, logs, checks, or status. Include delayed incident reports, release rollback windows, a change-review interval, and the time required to move material to an approved long-term system.
For example, a team may decide that ordinary pull-request logs need 14 days but release evidence needs 30 days. The repository-level Actions setting is not a per-workflow exception mechanism for checks and workflow runs after the October change. If a release repository must retain its record for 30 days, set a documented minimum for that repository and archive the small set of records that require longer retention before they expire.
Do not confuse retention with backup. A longer Actions window keeps a hosted record available; it does not create an independent copy, prove the record is complete, or preserve credentials that should have been removed from output. Sensitive values do not become safe to retain merely because a security investigation might need them. Design workflows to avoid printing them, then preserve only the redacted evidence needed for the operating procedure.
GitHub says public repositories are capped at 90 days for checks, workflow runs, and statuses, matching the existing public-repository maximum for artifacts and logs. Organization and enterprise caps can further limit a repository. A policy that demands 180 days for a public repository cannot be met by increasing a repository setting; it needs an external evidence process instead.
Read the setting without changing it
GitHub exposes the repository setting through the Actions permissions API. The response contains days, the selected retention window, and maximum_allowed_days, the upper limit inherited by the repository. Use an authenticated read with credentials that are permitted to view repository Actions settings. Do not put a broad administration token in a workflow just to run this preflight; a local administration or compliance job is usually a better boundary.
With GitHub CLI, an operator can save the response to a local file for the check:
gh api \
-H 'Accept: application/vnd.github+json' \
repos/<owner>/<repository>/actions/permissions/artifact-and-log-retention \
> actions-retention.json
The placeholder is intentional. Run the command against the repository under review and keep the response in a protected working directory. The file states a policy setting, but it can still identify a repository or reveal governance choices when combined with other data. Do not commit it as a build artifact or paste it into a public issue.
The response field matters. A checker that expects a made-up retention_days name can silently misread an otherwise valid response if it treats a missing value as zero or a pass. A missing field is an execution problem, not evidence that the repository chose a short window. The preflight below returns a separate error status for malformed input and for a response whose selected value exceeds the maximum GitHub reports.
Add a small policy check
Save this script outside application source when it is an operator check, or keep it in a controlled administration repository if several repositories share the same evidence policy. It accepts one saved API response and an explicit minimum. It has no GitHub token handling and makes no network request.
#!/usr/bin/env python3
import argparse
import json
import sys
from pathlib import Path
parser = argparse.ArgumentParser()
parser.add_argument("response", type=Path)
parser.add_argument("--minimum-days", type=int, required=True)
args = parser.parse_args()
if args.minimum_days < 1:
raise SystemExit("--minimum-days must be at least 1")
try:
response = json.loads(args.response.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as error:
print(f"ERROR: cannot read retention response: {error}", file=sys.stderr)
raise SystemExit(2)
days = response.get("days")
maximum = response.get("maximum_allowed_days")
if not isinstance(days, int) or isinstance(days, bool):
print("ERROR: response has no integer days field", file=sys.stderr)
raise SystemExit(2)
if not isinstance(maximum, int) or isinstance(maximum, bool):
print("ERROR: response has no integer maximum_allowed_days field", file=sys.stderr)
raise SystemExit(2)
if days > maximum:
print("ERROR: response days exceeds maximum_allowed_days", file=sys.stderr)
raise SystemExit(2)
if days < args.minimum_days:
print(
f"FAIL: Actions retention is {days} days; policy requires at least {args.minimum_days} days",
file=sys.stderr,
)
raise SystemExit(1)
print(f"PASS: Actions retention is {days} days and meets the {args.minimum_days}-day policy")
The exit codes separate three outcomes. Zero means the response has the expected shape and its selected value meets the local policy. One is a policy failure: the setting is valid but too short. Two means the checker cannot establish the answer because the response is unreadable, invalid JSON, missing a required integer, or internally inconsistent. Treat status two as a failed preflight rather than allowing an unavailable API response to look compliant.
Run it after obtaining the saved response:
python3 check_actions_retention.py actions-retention.json --minimum-days 30
A 30-day value is an example policy, not a GitHub recommendation. Replace it with the approved evidence window for the repository and record why the window is sufficient. If the API response reports a smaller maximum than the policy requires, escalate the cap decision to the organization or enterprise owner; do not edit the response file or lower the threshold merely to make the command pass.
Test the pass, failure, and malformed paths
A policy check is useful only if a repository review can distinguish a short retention setting from a broken collector. Build disposable JSON fixtures rather than changing an Actions setting to prove the negative path:
{"days": 90, "maximum_allowed_days": 90}
{"days": 7, "maximum_allowed_days": 90}
The first fixture returned zero with this output:
PASS: Actions retention is 90 days and meets the 30-day policy
The seven-day fixture returned one and printed:
FAIL: Actions retention is 7 days; policy requires at least 30 days
A third fixture used retention_days instead of GitHub’s days field. It returned two with ERROR: response has no integer days field. That is the important paired result: a policy failure is not the same as an unknown response schema. The check also passed against two owned repository responses that contained the documented days and maximum_allowed_days fields. Their names and selected values are intentionally omitted; the test establishes the parser boundary without publishing repository governance details.
Run this preflight before 1 October and after any repository, organization, or enterprise retention change. If the setting is shorter than the evidence requirement, preserve the specific release material that needs a longer life through the approved archive process, then change the retention policy where it is allowed. Re-run the API read and check after the change. Do not assume an archived artifact restores the hosted check or status record after GitHub removes it.
The October change makes one Actions setting cover more of a repository’s delivery history. A small read-only check turns that wider scope into an explicit, testable decision: the configured window is long enough for the evidence the repository has committed to retain, or it fails before that evidence disappears.