Skip to main content

In this article

Build Workflows

HVE Core uses GitHub Actions for continuous integration, quality validation, security scanning, and release automation. The workflow architecture emphasizes reusable components and parallel execution for fast feedback.

Pipeline Overview

flowchart TD
subgraph PR["Pull Request"]
direction TB
PR1[PR Opened/Updated] --> PV[pr-validation.yml]
PV --> LINT[Linting Jobs]
PV --> SEC[Security Jobs]
PV --> TEST[Test Jobs]
end

subgraph PRE["PreRelease"]
direction TB
MERGE[Merge to main] --> PREP[Pre-Release Promotion Preparation]
PREP --> PROMO[Review main to PreRelease Promotion]
PROMO -->|merge, no tag| PRE_RP[Pre-Release Pipeline PR-only mode]
PRE_RP --> PRE_REL[Review managed PreRelease PR]
PRE_REL -->|merge| PRE_DRAFT[Tag-only Draft at Managed Merge]
PRE_DRAFT --> PRE_EVIDENCE[Release-tag Packages and Canonical Evidence]
PRE_EVIDENCE --> PRE_PUBLISH[App-token Prerelease Publication]
PRE_PUBLISH --> PRE_MARKET[Pre-Release Marketplace Publish]
end

subgraph STABLE["Stable"]
direction TB
PRE_PUBLISH --> ST_PREP[Stable Release Preparation]
ST_PREP --> ST_PROMO[Review PreRelease to Stable Promotion]
ST_PROMO -->|merge, no tag| ST_RP[Stable Release Publish PR-only mode]
ST_RP --> ST_REL[Review managed Stable PR]
ST_REL -->|merge| ST_DRAFT[Tag-only Draft at Managed Merge]
ST_DRAFT --> ST_EVIDENCE[Release-tag Packages and Canonical Evidence]
ST_EVIDENCE --> ST_PUBLISH[App-token Stable Publication]
ST_PUBLISH --> ST_MARKET[Stable Marketplace Publish]
end

subgraph SCHED["Scheduled"]
direction TB
CRON[Weekly Sunday 2AM] --> WEEKLY[weekly-security-maintenance.yml]
WEEKLY --> SECCHECK[Security Checks]
end

subgraph MANUAL["Manual"]
direction TB
DISPATCH[Recovery Dispatch] --> PREP
DISPATCH --> ST_PREP
DISPATCH --> PUB[Channel Marketplace Workflow]
PUB --> VSCE[Publish to Marketplace]
end

Workflow Inventory

WorkflowTriggerPurpose
pr-validation.ymlPull request, manualPre-merge quality gate for main, develop, and both release branches
release-prerelease-prepare.ymlMerged PR to main, manualOpen the reviewed main to release/prerelease promotion PR
release-prerelease.ymlMerged PR to release/prereleasePrepare or publish the managed odd-minor PreRelease
release-stable.ymlPublished PreRelease, manualOpen the reviewed release/prerelease to release/stable promotion PR
release-stable-publish.ymlMerged PR to release/stablePrepare or publish the managed even-minor Stable release
weekly-security-maintenance.ymlSunday 2 AM UTC, manualScheduled security posture review
weekly-validation.ymlSchedule, manualWeekly full validation sweep
security-scan.ymlPush to main/developCodeQL security validation
release-marketplace-stable.ymlPublished Stable release, manualVS Code extension Marketplace publishing
release-marketplace-prerelease.ymlPublished PreRelease, manualVS Code extension pre-release publishing
copilot-setup-steps.ymlManualCoding agent environment setup
devcontainer-change-log.ymlPush to main/developLogs devcontainer infrastructure file changes to the step summary
devcontainer-lockfile-check.ymlReusableValidates devcontainer lockfile integrity and SHA-256 pinning
scorecard.ymlSchedule, pushOpenSSF Scorecard security analysis
codeql-analysis.ymlScheduleWeekly CodeQL security scan (also reusable)
dependency-review.ymlPull requestDependency vulnerability review (also reusable)
sha-staleness-check.ymlManualSHA reference freshness check (also reusable)
deploy-docs.ymlPush to main, manualDocusaurus documentation site deployment
create-stale-docs-issues.ymlScheduleAutomated stale docs issue creation from ms.date freshness
msdate-freshness-check.ymlSchedule, manualms.date freshness validation across documentation
label-sync.ymlPush to main, manualRepository label synchronization
workflow-permissions-scan.ymlSchedule, manualGitHub Actions permissions audit
weekly-gh-code-scanning.ymlMonday 3 AM UTC, manualWeekly GitHub code scanning alert retrieval and issue creation
vex-detect.ymlSchedule, release, manualDependency vulnerability scan and VEX triage issue creation

GitHub Agentic Workflow markdown files (issue-triage.md, issue-implement.md, pr-review.md, dependency-pr-review.md, doc-update-check.md, and vex-draft.md) compile to *.lock.yml workflows and are documented in Agentic Workflows.

Reusable Workflows

Individual validation workflows called by orchestration workflows:

WorkflowPurposenpm Script
markdown-lint.ymlMarkdownlint validationnpm run lint:md
spell-check.ymlcspell dictionary checknpm run spell-check
frontmatter-validation.ymlAI artifact frontmatter schemasnpm run lint:frontmatter
markdown-link-check.ymlBroken link detectionnpm run lint:md-links
link-lang-check.ymlLink language validationnpm run lint:links
yaml-lint.ymlYAML syntax validationnpm run lint:yaml
ps-script-analyzer.ymlPowerShell static analysisnpm run lint:ps
table-format.ymlMarkdown table formattingnpm run format:tables
pester-tests.ymlPowerShell unit testsnpm run test:ps
skill-validation.ymlSkill structure validationnpm run validate:skills
dependency-pinning-scan.ymlDependency pinning validationN/A (PowerShell direct)
sha-staleness-check.ymlSHA reference freshness*N/A (PowerShell direct)
codeql-analysis.ymlCodeQL security scanning*N/A (GitHub native)
dependency-review.ymlDependency vulnerability review*N/A (GitHub native)
gh-code-scanning.ymlGitHub code scanning alert retrievalN/A (PowerShell direct)
create-gh-code-scanning-issues.ymlCreate GitHub code scanning issues from alertsN/A (bash + gh CLI direct)
extension-package.ymlVS Code extension packaging (unprivileged)npm run extension:package
extension-provenance.ymlVS Code extension attestation and release uploadN/A
copyright-headers.ymlCopyright header validationnpm run validate:copyright
gitleaks-scan.ymlSecret detection scanningN/A (gitleaks direct)
plugin-package.ymlPlugin packagingN/A
plugin-validation.ymlMarketplace package metadata and closurenpm run lint:marketplace
extension-marketplace-publish.ymlExtension marketplace publishingN/A
python-lint.ymlPython linting (ruff)npm run lint:py
pytest-tests.ymlPython unit testsnpm run test:py
pip-audit.ymlPython dependency auditingN/A (pip-audit direct)
fuzz-tests.ymlPython fuzz testingN/A (pytest direct)
docusaurus-tests.ymlDocusaurus test suiteN/A (npm test)
model-validation.ymlModel reference validationnpm run lint:models
ai-artifact-validation.ymlAI artifact structure validationnpm run lint:ai-artifacts
devcontainer-lockfile-check.ymlDevcontainer lockfile integritynpm run validate:devcontainer-lockfile
action-version-consistency-scan.ymlAction version consistencynpm run lint:version-consistency

Workflows marked with * are dual-purpose: they accept workflow_call for reuse by orchestration workflows and also run independently via their own triggers.

Composite Actions

