Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
111 changes: 111 additions & 0 deletions .github/VALIDATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: Validate community-default source changes
description: Check committed source files without requiring a PR template.
---

# Validate community-default source changes

`Organization defaults validation` checks pull requests to `main` in the
special public `MSXOrg/.github` source repository.

## Before starting

Use PowerShell 7.4+, Git, and Node.js/npm. Fetch the intended base and commit
the changes being checked; the validator rejects staged, unstaged, or untracked
differences rather than certifying working-tree corrections as the committed head.
The existing runner restores pinned Pester 6.1.0 and verifies its module GUID.
Markdown validation restores the existing markdownlint-cli2 tool at 0.24.0.

PR descriptions follow the [canonical PR-format guidance][pr-format].
PR templates are intentionally absent: this check neither requires nor copies,
generates, or compares a template scaffold. Other community defaults retain
their ordinary GitHub inheritance behavior. Consumer repositories do not install
this workflow or copy policy/contribution files to satisfy it.

The [Repository Standard][file-policy] owns the no-file policy, not PR Format.
Template absence is not record-quality proof: review the actual title and full
description against PR Format's boundary, ordered results, complete consumer
actions, and supporting evidence. Release decisions apply only to actual
release-managed routes. This file validator does not replace those record checks.

## Steps

1. Fetch the intended base with `git fetch origin main`.
2. Run the anonymous regression suites:

```powershell
pwsh -NoProfile -File .github\scripts\Invoke-PesterSuite.ps1 -RequiredVersion 6.1.0
```

3. Validate the actual committed inputs, shared sources, and changed Markdown:

```powershell
pwsh -NoProfile -File .github\scripts\Test-OrganizationDefaults.ps1 -BaseRevision origin/main
```

## Verify

The result names the actual head and merge base, existing changed files,
Markdown files actually linted, checked deletions, and verified shared
configuration sources. Empty or unsupported-only diffs fail. Intentional
template deletion is checked as absence, not a missing-file error or a claim
that deleted content was linted. Regression tests are reported separately and
cannot disguise a scan that found no applicable input.
Deleted and surviving paths come from the committed diff with case-sensitive
identity, so a case-only rename cannot hide its removed source path.
The native test runner also fails if no discovered test passes, including
skipped-only suites. Discovery counts do not substitute for executed regressions.
The job-summary verdict and exit decision use the same success condition.

Every selected Markdown file is read literally and sent on stdin to
markdownlint-cli2 with the [unchanged shared rules][markdown].
An isolated temporary configuration sets `noInlineConfig: true`, so inline
disable/configuration directives cannot turn malformed Markdown into a pass.
Repository-local ignore/configuration files and glob-like filenames cannot
skip an input. Directive examples remain valid Markdown; they are not new rules.

The [shared PowerShell][powershell], [Markdown][markdown], and [zizmor][zizmor]
snapshots and [YAML baseline][yaml] are verified against the recorded immutable
Git blobs in `validation.psd1`. They are tooling sources, not copied PR-format
templates or producer-runtime dependencies. The [Pester runner][pester] comes
from the same immutable shared tooling revision, with its local default adapted
to `.github/tests` and a no-passed-test guard. Invocation without `-Path`
discovers this repository's suite; skipped-only discovery cannot pass it.

The workflow uses `pull_request` activities `opened`, `synchronize`, `reopened`,
and `edited`, so retargeting a PR to `main` starts validation without a new head
commit. It checks out and verifies that actual head. Only `contents: read` is
granted; persisted credentials, per-language statuses, and PR-summary writes are
disabled. Other language checks use the pinned shared linter's exact
repository-relative filter. Control/backslash names, symbolic links, and
relevant inputs in its pruned directories fail explicitly.
Surviving PowerShell paths containing wildcard characters are also rejected:
the shared analyzer's path option could otherwise inspect a different file.

For deletion-only diffs there is no surviving content to lint. The report counts
the checked deletions and configuration sources, and the other-language lint
step does not run. This is not an empty input or a Markdown pass.

The exact hosted check is `Organization defaults validation`, produced by
GitHub Actions. A completed result at the actual PR head is required evidence;
local tests or a manually dispatched/skipped job cannot replace it.
Making that check required for `main` is a separately approved governance action,
not a rule or access change performed by this code.

## If it fails

| Symptom | Cause | Resolution |
| --- | --- | --- |
| No applicable changed input | Empty diff or unsupported-only files | Confirm the intended committed base/head; do not substitute regression-only evidence. |
| Markdown lint failure | Shared-rule violation, even if an inline directive disables it | Correct the content; do not suppress or skip validation. |
| Source mismatch | A shared configuration differs from its recorded source | Select and verify an immutable source refresh, then rerun the regressions. |
| Head/working-tree mismatch | Wrong checkout, incomplete history, or uncommitted content | Fetch the intended base/head and commit the intended changes. |
| Check does not hold merge | No required-check rule | Ask the governance owner to separately approve requiring the exact check/source. |

