@codyswann/lisa 2.196.0 → 2.197.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa-agy/plugin.json +1 -1
  5. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  8. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  9. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  14. package/plugins/lisa-expo-agy/plugin.json +1 -1
  15. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  20. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  25. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  30. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  35. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-rails-agy/plugin.json +1 -1
  40. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  45. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  50. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  52. package/scripts/lisa-github-repo-setup.sh +11 -1
  53. package/scripts/lisa-github-rulesets.sh +123 -17
  54. package/scripts/setup-deploy-key.sh +5 -4
  55. package/cdk/github-rulesets/cdk-validation.json +0 -43
package/package.json CHANGED
@@ -94,7 +94,7 @@
94
94
  "ws": ">=8.20.1"
95
95
  },
96
96
  "name": "@codyswann/lisa",
97
- "version": "2.196.0",
97
+ "version": "2.197.0",
98
98
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
99
99
  "main": "dist/index.js",
100
100
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.196.0",
3
+ "version": "2.197.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -56,7 +56,17 @@ echo "==> Step 3/3: deploy key"
56
56
  if [[ "$DRY_RUN" == "true" ]]; then
57
57
  echo "[DRY RUN] Would ensure a write-access deploy key + DEPLOY_KEY secret exist"
58
58
  else
59
- (cd "$PROJECT_PATH" && bash "$SCRIPT_DIR/setup-deploy-key.sh" --yes)
59
+ deploy_output=$(cd "$PROJECT_PATH" && bash "$SCRIPT_DIR/setup-deploy-key.sh" --yes 2>&1)
60
+ deploy_rc=$?
61
+ echo "$deploy_output"
62
+ if [[ $deploy_rc -ne 0 ]]; then
63
+ if echo "$deploy_output" | grep -qi "deploy keys are disabled"; then
64
+ # Org policy, not a repo problem — settings/rulesets still applied.
65
+ echo "⚠ Deploy keys are disabled by organization policy — skipped. Release workflows needing DEPLOY_KEY will not work until an org admin re-enables deploy keys."
66
+ else
67
+ exit $deploy_rc
68
+ fi
69
+ fi
60
70
  fi
61
71
 
62
72
  echo ""
@@ -309,6 +309,48 @@ strip_actions_checks_if_no_workflows() {
309
309
  else . end'
310
310
  }
311
311
 