Composite actions package reusable step sequences that workflows invoke directly. Unlike reusable workflows (called via uses: at the job level with workflow_call), composite actions are referenced as steps within a job.

ActionPurposeReference
setup-ps-modulesCached PowerShell module install with retryuses: ./.github/actions/setup-ps-modules

The setup-ps-modules action caches modules keyed on scripts/security/ps-module-versions.json and retries installation with exponential backoff on PSGallery failures. Workflows that need PowerShell modules must use uses: ./.github/actions/setup-ps-modules instead of inline Install-Module steps, consistent with the convention recorded in .github/copilot-instructions.md.

PR Validation Pipeline

The pr-validation.yml workflow serves as the primary quality gate for all pull requests. It runs parallel linting, security, and testing jobs.

flowchart LR
subgraph "Linting"
ML[markdown-lint]
SC[spell-check]
TF[table-format]
YL[yaml-lint]
FV[frontmatter-validation]
LLC[link-lang-check]
MLC[markdown-link-check]
CH[copyright-headers]
end

subgraph "Analysis"
PSA[psscriptanalyzer]
PT[pester-tests]
SV[skill-validation]
PV[plugin-validation]
end

subgraph "Security"
DPC[dependency-pinning-check]
DCL[devcontainer-lockfile-check]
NA[npm-audit]
CQL[codeql]
GLS[gitleaks-scan]
end

Jobs

JobReusable WorkflowValidates
spell-checkspell-check.ymlSpelling across all files
markdown-lintmarkdown-lint.ymlMarkdown formatting rules
table-formattable-format.ymlMarkdown table structure
psscriptanalyzerps-script-analyzer.ymlPowerShell code quality
yaml-lintyaml-lint.ymlYAML syntax
pester-testspester-tests.ymlPowerShell unit tests
frontmatter-validationfrontmatter-validation.ymlAI artifact metadata
skill-validationskill-validation.ymlSkill directory structure
link-lang-checklink-lang-check.ymlLink accessibility
markdown-link-checkmarkdown-link-check.ymlBroken links
dependency-pinning-checkdependency-pinning-scan.ymlDependency pinning
devcontainer-lockfile-checkdevcontainer-lockfile-check.ymlDevcontainer lockfile integrity
npm-auditInlinenpm dependency vulnerabilities
codeqlcodeql-analysis.ymlCode security patterns
copyright-headerscopyright-headers.ymlCopyright header compliance
plugin-validationplugin-validation.ymlPlugin and package metadata
gitleaks-scangitleaks-scan.ymlSecret detection

All jobs run in parallel with no dependencies, enabling fast feedback (typically under 3 minutes).

Release Promotion and Publication

The preparation workflows each contain exactly two jobs:

WorkflowJobsSource and target
release-prerelease-prepare.ymlprepare-promotion, open-promotion-prmain to release/prerelease
release-stable.ymlprepare-promotion, open-promotion-prrelease/prerelease to release/stable

Each preparation starts from the target branch, merges the current source, restores target-owned release metadata, writes the exact release-as, and opens a reviewed PR. Promotion heads are stable per hop and are updated without force. The promotion merge creates no tag.

The release workflows accept only the exact promotion or managed head for their channel. A promotion merge selects PR-only mode. A managed PR merge selects tag-only mode and creates prerelease-v<version> for PreRelease or v<version> for Stable at that managed merge commit.

Release Version Allocation

Ordinary version allocation is branch-owned. PreRelease reads the current release/prerelease version and returns the same major, minor plus two, and patch zero. Stable reads the promoted PreRelease version and returns the promoted major, promoted minor plus one, and patch zero. Current Stable state only rejects a candidate that does not advance it. The ordinary sequence is 3.3.101 to 3.5.0 to 3.6.0.

