Azure DevOps vs GitHub assets
A template means the same thing on both planes - a reusable, versioned step - but the two platforms package it differently, so the asset shape differs.
| Azure DevOps | GitHub Actions | |
|---|---|---|
| Template kind | a template: include (step list) | a composite action |
| Source shape | one file: templates/azd/<name>.yml | a directory: templates/gh/<name>/action.yml |
| Release asset | azd.<name>.yml (single file) | gh.<name>.zip (zipped directory) |
| Integrity anchor | file SHA256 | SHA256 of the inner action.yml |
| Vendored as | <name>.yml | <name>/action.yml |
Asset shapes and integrity anchors
That table is the pipeline case. More broadly, the integrity anchor follows the asset shape, not just the platform:
| Shape | Examples | Anchor |
|---|---|---|
| single file | azd template, gh workflow, PR template, one issue form | file SHA256 |
composite action (dir with action.yml) | gh register / install / notify | the inner action.yml SHA256 |
The anchor is always a single file SHA256 - a composite action just anchors on its inner action.yml. Repo furniture that would once have been a multi-file directory (the issue-template set) is split into one asset per file - e.g. templatesRepoIssue and templatesRepoIssueConfig - so every asset stays on the simple lock-vs-file check and a shared dest dir never causes false drift. (The earlier canonical tree-hash path has been retired.)
GitHub repoScaffold assets - workflows and PR/issue templates - vendor to a fixed dest under .github/ rather than a chosen templates dir. See Repo scaffolding (archetypes).
Why GitHub templates are directories
A GitHub composite action is not a loose file - it is a directory whose entry file must be named action.yml. A consumer references it by directory:
uses: my-org/modusops-templates/templates/gh/registerModusOpsFeeds@v1
So the per-template folder is a GitHub requirement, not a modusOps choice. To ship a directory as a single release asset it is zipped (gh.<name>.zip); Add-MOTemplate expands it back into <name>/action.yml on vendor. Everything else - the lockfile, Test-MOTemplate, pinning - works the same as for single-file Azure DevOps templates.
Composite actions, not reusable workflows
The notification and credential templates are composite actions rather than reusable workflows for a concrete reason: the registerModusOpsFeeds -> installModusOpsModules pair must share one job so the per-run credential vault survives between them. A composite action runs inline in the caller’s job; a reusable workflow runs as its own job and would lose the vault. See the credential model.
Self-contained by design
GitHub templates inline everything they need (for example the GitHub Packages folder-casing fix) so a vendored action carries no runtime module dependency. That keeps each privileged template a single, reviewable action.yml.