diff --git a/.gitea/ci/sync_thirdparty_skills.sh b/.gitea/ci/sync_thirdparty_skills.sh index aacea86..f19a9c2 100644 --- a/.gitea/ci/sync_thirdparty_skills.sh +++ b/.gitea/ci/sync_thirdparty_skills.sh @@ -25,6 +25,7 @@ for entry in data["sources"]: entry["sync_mode"], entry["source_list"], entry.get("skills_subdir", ""), + ",".join(entry.get("exclude_skill_dirs", [])), entry.get("output_name", entry["id"]), entry.get("platform_config", ""), entry.get("template_root", ""), @@ -107,6 +108,23 @@ tracked_skill_exists() { return 1 } +is_excluded_skill_dir() { + local name="$1" + local exclude_csv="$2" + + [ -n "$exclude_csv" ] || return 1 + + local IFS=',' + read -r -a excluded_names <<< "$exclude_csv" + for excluded_name in "${excluded_names[@]}"; do + if [ "$name" = "$excluded_name" ]; then + return 0 + fi + done + + return 1 +} + cd "$REPO_DIR" git config user.name "$COMMIT_AUTHOR_NAME" @@ -131,7 +149,7 @@ if ! emit_sources_tsv > "$sources_file"; then exit 1 fi -while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdir output_name platform_config template_root data_dir scripts_dir; do +while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdir exclude_skill_dirs output_name platform_config template_root data_dir scripts_dir; do [ -n "$source_id" ] || continue if [ -f "$source_list" ]; then @@ -143,7 +161,7 @@ while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_su done < "$sources_file" declare -A owners=() -while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdir output_name platform_config template_root data_dir scripts_dir; do +while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_subdir exclude_skill_dirs output_name platform_config template_root data_dir scripts_dir; do [ -n "$source_id" ] || continue git archive --format=tar "origin/${THIRDPARTY_BRANCH}" "$snapshot_dir" | tar -xf - -C "$tmp_dir" @@ -161,6 +179,9 @@ while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_su for dir in "$source_skills_dir"/*; do [ -d "$dir" ] || continue name="$(basename "$dir")" + if is_excluded_skill_dir "$name" "$exclude_skill_dirs"; then + continue + fi if [ -n "${owners[$name]:-}" ] && [ "${owners[$name]}" != "$source_id" ]; then echo "ERROR: duplicate third-party skill name: $name" >&2 exit 1 diff --git a/.gitea/ci/thirdparty_skills.json b/.gitea/ci/thirdparty_skills.json index 0196f10..a74fcb2 100644 --- a/.gitea/ci/thirdparty_skills.json +++ b/.gitea/ci/thirdparty_skills.json @@ -7,7 +7,8 @@ "snapshot_dir": "superpowers", "sync_mode": "copy_skill_dirs", "source_list": "codex/skills/.sources/superpowers.list", - "skills_subdir": "skills" + "skills_subdir": "skills", + "exclude_skill_dirs": ["ui-ux-pro-max"] }, { "id": "ui-ux-pro-max", diff --git a/tests/test_thirdparty_skills_pipeline.py b/tests/test_thirdparty_skills_pipeline.py index bd5a0d3..fe8419f 100644 --- a/tests/test_thirdparty_skills_pipeline.py +++ b/tests/test_thirdparty_skills_pipeline.py @@ -33,6 +33,11 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase): self.assertEqual(ui_skill["sync_mode"], "render_codex_skill") self.assertEqual(ui_skill["snapshot_dir"], "ui-ux-pro-max") + def test_superpowers_manifest_excludes_ui_ux_pro_max_from_copy_mode(self): + data = load_manifest() + superpowers = next(item for item in data["sources"] if item["id"] == "superpowers") + self.assertEqual(superpowers["exclude_skill_dirs"], ["ui-ux-pro-max"]) + def test_workflow_uses_generic_scripts_and_single_serial_job(self): text = WORKFLOW.read_text(encoding="utf-8") self.assertFalse(LEGACY_WORKFLOW.exists()) @@ -97,6 +102,8 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase): self.assertIn('"\\x1f".join(', text) self.assertIn("while IFS=$'\\x1f' read -r", text) self.assertNotIn("while IFS=$'\\t' read -r", text) + self.assertIn("exclude_skill_dirs", text) + self.assertIn('if is_excluded_skill_dir "$name" "$exclude_skill_dirs"; then', text) if __name__ == "__main__":