No commit classification or automatic patch, minor, or major release class participates in ordinary allocation. Matching plugin packages use the identical channel version. A major-line transition, or a Stable patch or hotfix, requires a separate explicit manifest and release-state decision. Odd/even minor parity is repository policy aligned with VS Code Marketplace guidance and behavior, not a requirement of MAJOR.MINOR.PATCH syntax.

Release Channel Jobs

release-prerelease.yml jobs: release-please, sync-release-pr, validate-release, close-milestone, extension-package-prerelease, plugin-package-prerelease, generate-dependency-sbom, extension-provenance-prerelease, upload-plugin-packages, verify-provenance, and publish-release.

release-stable-publish.yml jobs: validate-trigger, release-please, sync-release-pr, validate-release, close-milestone, extension-package-release, extension-provenance, plugin-package-release, generate-dependency-sbom, upload-plugin-packages, vex-attest, verify-provenance, sbom-diff, append-verification-notes, and publish-release.

Both channels build the VSIX in extension-package.yml, which holds only contents: read, and attest it in extension-provenance.yml, which holds the signing scopes and never installs dependencies. No job does both.

Both release workflows verify event, merge, release-please, and release-tag SHA equality plus target-branch ancestry. Extension and plugin packages use the validated release SHA bound to the immutable channel tag. Every release catalog entry uses prerelease-v<version> or v<version> for its channel. The workflows attach and attest plugin-release-evidence.json, derived from declared canonical tracked sources, alongside signed plugin ZIPs, SBOM, Sigstore, and in-toto assets.

Both channels publish their draft with a release GitHub App token. The resulting published event triggers the matching Marketplace workflow. Main is not part of either release completion graph. It remains a ref-less development-tip channel sourced from canonical .github content and is not updated by release completion. Release branches, immutable tags, and published releases own release state and history.

The ref-less microsoft/hve-core registration sources canonical content from .github through the ref-less main catalog. An explicit marketplace refresh and plugin update are required for that catalog, which has no release gate, SBOM, or attestation. PreRelease and Stable retain reviewed, release-gated, SBOM-covered, and attested immutable delivery through moving branch registrations and exact tags.

Because snapshot publication has stopped, tags and catalogs remain immutable and supported only as historical records. They are not current release or registration namespaces.

Security Workflows

Weekly Security Maintenance

The weekly-security-maintenance.yml workflow runs every Sunday at 2AM UTC, providing scheduled security posture review.

JobPurpose
validate-pinningVerify dependency pinning compliance
check-stalenessDetect outdated SHA references
codeql-analysisFull CodeQL security scan
summaryAggregate security status report

Security Validation Tools

ToolScriptChecks
Dependency PinningTest-DependencyPinning.ps1Actions use SHA refs; npm uses exact versions
SHA StalenessTest-SHAStaleness.ps1SHAs reference recent commits
audit-ciaudit-ci --config audit-ci.jsonKnown vulnerabilities in dependencies, using the allowlist in audit-ci.json
CodeQLGitHub nativeCode patterns indicating security issues
GitleaksgitleaksSecret detection in repository history
Dependency ReviewGitHub nativeDependency vulnerability analysis

Extension Publishing

Both Marketplace entry workflows publish release assets selected by a validated exact channel tag.

flowchart LR
PRE[Validate prerelease-v tag] --> PRE_MATRIX[Resolve PreRelease package matrix]
PRE_MATRIX --> GENERIC[Generic Marketplace publisher]
STABLE[Validate v tag and discover Stable matrix] --> GENERIC
GENERIC --> ASSET[Download VSIX release asset]
ASSET --> VERIFY[Verify lane-specific attestation]
VERIFY --> OIDC[Publish through Azure OIDC and vsce]

Channel Tags and Attestation Signers

ChannelExact release tagAttestation signer
PreReleaseprerelease-v<version>extension-provenance.yml
Stablev<version>extension-provenance.yml

Both callers pass the exact tag to the generic publisher, which resolves the signer to the one constant both channels sign from. It downloads the matching VSIX release asset, verifies the attestation, and then publishes through Azure OIDC and vsce.

