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
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ on:
jobs:
check:
name: Lint and validate
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Lint
run: make lint
Expand All @@ -22,13 +22,13 @@ jobs:

link-check:
name: Check links
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Check links
uses: lycheeverse/lychee-action@v2
uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
with:
args: >-
--exclude-loopback
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ lint:
validate:
bash scripts/validate-workspace.sh

validate-workflows:
bash scripts/validate-workflow-policy.sh .

lint-fix:
npx rumdl check --fix .

Expand All @@ -15,4 +18,4 @@ check-links:

ci: lint validate check-links

.PHONY: lint validate lint-fix format check-links ci
.PHONY: lint validate validate-workflows lint-fix format check-links ci
2 changes: 1 addition & 1 deletion scripts/setup-github-repo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,5 @@ echo " Org-level labels: bug, enhancement, question, duplicate, needs-repro, ne
echo " stale, good first issue, wontfix, invalid, security, needs-human-review"
echo ""
echo " Next required step"
echo " Run sdk-sync before opening implementation PRs so .github/workflows/semantic-pr.yml"
echo " Run sdk-sync before opening implementation PRs so .github/workflows/semantic-pull-request.yml"
echo " and other managed community files are present."
60 changes: 60 additions & 0 deletions scripts/validate-workflow-policy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Validates Altertable's GitHub Actions supply-chain and runtime policy.
#
# Usage: ./scripts/validate-workflow-policy.sh [repository-root]

set -euo pipefail

REPOSITORY_ROOT="${1:-.}"
REQUIRED_UBUNTU_RUNNER="ubuntu-24.04"
WORKFLOWS_DIRECTORY="$REPOSITORY_ROOT/.github/workflows"

fail() {
echo "ERROR: $*" >&2
exit 1
}

[[ -d "$WORKFLOWS_DIRECTORY" ]] || exit 0

while IFS= read -r -d '' workflow; do
while IFS= read -r runner; do
[[ "$runner" == "$REQUIRED_UBUNTU_RUNNER" ]] || fail \
"$workflow must use $REQUIRED_UBUNTU_RUNNER instead of $runner"
done < <(sed -nE 's/^[[:space:]]*runs-on:[[:space:]]*(ubuntu-(latest|[0-9]+\.[0-9]+))[[:space:]]*(#.*)?$/\1/p' "$workflow")

while IFS= read -r action_reference; do
action_reference="${action_reference%%[[:space:]]#*}"
case "$action_reference" in
./*) continue ;;
docker://*) fail "$workflow must pin container actions by digest: $action_reference" ;;
esac

[[ "$action_reference" =~ ^[^@]+@[0-9a-f]{40}$ ]] || fail \
"$workflow has an action that is not pinned to a commit SHA: $action_reference"
done < <(sed -nE \
-e 's/^[[:space:]]*-[[:space:]]*uses:[[:space:]]*([^[:space:]#]+).*/\1/p' \
-e 's/^[[:space:]]*uses:[[:space:]]*([^[:space:]#]+).*/\1/p' \
"$workflow")
done < <(find "$WORKFLOWS_DIRECTORY" -type f \( -name '*.yml' -o -name '*.yaml' \) -print0)

if grep -R -qE 'uses:[[:space:]]*actions/setup-node@' "$WORKFLOWS_DIRECTORY"; then
[[ -f "$REPOSITORY_ROOT/.node-version" ]] || fail \
"$REPOSITORY_ROOT uses actions/setup-node but has no .node-version"
grep -R -qE 'node-version-file:[[:space:]]*\.node-version([[:space:]]|$)' "$WORKFLOWS_DIRECTORY" || fail \
"$REPOSITORY_ROOT must configure actions/setup-node with node-version-file: .node-version"
if grep -R -qE '^[[:space:]]*node-version:[[:space:]]*[^[:space:]#]' "$WORKFLOWS_DIRECTORY"; then
fail "$REPOSITORY_ROOT must not hard-code node-version in workflows; use .node-version"
fi
fi

if grep -R -qE 'uses:[[:space:]]*oven-sh/setup-bun@' "$WORKFLOWS_DIRECTORY"; then
[[ -f "$REPOSITORY_ROOT/.bun-version" ]] || fail \
"$REPOSITORY_ROOT uses oven-sh/setup-bun but has no .bun-version"
grep -R -qE 'bun-version-file:[[:space:]]*\.bun-version([[:space:]]|$)' "$WORKFLOWS_DIRECTORY" || fail \
"$REPOSITORY_ROOT must configure oven-sh/setup-bun with bun-version-file: .bun-version"
if grep -R -qE '^[[:space:]]*bun-version:[[:space:]]*[^[:space:]#]' "$WORKFLOWS_DIRECTORY"; then
fail "$REPOSITORY_ROOT must not hard-code bun-version in workflows; use .bun-version"
fi
fi

echo "Workflow policy passed: $REPOSITORY_ROOT"
12 changes: 8 additions & 4 deletions scripts/validate-workspace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ require_file scripts/spec-status.sh
require_file scripts/ecosystem-status.sh
require_file scripts/subscribe-repos.sh
require_file schemas/heartbeat-state.example.json
require_file skills/sdk-sync/templates/.github/workflows/semantic-pr.yml
require_file skills/sdk-sync/templates/.github/workflows/semantic-pull-request.yml

jq empty repositories.config.json

Expand Down Expand Up @@ -81,8 +81,12 @@ if grep -R -nE "Close the issue|Close the PR|close the issue|close the PR|will b
fail "autonomous issue/PR close instruction found"
fi

if ! grep -q "action-semantic-pull-request@v5" skills/sdk-sync/templates/.github/workflows/semantic-pr.yml; then
fail "semantic PR title template does not use the required action"
fi
bash scripts/validate-workflow-policy.sh .

template_root="$(mktemp -d)"
trap 'rm -rf "$template_root"' EXIT
mkdir -p "$template_root/.github"
cp -R skills/sdk-sync/templates/.github/workflows "$template_root/.github/workflows"
bash scripts/validate-workflow-policy.sh "$template_root"

echo "Workspace validation passed"
4 changes: 2 additions & 2 deletions skills/sdk-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Use **release-please** GitHub Action for:
3. GitHub Release creation with release notes.
4. Triggering registry publish on release.

Because Altertable squash-merges pull requests and release-please derives release notes and version bumps from the merged commit subject, every repository using release-please must validate pull request titles in CI. The required gate is a dedicated GitHub Actions workflow using `amannn/action-semantic-pull-request@v5`, triggered on `pull_request_target` for `opened`, `edited`, and `synchronize`. Allowed title types are:
Because Altertable squash-merges pull requests and release-please derives release notes and version bumps from the merged commit subject, every repository using release-please must validate pull request titles in CI. The required gate is a dedicated GitHub Actions workflow using `amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50` (v6.1.1), triggered on `pull_request_target` for `opened`, `edited`, and `synchronize`. Allowed title types are:

- `feat`
- `fix`
Expand All @@ -81,7 +81,7 @@ Because Altertable squash-merges pull requests and release-please derives releas
- `build`
- `ci`

Name the workflow clearly (for example `Semantic Pull Request`), keep it separate from language-specific CI when possible, and treat missing PR-title validation as release automation drift that must be patched across affected repositories. The canonical workflow is managed by [sdk-sync](../sdk-sync/SKILL.md) at `skills/sdk-sync/templates/.github/workflows/semantic-pr.yml`.
Name the workflow clearly (for example `Semantic Pull Request`), keep it separate from language-specific CI when possible, and treat missing PR-title validation as release automation drift that must be patched across affected repositories. The canonical workflow is managed by [sdk-sync](../sdk-sync/SKILL.md) at `skills/sdk-sync/templates/.github/workflows/semantic-pull-request.yml`. It and every repository workflow must follow sdk-sync's GitHub Actions policy: Ubuntu 24.04 LTS, immutable action SHAs, and `.node-version`/`.bun-version` runtime files where those toolchains are used.

Commit message prefixes:

Expand Down
19 changes: 16 additions & 3 deletions skills/sdk-sync/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ All files in the [`templates/`](./templates/) folder are the source of truth and

Managed files include community docs, issue/PR templates, funding metadata, and release automation guardrails. Language-specific CI workflows are owned by each SDK repo, but the semantic PR title workflow is shared because release-please depends on squash-merge titles.

## GitHub Actions policy

Apply this policy to every workflow in each repository, including language-specific CI, release, security, and semantic-title workflows:

- Linux jobs use `ubuntu-24.04`, the current GitHub-hosted Ubuntu LTS image; do not use `ubuntu-latest` or an older Ubuntu image. macOS and Windows jobs retain their platform-specific pinned image where required.
- Every third-party `uses:` reference is pinned to a 40-character commit SHA with its reviewed release tag in a comment. Local reusable workflows remain relative references.
- A repository that uses `actions/setup-node` commits a root `.node-version`; every Node setup reads it through `node-version-file: .node-version` rather than hard-coding a workflow value.
- A repository that uses `oven-sh/setup-bun` commits a root `.bun-version`; every Bun setup reads it through `bun-version-file: .bun-version` rather than hard-coding a workflow value.

`.node-version` and `.bun-version` are repository-owned runtime contracts, not shared templates: preserve the version that the repository supports and make its workflows consume that file. During an audit, run `bash scripts/validate-workflow-policy.sh <repository-root>` after fetching the target repository. Resolve any intentionally dynamic matrix runner or runtime version to an explicit, pinned value before opening the sync PR.

### Template variables

Templated files contain `{variable}` placeholders. Render them with repo-specific values during sync:
Expand All @@ -41,16 +52,17 @@ Templated files contain `{variable}` placeholders. Render them with repo-specifi
1. Read `repositories.config.json` and iterate over the `sdks` array (do not include the `workspace` entry).
2. Clone or fetch all SDK repos from the `sdks` array.
3. For each managed file, compare the repo's version against the source of truth.
4. Treat a missing `.github/workflows/semantic-pr.yml` as release automation drift for every repo that uses release-please.
5. Report drift:
4. Audit every `.github/workflows/*.{yml,yaml}` against the GitHub Actions policy and record runner, action-pin, and runtime-version-file drift.
5. Treat a missing `.github/workflows/semantic-pull-request.yml` as release automation drift for every repo that uses release-please.
6. Report drift:

```text
DRIFT REPORT
============
altertable-lakehouse-ruby:
✗ SECURITY.md — missing
✗ CONTRIBUTING.md — outdated (missing Conventional Commits section)
✗ .github/workflows/semantic-pr.yml — missing
✗ .github/workflows/semantic-pull-request.yml — missing
✓ LICENSE — ok

altertable-py:
Expand All @@ -65,6 +77,7 @@ For each repo with drift:

1. Copy verbatim files from `templates/` directly.
2. Render templated files from `templates/` with repo-specific variables (see **Template variables** above).
3. For workflow-policy drift, update only the affected repository-owned workflow(s) and root runtime version file(s); do not overwrite language-specific workflow logic with a shared template.

### Phase 3: Open PRs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ on:
permissions:
pull-requests: read

concurrency:
group: semantic-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
semantic-pr:
main:
name: Validate PR title
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Validate title
uses: amannn/action-semantic-pull-request@v5
- name: Validate pull request title
uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down
Loading