312
+ # Per-repo opt-out: .lisa.config.json can list required-check contexts that
313
+ # must never be required on this repository, e.g. wikis that should not gate
314
+ # on CodeRabbit:
315
+ # { "github": { "rulesets": { "dropRequiredChecks": ["CodeRabbit"] } } }
316
+ strip_config_dropped_checks() {
317
+ local json="$1"
318
+ local project_path="$2"
319
+ local config="$project_path/.lisa.config.json"
320
+
321
+ if [[ ! -f "$config" ]]; then
322
+ echo "$json"
323
+ return 0
324
+ fi
325
+
326
+ local dropped
327
+ if ! dropped=$(jq -c '.github.rulesets.dropRequiredChecks // []' "$config" 2>/dev/null); then
328
+ log_warning ".lisa.config.json could not be parsed — ignoring github.rulesets overrides" >&2
329
+ dropped="[]"
330
+ fi
331
+
332
+ if [[ "$dropped" == "[]" ]]; then
333
+ echo "$json"
334
+ return 0
335
+ fi
336
+
337
+ echo "$json" | jq --argjson dropped "$dropped" '
338
+ if .rules then
339
+ .rules |= (
340
+ map(
341
+ if .type == "required_status_checks" then
342
+ .parameters.required_status_checks |=
343
+ map(select(.context as $c | ($dropped | index($c)) | not))
344
+ else . end
345
+ )
346
+ | map(select(
347
+ .type != "required_status_checks"
348
+ or (.parameters.required_status_checks | length) > 0
349
+ ))
350
+ )
351
+ else . end'
352
+ }
353
+
312
354
  apply_ruleset() {
313
355
  local repo="$1"
314
356
  local template_file="$2"
@@ -324,6 +366,7 @@ apply_ruleset() {
324
366
  local clean_template
325
367
  clean_template=$(strip_readonly_fields "$template_content")
326
368
  clean_template=$(strip_actions_checks_if_no_workflows "$clean_template" "$project_path")
369
+ clean_template=$(strip_config_dropped_checks "$clean_template" "$project_path")
327
370
 
328
371
  # A template whose rules were entirely stripped has nothing to enforce here.
329
372
  if [[ $(echo "$clean_template" | jq '(.rules // [1]) | length') -eq 0 ]]; then
@@ -344,32 +387,95 @@ apply_ruleset() {
344
387
  return 0
345
388
  fi
346
389
 
347
- # Create temp file for the request body
348
- local temp_file
349
- temp_file=$(mktemp)
350
- echo "$clean_template" > "$temp_file"
351
-
352
390
  if [[ -n "$existing_id" ]]; then
353
391
  log_info "Updating ruleset '$ruleset_name' (id: $existing_id)..."
354
- if gh api -X PUT "repos/$repo/rulesets/$existing_id" --input "$temp_file" > /dev/null; then
355
- log_success "Updated ruleset '$ruleset_name'"
356
- else
357
- log_error "Failed to update ruleset '$ruleset_name'"
358
- rm -f "$temp_file"
359
- return 1
360
- fi
361
392
  else
362
393
  log_info "Creating ruleset '$ruleset_name'..."
363
- if gh api -X POST "repos/$repo/rulesets" --input "$temp_file" > /dev/null; then
364
- log_success "Created ruleset '$ruleset_name'"
394
+ fi
395
+
396
+ if apply_with_integration_fallback "$repo" "$ruleset_name" "$clean_template" "$existing_id"; then
397
+ return 0
398
+ fi
399
+ log_error "Failed to apply ruleset '$ruleset_name'"
400
+ return 1
401
+ }
402
+
403
+ # Send the ruleset to GitHub. App-based required checks (CodeRabbit,
404
+ # GitGuardian, ...) are rejected with "Invalid integration ids" on repos
405
+ # where that app is not installed — and no user-token API can list per-repo
406
+ # installations up front. So on that specific error, retry with app-based
407
+ # checks progressively removed: first each single app id, then all of them,
408
+ # keeping as many checks as the repo actually supports.
409
+ apply_with_integration_fallback() {
410
+ local repo="$1"
411
+ local ruleset_name="$2"
412
+ local payload="$3"
413
+ local existing_id="$4"
414
+
415
+ local temp_file error_output
416
+ temp_file=$(mktemp)
417
+
418
+ # Capture stdout AND stderr — gh prints the API error body (which carries
419
+ # the "Invalid integration ids" detail) on stdout, not stderr.
420
+ send_ruleset() {
421
+ echo "$1" > "$temp_file"
422
+ if [[ -n "$existing_id" ]]; then
423
+ error_output=$(gh api -X PUT "repos/$repo/rulesets/$existing_id" --input "$temp_file" 2>&1)
365
424
  else
366
- log_error "Failed to create ruleset '$ruleset_name'"
367
- rm -f "$temp_file"
368
- return 1
425
+ error_output=$(gh api -X POST "repos/$repo/rulesets" --input "$temp_file" 2>&1)
369
426
  fi
427
+ }
428
+
429
+ if send_ruleset "$payload"; then
430
+ log_success "Applied ruleset '$ruleset_name'"
431
+ rm -f "$temp_file"
432
+ return 0
370
433
  fi
371
434
 
435
+ if ! echo "$error_output" | grep -qi "invalid integration ids"; then
436
+ log_error "$error_output"
437
+ rm -f "$temp_file"
438
+ return 1
439
+ fi
440
+
441
+ local app_ids
442
+ app_ids=$(echo "$payload" | jq --argjson actions "$ACTIONS_INTEGRATION_ID" \
443
+ '[.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]?.integration_id | select(. != null and . != $actions)] | unique | .[]')
444
+
445
+ local drop_filter='
446
+ .rules |= (
447
+ map(
448
+ if .type == "required_status_checks" then
449
+ .parameters.required_status_checks |= map(select((.integration_id // -1) as $i | ($drop | index($i)) | not))
450
+ else . end
451
+ )
452
+ | map(select(.type != "required_status_checks" or (.parameters.required_status_checks | length) > 0))
453
+ )'
454
+
455
+ # Each single app id first (keep the most checks), then all app ids.
456
+ local candidates=()
457
+ local app_id
458
+ for app_id in $app_ids; do
459
+ candidates+=("[$app_id]")
460
+ done
461
+ candidates+=("$(echo "$app_ids" | jq -s -c .)")
462
+
463
+ local drop attempt
464
+ for drop in "${candidates[@]}"; do
465
+ attempt=$(echo "$payload" | jq --argjson drop "$drop" --argjson actions "$ACTIONS_INTEGRATION_ID" "$drop_filter")
466
+ if [[ $(echo "$attempt" | jq '(.rules // [1]) | length') -eq 0 ]]; then
467
+ continue
468
+ fi
469
+ if send_ruleset "$attempt"; then
470
+ log_warning "Applied ruleset '$ruleset_name' without app integration id(s) $drop — app(s) not installed on this repository"
471
+ rm -f "$temp_file"
472
+ return 0
473
+ fi
474
+ done
475
+
476
+ log_error "$error_output"
372
477
  rm -f "$temp_file"
478
+ return 1
373
479
  }
374
480
 
375
481
  ##############################################################################
@@ -89,8 +89,9 @@ if [[ "$YES_MODE" == "true" ]]; then
89
89
  exit 1
90
90
  fi
91
91
 
92
- HAS_KEY=$(gh repo deploy-key list --repo "$OWNER/$REPO" --json title \
93
- --jq --arg t "$KEY_TITLE" '[.[] | select(.title == $t)] | length' 2>/dev/null || echo 0)
92
+ # NOTE: gh's --jq flag does not support jq --arg; pipe through jq instead.
93
+ HAS_KEY=$(gh repo deploy-key list --repo "$OWNER/$REPO" --json title 2>/dev/null \
94
+ | jq --arg t "$KEY_TITLE" '[.[] | select(.title == $t)] | length' 2>/dev/null || echo 0)
94
95
  HAS_SECRET=$(gh secret list --repo "$OWNER/$REPO" --json name \
95
96
  --jq '[.[] | select(.name == "DEPLOY_KEY")] | length' 2>/dev/null || echo 0)
96
97
  if [[ "$HAS_KEY" -gt 0 && "$HAS_SECRET" -gt 0 ]]; then
@@ -107,8 +108,8 @@ if [[ "$YES_MODE" == "true" ]]; then
107
108
 
108
109
  # A stale key under the same title blocks re-adding; replace it.
109
110
  if [[ "$HAS_KEY" -gt 0 ]]; then
110
- gh repo deploy-key list --repo "$OWNER/$REPO" --json id,title \
111
- --jq --arg t "$KEY_TITLE" '.[] | select(.title == $t) | .id' 2>/dev/null \
111
+ gh repo deploy-key list --repo "$OWNER/$REPO" --json id,title 2>/dev/null \
112
+ | jq -r --arg t "$KEY_TITLE" '.[] | select(.title == $t) | .id' \
112
113
  | while read -r key_id; do
113
114
  gh repo deploy-key delete "$key_id" --repo "$OWNER/$REPO" || true
114
115
  done
@@ -1,43 +0,0 @@
1
- {
2
- "name": "cdk validation",
3
- "target": "branch",
4
- "enforcement": "active",
5
- "conditions": {
6
- "ref_name": {
7
- "exclude": [],
8
- "include": [
9
- "~DEFAULT_BRANCH",
10
- "refs/heads/dev",
11
- "refs/heads/staging",
12
- "refs/heads/main"
13
- ]
14
- }
15
- },
16
- "bypass_actors": [
17
- {
18
- "actor_id": null,
19
- "actor_type": "DeployKey",
20
- "bypass_mode": "always"
21
- },
22
- {
23
- "actor_id": 5,
24
- "actor_type": "RepositoryRole",
25
- "bypass_mode": "always"
26
- }
27
- ],
28
- "rules": [
29
- {
30
- "type": "required_status_checks",
31
- "parameters": {
32
- "strict_required_status_checks_policy": false,
33
- "do_not_enforce_on_create": true,
34
- "required_status_checks": [
35
- {
36
- "context": "🏗️ CDK Validation",
37
- "integration_id": 15368
38
- }
39
- ]
40
- }
41
- }
42
- ]
43
- }