From c1e9e16c44152008093d1dac683a47ae2647d906 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jan 2026 18:46:36 +1300 Subject: [PATCH 1/7] Add bindings validation and PR title validation --- .github/workflows/ci-tests.yml | 21 +++++++-- .github/workflows/conventional-commit.yml | 57 +++++++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/conventional-commit.yml diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index a2eaa53..dd011e9 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -8,15 +8,17 @@ on: workflow_dispatch: {} jobs: - tests_and_lint: - name: Tests & Lint + setup: + name: Setup Environment runs-on: ubuntu-latest - + outputs: + go-home: ${{ steps.setup-go.outputs.go-home }} steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Go + id: setup-go uses: actions/setup-go@v4 with: go-version: '1.24.2' @@ -24,6 +26,11 @@ jobs: - name: Install tools run: scripts/tools/install_tools.sh + tests: + name: Tests & Lint + needs: setup + runs-on: ubuntu-latest + steps: - name: Go Build & Vet run: | go build ./... @@ -37,3 +44,11 @@ jobs: - name: Coverage (threshold) run: scripts/testing/run_coverage.sh + + bindings: + name: Validate Bindings + needs: setup + runs-on: ubuntu-latest + steps: + - name: Check Bindings Exports + run: scripts/bindings/check_bindings_exports.sh diff --git a/.github/workflows/conventional-commit.yml b/.github/workflows/conventional-commit.yml new file mode 100644 index 0000000..2f1c198 --- /dev/null +++ b/.github/workflows/conventional-commit.yml @@ -0,0 +1,57 @@ +name: Conventional Commit Check + +on: + pull_request: + types: [opened, edited] + +jobs: + validate_pr_title: + name: Validate PR Title + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate PR title and detect breaking changes + id: check_title + run: | + #!/bin/bash + set -euo pipefail + + # Allowed prefixes + PREFIXES=("feat" "fix" "docs" "style" "refactor" "test" "chore") + + # Get PR title and number + PR_TITLE=$(jq -r .pull_request.title "$GITHUB_EVENT_PATH") + PR_NUMBER=$(jq -r .pull_request.number "$GITHUB_EVENT_PATH") + + echo "PR title: $PR_TITLE" + + # Regex for conventional commit: prefix[optional scope][optional !]: description + PREFIX_PATTERN=$(IFS="|"; echo "${PREFIXES[*]}") + REGEX="^(${PREFIX_PATTERN})(\\([a-zA-Z0-9_-]+\\))?(!)?: .+" + + if [[ "$PR_TITLE" =~ $REGEX ]]; then + if [[ "$PR_TITLE" == *"!"* ]]; then + echo "Breaking change detected!" + echo "breaking_change=true" >> $GITHUB_OUTPUT + else + echo "breaking_change=false" >> $GITHUB_OUTPUT + fi + else + echo "PR title does NOT follow Conventional Commits." + echo "Expected format: [optional scope][!]: description" + echo "Allowed types: ${PREFIXES[*]}" + echo "Examples:" + echo " feat: add login endpoint" + echo " fix(auth)!: fix critical bug" + exit 1 + fi + + - name: Add breaking-change label if needed + if: steps.check_title.outputs.breaking_change == 'true' + uses: actions-ecosystem/action-add-labels@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: breaking-change From 94c06a4ca788cf4e4775ac0cf9b05f140f324ad9 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jan 2026 18:54:56 +1300 Subject: [PATCH 2/7] Fix CI workflows --- .github/workflows/ci-tests.yml | 6 ++++++ .github/workflows/conventional-commit.yml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index dd011e9..596edac 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -31,6 +31,9 @@ jobs: needs: setup runs-on: ubuntu-latest steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Go Build & Vet run: | go build ./... @@ -50,5 +53,8 @@ jobs: needs: setup runs-on: ubuntu-latest steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Check Bindings Exports run: scripts/bindings/check_bindings_exports.sh diff --git a/.github/workflows/conventional-commit.yml b/.github/workflows/conventional-commit.yml index 2f1c198..bf9175e 100644 --- a/.github/workflows/conventional-commit.yml +++ b/.github/workflows/conventional-commit.yml @@ -1,7 +1,7 @@ name: Conventional Commit Check on: - pull_request: + pull_request_target: types: [opened, edited] jobs: From bed4665a5558ebeee1916e522bfb83a0f1a34d7d Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jan 2026 19:02:43 +1300 Subject: [PATCH 3/7] Attempt to fix CI --- .github/workflows/ci-tests.yml | 23 +++++++++------------- scripts/bindings/check_bindings_exports.sh | 23 +++++++++++----------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 596edac..6a31303 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -8,11 +8,9 @@ on: workflow_dispatch: {} jobs: - setup: - name: Setup Environment + tests: + name: Tests & Lint runs-on: ubuntu-latest - outputs: - go-home: ${{ steps.setup-go.outputs.go-home }} steps: - name: Checkout uses: actions/checkout@v4 @@ -26,14 +24,6 @@ jobs: - name: Install tools run: scripts/tools/install_tools.sh - tests: - name: Tests & Lint - needs: setup - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Go Build & Vet run: | go build ./... @@ -50,11 +40,16 @@ jobs: bindings: name: Validate Bindings - needs: setup runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - + + - name: Set up Go + id: setup-go + uses: actions/setup-go@v4 + with: + go-version: '1.24.2' + - name: Check Bindings Exports run: scripts/bindings/check_bindings_exports.sh diff --git a/scripts/bindings/check_bindings_exports.sh b/scripts/bindings/check_bindings_exports.sh index ca529be..7c3606e 100755 --- a/scripts/bindings/check_bindings_exports.sh +++ b/scripts/bindings/check_bindings_exports.sh @@ -1,12 +1,13 @@ #!/usr/bin/env bash set -euo pipefail -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +# Move to the repository root reliably +ROOT_DIR="$(git rev-parse --show-toplevel)" cd "$ROOT_DIR" +# Directories/files to exclude from scanning for exported functions EXCLUDE_DIRS=( ".github" - "bindings" "cmd" "examples" "internal" @@ -16,7 +17,7 @@ EXCLUDE_FILES=( "*_test.go" ) -# Build rg/glob exclude arguments +# Build ripgrep/glob exclude arguments RG_EXCLUDES=() for d in "${EXCLUDE_DIRS[@]}"; do RG_EXCLUDES+=(--glob "!$d/**") @@ -25,11 +26,9 @@ for f in "${EXCLUDE_FILES[@]}"; do RG_EXCLUDES+=(--glob "!$f") done -# Find exported top-level functions with file context +# Find exported top-level functions if command -v rg >/dev/null 2>&1; then - exported=$(rg --no-heading --line-number \ - '^func\s+[A-Z][A-Za-z0-9_]*' \ - "${RG_EXCLUDES[@]}" . | + exported=$(rg --no-heading --line-number '^func\s+[A-Z][A-Za-z0-9_]*' "${RG_EXCLUDES[@]}" . | sed -E 's/^(.+):[0-9]+:func\s+([A-Z][A-Za-z0-9_]*).*/\1:\2/' | sort -u) else @@ -41,9 +40,7 @@ else GREP_EXCLUDES+=(--exclude="$f") done - exported=$(grep -R --line-number -h \ - -E "^func\s+[A-Z][A-Za-z0-9_]*" \ - "${GREP_EXCLUDES[@]}" . | + exported=$(grep -R --line-number -h -E "^func\s+[A-Z][A-Za-z0-9_]*" "${GREP_EXCLUDES[@]}" . | sed -E 's/^(.+):[0-9]+:func\s+([A-Z][A-Za-z0-9_]*).*/\1:\2/' | sort -u) fi @@ -53,11 +50,15 @@ if [ -z "$exported" ]; then exit 0 fi +# Absolute paths to bindings files +BINDINGS_GO="$ROOT_DIR/bindings/c/gspl.go" +BINDINGS_H="$ROOT_DIR/bindings/c/gspl.h" + declare -A missing_by_file missing_count=0 while IFS=: read -r file fn; do - if ! rg -q "\b$fn\b" bindings/c/gspl.go bindings/c/gspl.h 2>/dev/null; then + if ! rg -q "\b$fn\b" "$BINDINGS_GO" "$BINDINGS_H" 2>/dev/null; then missing_by_file["$file"]+=$'\n'" - $fn" missing_count=$((missing_count + 1)) fi From c167222d139a032704afa997760985432e916832 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jan 2026 19:05:11 +1300 Subject: [PATCH 4/7] Add logs to script --- scripts/bindings/check_bindings_exports.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/bindings/check_bindings_exports.sh b/scripts/bindings/check_bindings_exports.sh index 7c3606e..ccd8fc3 100755 --- a/scripts/bindings/check_bindings_exports.sh +++ b/scripts/bindings/check_bindings_exports.sh @@ -4,6 +4,8 @@ set -euo pipefail # Move to the repository root reliably ROOT_DIR="$(git rev-parse --show-toplevel)" cd "$ROOT_DIR" +echo "$ROOT_DIR" +ls -la # Directories/files to exclude from scanning for exported functions EXCLUDE_DIRS=( From 315fc38f8d7e42832b548636328e105db322c374 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jan 2026 19:20:48 +1300 Subject: [PATCH 5/7] Fix scripts --- .github/workflows/conventional-commit.yml | 24 ++++------------- scripts/bindings/check_bindings_exports.sh | 30 +++++++++------------- 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/.github/workflows/conventional-commit.yml b/.github/workflows/conventional-commit.yml index bf9175e..5411ffb 100644 --- a/.github/workflows/conventional-commit.yml +++ b/.github/workflows/conventional-commit.yml @@ -1,7 +1,7 @@ name: Conventional Commit Check on: - pull_request_target: + pull_request: types: [opened, edited] jobs: @@ -13,7 +13,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Validate PR title and detect breaking changes + - name: Validate PR title id: check_title run: | #!/bin/bash @@ -22,10 +22,8 @@ jobs: # Allowed prefixes PREFIXES=("feat" "fix" "docs" "style" "refactor" "test" "chore") - # Get PR title and number + # Get PR title PR_TITLE=$(jq -r .pull_request.title "$GITHUB_EVENT_PATH") - PR_NUMBER=$(jq -r .pull_request.number "$GITHUB_EVENT_PATH") - echo "PR title: $PR_TITLE" # Regex for conventional commit: prefix[optional scope][optional !]: description @@ -33,14 +31,9 @@ jobs: REGEX="^(${PREFIX_PATTERN})(\\([a-zA-Z0-9_-]+\\))?(!)?: .+" if [[ "$PR_TITLE" =~ $REGEX ]]; then - if [[ "$PR_TITLE" == *"!"* ]]; then - echo "Breaking change detected!" - echo "breaking_change=true" >> $GITHUB_OUTPUT - else - echo "breaking_change=false" >> $GITHUB_OUTPUT - fi + echo "PR title follows Conventional Commits." else - echo "PR title does NOT follow Conventional Commits." + echo "❌ PR title does NOT follow Conventional Commits." echo "Expected format: [optional scope][!]: description" echo "Allowed types: ${PREFIXES[*]}" echo "Examples:" @@ -48,10 +41,3 @@ jobs: echo " fix(auth)!: fix critical bug" exit 1 fi - - - name: Add breaking-change label if needed - if: steps.check_title.outputs.breaking_change == 'true' - uses: actions-ecosystem/action-add-labels@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - labels: breaking-change diff --git a/scripts/bindings/check_bindings_exports.sh b/scripts/bindings/check_bindings_exports.sh index ccd8fc3..7d12099 100755 --- a/scripts/bindings/check_bindings_exports.sh +++ b/scripts/bindings/check_bindings_exports.sh @@ -4,8 +4,6 @@ set -euo pipefail # Move to the repository root reliably ROOT_DIR="$(git rev-parse --show-toplevel)" cd "$ROOT_DIR" -echo "$ROOT_DIR" -ls -la # Directories/files to exclude from scanning for exported functions EXCLUDE_DIRS=( @@ -29,23 +27,19 @@ for f in "${EXCLUDE_FILES[@]}"; do done # Find exported top-level functions -if command -v rg >/dev/null 2>&1; then - exported=$(rg --no-heading --line-number '^func\s+[A-Z][A-Za-z0-9_]*' "${RG_EXCLUDES[@]}" . | - sed -E 's/^(.+):[0-9]+:func\s+([A-Z][A-Za-z0-9_]*).*/\1:\2/' | - sort -u) -else - GREP_EXCLUDES=() - for d in "${EXCLUDE_DIRS[@]}"; do - GREP_EXCLUDES+=(--exclude-dir="$d") - done - for f in "${EXCLUDE_FILES[@]}"; do - GREP_EXCLUDES+=(--exclude="$f") - done +GREP_EXCLUDES=() +for d in "${EXCLUDE_DIRS[@]}"; do + GREP_EXCLUDES+=(--exclude-dir="$d") +done +for f in "${EXCLUDE_FILES[@]}"; do + GREP_EXCLUDES+=(--exclude="$f") +done - exported=$(grep -R --line-number -h -E "^func\s+[A-Z][A-Za-z0-9_]*" "${GREP_EXCLUDES[@]}" . | - sed -E 's/^(.+):[0-9]+:func\s+([A-Z][A-Za-z0-9_]*).*/\1:\2/' | - sort -u) -fi +exported=$(grep -R -n "${GREP_EXCLUDES[@]}" -E '^func[[:space:]]+[A-Z][A-Za-z0-9_]*' . | + while IFS=: read -r file _ rest; do + fn=$(printf '%s' "$rest" | sed -E 's/^func[[:space:]]+([A-Z][A-Za-z0-9_]*).*/\1/') + printf '%s:%s\n' "$file" "$fn" + done | sort -u) if [ -z "$exported" ]; then echo "No exported functions found." From f442ab74a9dd988276eaae62e4451113de81507b Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jan 2026 19:41:45 +1300 Subject: [PATCH 6/7] Remove ripgrep reference --- scripts/bindings/check_bindings_exports.sh | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/scripts/bindings/check_bindings_exports.sh b/scripts/bindings/check_bindings_exports.sh index 7d12099..a84ada1 100755 --- a/scripts/bindings/check_bindings_exports.sh +++ b/scripts/bindings/check_bindings_exports.sh @@ -17,15 +17,6 @@ EXCLUDE_FILES=( "*_test.go" ) -# Build ripgrep/glob exclude arguments -RG_EXCLUDES=() -for d in "${EXCLUDE_DIRS[@]}"; do - RG_EXCLUDES+=(--glob "!$d/**") -done -for f in "${EXCLUDE_FILES[@]}"; do - RG_EXCLUDES+=(--glob "!$f") -done - # Find exported top-level functions GREP_EXCLUDES=() for d in "${EXCLUDE_DIRS[@]}"; do @@ -54,7 +45,7 @@ declare -A missing_by_file missing_count=0 while IFS=: read -r file fn; do - if ! rg -q "\b$fn\b" "$BINDINGS_GO" "$BINDINGS_H" 2>/dev/null; then + if ! grep -q -w -- "$fn" "$BINDINGS_GO" "$BINDINGS_H" 2>/dev/null; then missing_by_file["$file"]+=$'\n'" - $fn" missing_count=$((missing_count + 1)) fi From 26087c73bdc3570948a2319e4cd8d15be73e431d Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 22 Jan 2026 19:46:15 +1300 Subject: [PATCH 7/7] Add synchronize to conventional commit validator --- .github/workflows/conventional-commit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/conventional-commit.yml b/.github/workflows/conventional-commit.yml index 5411ffb..da7b4bb 100644 --- a/.github/workflows/conventional-commit.yml +++ b/.github/workflows/conventional-commit.yml @@ -2,7 +2,7 @@ name: Conventional Commit Check on: pull_request: - types: [opened, edited] + types: [opened, edited, synchronize] jobs: validate_pr_title: