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
37 changes: 37 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"author": {
"name": "Anton Babenko",
"url": "https://github.com/antonbabenko"
},
"description": "Terraform and OpenTofu best-practices skill for writing, reviewing, debugging, testing, CI, scans, and state operations.",
"homepage": "https://github.com/antonbabenko/terraform-skill",
"interface": {
"capabilities": [
"Interactive",
"Read",
"Write"
],
"category": "Development",
"developerName": "Anton Babenko",
"displayName": "Terraform Skill",
"longDescription": "Diagnose-first Terraform and OpenTofu guidance with version-aware guardrails for module design, testing strategy, CI/CD workflows, security scanning, compliance checks, and state management.",
"shortDescription": "Terraform and OpenTofu guidance for modules, tests, CI, scans, and state operations.",
"websiteURL": "https://github.com/antonbabenko/terraform-skill"
},
"keywords": [
"ci-cd",
"iac",
"infrastructure-as-code",
"modules",
"opentofu",
"security-scanning",
"state-management",
"terraform",
"testing"
],
"license": "Apache-2.0",
"name": "terraform-skill",
"repository": "https://github.com/antonbabenko/terraform-skill",
"skills": "./skills",
"version": "1.12.0"
}
51 changes: 47 additions & 4 deletions .github/workflows/automated-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ jobs:
skip-version-file: 'false'
skip-commit: 'false'

# 2b. Sync plugin version, SKILL.md version, and git ref
# This ensures all three version fields stay synchronized:
# - root version (updated by conventional-changelog-action above)
# - plugins[0].version (synced here)
# 2b. Sync version fields and git ref
# This ensures all version fields stay synchronized:
# - root version.json (updated by conventional-changelog-action above)
# - SKILL.md metadata.version (synced here)
# - .codex-plugin/plugin.json version (synced here, if present)
- name: Sync Plugin Version and SKILL.md
if: steps.changelog.outputs.skipped == 'false'
env:
Expand Down Expand Up @@ -90,13 +90,53 @@ jobs:

return skill_path

def update_codex_manifest(version):
"""Mirror the version into .codex-plugin/plugin.json if present.

The Codex plugin host reads this manifest when the
agent-plugins marketplace resolves terraform-skill as a
url-source plugin. Keep its version in lockstep with the
SKILL.md single version source so it never goes stale.
"""
manifest_path = '.codex-plugin/plugin.json'

if not os.path.exists(manifest_path):
return None

with open(manifest_path, 'r') as f:
lines = f.readlines()

updated = False
for i, line in enumerate(lines):
# Top-level key only: exactly 2-space indent. Anchored so a
# nested "version" key could never be matched by accident.
if line.startswith(' "version":'):
lines[i] = f' "version": "{version}"\n'
updated = True
break

if not updated:
raise ValueError(
"Could not find version field in .codex-plugin/plugin.json")

with open(manifest_path, 'w') as f:
f.writelines(lines)

return manifest_path

try:
version = os.environ['VERSION']

# SKILL.md frontmatter is the single version source.
skill_path = update_skill_version(version)
print(f"✅ Synced {skill_path} metadata.version to {version}")

manifest_path = update_codex_manifest(version)
if manifest_path:
print(f"✅ Synced {manifest_path} version to {version}")
else:
print("ℹ️ No .codex-plugin/plugin.json; skipped")

except Exception as e:
print(f"❌ ERROR: Failed to sync versions: {e}")
sys.exit(1)
Expand All @@ -106,6 +146,9 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add version.json skills/terraform-skill/SKILL.md
if [ -f .codex-plugin/plugin.json ]; then
git add .codex-plugin/plugin.json
fi
git commit --amend --no-edit
git push --force-with-lease

Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ on:
paths:
- 'skills/**'
- '.claude-plugin/**'
- '.codex-plugin/**'
push:
branches: [master, main]
paths:
- 'skills/**'
- '.claude-plugin/**'
- '.codex-plugin/**'
workflow_dispatch:

jobs:
Expand Down Expand Up @@ -89,6 +91,51 @@ jobs:
print(f"✅ Frontmatter valid ({desc_len} chars)")
EOF

- name: Check Codex Manifest Version Sync
run: |
python3 << 'EOF'
import json
import os
import re
import sys
import yaml

SEMVER = re.compile(r'^\d+\.\d+\.\d+$')

manifest_path = '.codex-plugin/plugin.json'
if not os.path.exists(manifest_path):
print("ℹ️ No .codex-plugin/plugin.json; skipping sync check")
sys.exit(0)

with open('skills/terraform-skill/SKILL.md') as f:
fm = yaml.safe_load(f.read().split('---', 2)[1])
skill_version = (fm.get('metadata') or {}).get('version')

with open(manifest_path) as f:
manifest_version = json.load(f).get('version')

# Both must exist and be real semver, not merely equal: equality
# alone passes when both are missing/empty.
for label, value in (
('SKILL.md metadata.version', skill_version),
(f'{manifest_path} version', manifest_version),
):
if not (isinstance(value, str) and SEMVER.match(value)):
print(
f"❌ ERROR: {label} is not a valid semver: {value!r}. "
f"CI owns these; do not hand-edit (see CLAUDE.md).")
sys.exit(1)

if skill_version != manifest_version:
print(
f"❌ ERROR: version mismatch - SKILL.md metadata.version="
f"{skill_version!r} vs {manifest_path}={manifest_version!r}. "
f"CI owns these; do not hand-edit (see CLAUDE.md).")
sys.exit(1)

print(f"✅ Codex manifest version in sync ({manifest_version})")
EOF

- name: Check File Size
run: |
LINES=$(wc -l < skills/terraform-skill/SKILL.md)
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ git clone https://github.com/antonbabenko/terraform-skill.git ~/.agents/skills/t

Codex auto-discovers skills from `~/.agents/skills/` and `.agents/skills/`. Update with `cd ~/.agents/skills/terraform-skill && git pull`.

For a managed Codex plugin install, use the `antonbabenko/agent-plugins`
marketplace (`codex plugin marketplace add antonbabenko/agent-plugins`, then
install `terraform-skill`). Do not add `antonbabenko/terraform-skill` as a
separate marketplace - it clashes by name with `agent-plugins`.

</details>

<details>
Expand Down
Loading