Marketplace Build

Get-MarketplacePackageMatrix.ps1 emits a sorted, nonempty matrix from active catalog entries. Stable and PreRelease must resolve the same package-name set and the same active component and maturity projection for every package. The matrix, not a literal package count or a package-specific workflow branch, controls packaging and publication.

hve-core retains the unsuffixed HVE Core extension identity. Every other active catalog entry receives a deterministic package-specific extension identity and plugin root.

Each package remains self-contained; the release model does not use package dependencies or aggregate metadata. Catalog membership uses .github-root canonical paths, while generated ZIP and VSIX paths remain host-specific packaging details.

Lifecycle inclusion rules:

Lifecycle LevelBuild Inclusion
DeprecatedExcluded from both channels
RemovedExcluded from both channels
ExperimentalIncluded in both Stable and PreRelease channels
PreviewIncluded in both Stable and PreRelease channels
StableIncluded in both Stable and PreRelease channels

Lifecycle labels are disclosure and governance metadata. Channel selection does not filter active components.

Version Channels

ChannelVersion PatternMarketplace
StableEven minor (1.2.0)Main listing
Pre-releaseOdd minor (1.3.0)Pre-release flag

Hosted Marketplace selection and installed-client switching remain operator observations, not results of local workflow or documentation validation.

npm Script Mapping

Workflows invoke validation through npm scripts defined in package.json:

npm ScriptCommandUsed By
lint:mdmarkdownlint-cli2markdown-lint.yml
lint:md:fixmarkdownlint-cli2 --fixLocal
spell-checkcspellspell-check.yml
spell-check:fixcspell --show-suggestionsLocal
lint:frontmatterValidate-MarkdownFrontmatter.ps1frontmatter-validation.yml
lint:md-linksMarkdown-Link-Check.ps1markdown-link-check.yml
lint:linksInvoke-LinkLanguageCheck.ps1link-lang-check.yml
lint:yamlInvoke-YamlLint.ps1yaml-lint.yml
lint:psInvoke-PSScriptAnalyzer.ps1ps-script-analyzer.yml
lint:marketplaceValidate-Marketplace.ps1plugin-validation.yml
lint:version-consistencyTest-ActionVersionConsistency.ps1Local
validate:localLocal-safe repository validation aggregateLocal-safe default
validate:docsDocusaurus lint, label registry, typecheck, and component testsLocal-safe docs default
ci:docs:test:e2eDelegates to the Docusaurus Playwright E2E suiteCI-owned browser lane
ci:docs:setup:e2eProvisions Chrome for the Docusaurus browser laneCI-owned browser setup
format:tablesmarkdown-table-formattertable-format.yml
test:psInvoke-PesterTests.ps1pester-tests.yml
validate:skillsValidate-SkillStructure.ps1skill-validation.yml
validate:copyrightTest-CopyrightHeaders.ps1copyright-headers.yml
extension:preparepwsh ./scripts/extension/Prepare-Extension.ps1 && npm run extension:postprocessextension-package.yml
extension:prepare:prereleasepwsh ./scripts/extension/Prepare-Extension.ps1 -Channel PreRelease && npm run extension:postprocessextension-package.yml
extension:postprocessmarkdownlint-cli2 + markdown-table-formatter (extension/**/*.md)extension-package.yml
extension:packagePackage-Extension.ps1extension-package.yml
extension:package:prereleasePackage-Extension.ps1 -PreReleaseextension-package.yml
plugin:generateGenerate-Plugins.ps1 + post-processplugin-package.yml
plugin:validateMarketplace package metadata and closure validationplugin-validation.yml
lint:pyruff checkpython-lint.yml
lint:modelsValidate-ModelReferences.ps1model-validation.yml
lint:ai-artifactsValidate-PlannerArtifacts.ps1 -FailOnMissingai-artifact-validation.yml
lint:permissionsTest-WorkflowPermissions.ps1workflow-permissions-scan.yml
lint:ps-module-pinsTest-PSModulePins.ps1Local
lint:dependency-pinningTest-DependencyPinning.ps1dependency-pinning-scan.yml
audit:npmaudit-ci --config audit-ci.jsonpr-validation.yml
test:pyuv run pytestpytest-tests.yml
ci:eval:lint:vallyBuild-AgentBehaviorSpec.ps1 -WhatIf && vally lint --eval-spec evals/CI-owned static lane
ci:eval:lint:schemaTest-EvalSpec.ps1CI-owned static lane
ci:eval:lint:textTest-EvalSpecText.ps1CI-owned static lane
ci:eval:lint:safetyTest-VallyTestSafety.ps1CI-owned static lane
ci:eval:lint:skillsvally lint .github/skills/CI-owned static lane
ci:eval:runRuns all eval suitesCI-owned model-backed lane
ci:eval:run:skillsvally eval --suite skill-qualityCI-owned model-backed lane
ci:eval:run:agentsvally eval --suite agent-behaviorCI-owned model-backed lane
ci:eval:run:scriptsvally eval --suite script-validationCI-owned model-backed lane
ci:eval:comparevally compareCI-owned comparison lane
ci:eval:presenceTest-StimulusPresence.ps1 (changed-artifact eval-spec coverage gate)CI-owned manifest lane
ci:eval:executeInvoke-VallyEvals.ps1 (run evals for changed artifacts)CI-owned model-backed lane
ci:eval:moderateInvoke-ContentModeration.ps1CI-owned moderation lane
ci:eval:moderate:corpusInvoke-CorpusModeration.ps1CI-owned moderation lane
ci:eval:moderate:artifactsInvoke-ArtifactModeration.ps1CI-owned moderation lane
ci:eval:moderate:testRuns Invoke-ContentModeration.Tests.ps1CI-owned test lane
ci:eval:equivalenceInvoke-BaselineEquivalence.ps1CI-owned model-backed lane
ci:eval:dashboardNew-EquivalenceDashboard.ps1CI-owned noninteractive report lane
ci:eval:run:equivalenceRuns baseline and customized equivalence specsCI-owned model-backed lane
ci:eval:behavior-promptsvally eval --eval-spec evals/behavior-conformance/prompts.eval.yamlCI-owned model-backed lane
ci:eval:behavior-instructionsvally eval --eval-spec evals/behavior-conformance/instructions.eval.yamlCI-owned model-backed lane
ci:eval:behavior-skillsvally eval --eval-spec evals/behavior-conformance/skill-behavior.eval.yamlCI-owned model-backed lane
ci:eval:agentInvoke-AgentMatrix.ps1 (agent behavior matrix)CI-owned model-backed lane
ci:eval:agent:matrixInvoke-AgentMatrix.ps1 -All -Tier nightlyCI-owned model-backed lane
ci:eval:agent:matrix:dryrunInvoke-AgentMatrix.ps1 -All -Tier nightly -WhatIfCI-owned dry-run lane
ci:eval:agent:changedInvoke-AgentMatrix.ps1 for changed agents (PR tier)CI-owned model-backed lane
ci:eval:agent:dashboardNew-AgentMatrixDashboard.ps1CI-owned noninteractive report lane
ci:eval:agent:dashboard:openNew-AgentMatrixDashboard.ps1 -OpenCI-owned interactive lane
ci:eval:agent:reportRuns ci:eval:agent:matrix then ci:eval:agent:dashboardCI-owned noninteractive report lane
ci:eval:agent:report:dryrunRuns ci:eval:agent:matrix:dryrun then ci:eval:agent:dashboardCI-owned noninteractive dry-run report lane

🤖 Crafted with precision by ✨Copilot following brilliant human instruction, then carefully refined by our team of discerning human reviewers.