[pr-format]: https://msx.no/docs/Ways-of-Working/PR-Format/
[file-policy]: https://github.com/MSXOrg/docs/blob/bc03a5992615f65d1d5346dc48e7506e80b8b6ca/src/docs/Ways-of-Working/Repository-Standard.md#no-pr-template-files
[markdown]: https://github.com/MSXOrg/docs/blob/36da9154aa55d2052345fb2f28b812b29daf8bc9/.github/linters/.markdown-lint.yml
[powershell]: https://github.com/MSXOrg/docs/blob/36da9154aa55d2052345fb2f28b812b29daf8bc9/.github/linters/.powershell-psscriptanalyzer.psd1
[zizmor]: https://github.com/MSXOrg/docs/blob/36da9154aa55d2052345fb2f28b812b29daf8bc9/.github/linters/zizmor.yaml
[yaml]: https://github.com/super-linter/super-linter/blob/4ce20838b8ab83717e78138c5b3a1407148e0918/TEMPLATES/.yaml-lint.yml
[pester]: https://github.com/MSXOrg/docs/blob/36da9154aa55d2052345fb2f28b812b29daf8bc9/.github/scripts/Invoke-PesterSuite.ps1
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
version: 2

updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
29 changes: 29 additions & 0 deletions .github/linters/.markdown-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
###########################
## Markdown Linter rules ##
###########################

# Linter rules doc:
# - https://github.com/DavidAnson/markdownlint

###############
# Rules by id #
###############
MD004: false # Unordered list style
MD007:
indent: 2 # Unordered list indentation
MD013:
line_length: 3000 # Line length
MD025:
front_matter_title: "" # Allow a body H1 alongside the front matter title
MD026:
punctuation: ".,;:!。,;:" # List of not allowed
MD029: false # Ordered list item prefix
MD033: false # Allow inline HTML
MD036: false # Emphasis used instead of a heading
MD041: false # First line in file should be a top level heading, PULL_REQUEST_TEMPLATE.md is an exception
MD060: false # Table column style — content mixes compact and aligned tables

#################
# Rules by tags #
#################
blank_lines: false # Error on blank lines
55 changes: 55 additions & 0 deletions .github/linters/.powershell-psscriptanalyzer.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# PSScriptAnalyzer settings — the enforcement mechanism for the PowerShell coding
# standard (src/docs/Coding-Standards/PowerShell/index.md). The standard is the
# source of truth; every rule configured here is derived from it. Change a rule by
# changing the standard first, then reflect it here — never the other way around.
#
# super-linter discovers this file automatically as POWERSHELL_CONFIG_FILE
# (.powershell-psscriptanalyzer.psd1) under .github/linters.
@{
# Run the full default rule set — approved verbs, singular nouns, alias bans,
# $null-on-the-left comparisons, Invoke-Expression, unused variables, and the
# rest — then tighten the formatting rules below to match the standard.
IncludeDefaultRules = $true

# Gate on errors and warnings; both map to rules the standard requires.
Severity = @('Error', 'Warning')

Rules = @{
# One True Brace Style: opening brace on the statement line, closing brace
# on its own line with no blank line before it. NewLineAfter stays false on
# the close brace so else / elseif / catch / finally sit on the same line as
# the preceding brace ("} else {"), as the standard requires.
PSPlaceOpenBrace = @{
Enable = $true
OnSameLine = $true
NewLineAfter = $true
IgnoreOneLineBlock = $true
}
PSPlaceCloseBrace = @{
Enable = $true
NewLineAfter = $false
IgnoreOneLineBlock = $true
NoEmptyLineBefore = $true
}

# Indent with four spaces, never tabs.
PSUseConsistentIndentation = @{
Enable = $true
Kind = 'space'
IndentationSize = 4
PipelineIndentation = 'IncreaseIndentationForFirstPipeline'
}

# One space around operators and after commas, and consistent brace and
# parenthesis spacing.
PSUseConsistentWhitespace = @{
Enable = $true
CheckInnerBrace = $true
CheckOpenBrace = $true
CheckOpenParen = $true
CheckOperator = $true
CheckPipe = $true
CheckSeparator = $true
}
}
}
59 changes: 59 additions & 0 deletions .github/linters/.yaml-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
###########################################
# These are the rules used for #
# linting all the yaml files in the stack #
# NOTE: #
# You can disable line with: #
# # yamllint disable-line #
###########################################
rules:
braces:
level: warning
min-spaces-inside: 0
max-spaces-inside: 0
min-spaces-inside-empty: 1
max-spaces-inside-empty: 5
brackets:
level: warning
min-spaces-inside: 0
max-spaces-inside: 0
min-spaces-inside-empty: 1
max-spaces-inside-empty: 5
colons:
level: warning
max-spaces-before: 0
max-spaces-after: 1
commas:
level: warning
max-spaces-before: 0
min-spaces-after: 1
max-spaces-after: 1
comments: disable
comments-indentation: disable
document-end: disable
document-start:
level: warning
present: true
empty-lines:
level: warning
max: 2
max-start: 0
max-end: 0
hyphens:
level: warning
max-spaces-after: 1
indentation:
level: warning
spaces: consistent
indent-sequences: true
check-multi-line-strings: false
key-duplicates: enable
line-length:
level: warning
max: 80
allow-non-breakable-words: true
allow-non-breakable-inline-mappings: true
new-line-at-end-of-file: disable
new-lines:
type: unix
trailing-spaces: disable
4 changes: 4 additions & 0 deletions .github/linters/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
rules:
dependabot-cooldown:
disable: true
Loading
Loading