← Files Plugin AutopilotARCHIVED FILE

tests/test_github_action.py

6.38 KB · Oct 2, 2026 · 00:33 UTC

↓ Download file

#!/usr/bin/env python3
import json
import os
import subprocess
import tempfile
import unittest
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
ACTION_YML = ROOT / "action.yml"
ENTRYPOINT = ROOT / "scripts/action_entrypoint.py"

VALID_BRANDING_COLORS = {
    "white", "yellow", "blue", "green", "orange", "red", "purple", "gray-dark"
}


class GitHubActionTests(unittest.TestCase):
    def test_action_yml_exists_and_conforms_to_marketplace_contract(self):
        self.assertTrue(ACTION_YML.is_file(), "action.yml must exist at repository root")
        text = ACTION_YML.read_text(encoding="utf-8")
        
        # Parse basic YAML structure
        self.assertIn("name:", text)
        self.assertIn("description:", text)
        self.assertIn("author:", text)
        self.assertIn("branding:", text)
        self.assertIn("icon:", text)
        self.assertIn("color:", text)
        self.assertIn("runs:", text)
        self.assertIn("using: 'composite'", text)
        self.assertIn("scripts/action_entrypoint.py", text)

        # Check required inputs
        for input_name in ("path:", "action:", "output-dir:", "fail-on-error:", "summary:"):
            self.assertIn(input_name, text)

        # Check required outputs
        for output_name in ("ok:", "architecture:", "skills-count:", "plugin-path:", "sha256:"):
            self.assertIn(output_name, text)

    def test_entrypoint_renders_markdown_summary_and_outputs(self):
        with tempfile.TemporaryDirectory(prefix="action-test-") as temp_dir:
            temp_path = Path(temp_dir)
            gh_output = temp_path / "github_output.txt"
            gh_summary = temp_path / "github_summary.md"

            # Create a mock agentic repository with a skill and AGENTS.md
            mock_repo = temp_path / "mock-repo"
            mock_repo.mkdir()
            (mock_repo / "AGENTS.md").write_text("# Test Agents\nInstructions here", encoding="utf-8")
            mock_skill = mock_repo / "skills/test-skill"
            mock_skill.mkdir(parents=True)
            (mock_skill / "SKILL.md").write_text("---\nname: test-skill\ndescription: A test skill\n---\nBody", encoding="utf-8")

            env = {
                **os.environ,
                "ACTION_PATH": str(ROOT),
                "GITHUB_OUTPUT": str(gh_output),
                "GITHUB_STEP_SUMMARY": str(gh_summary),
            }

            # Run action in analyze mode
            cmd = [
                "python3",
                str(ENTRYPOINT),
                "--path", str(mock_repo),
                "--action", "analyze",
                "--output-dir", str(temp_path / "dist"),
                "--fail-on-error", "true",
                "--summary", "true",
            ]
            proc = subprocess.run(cmd, env=env, text=True, capture_output=True, cwd=str(ROOT))
            self.assertEqual(proc.returncode, 0, f"STDOUT: {proc.stdout}\nSTDERR: {proc.stderr}")

            # Verify GITHUB_OUTPUT was written
            self.assertTrue(gh_output.is_file(), "GITHUB_OUTPUT file must exist")
            output_content = gh_output.read_text(encoding="utf-8")
            self.assertIn("ok=true", output_content)
            self.assertIn("architecture=skills-only", output_content)
            self.assertIn("skills_count=", output_content)

            # Verify GITHUB_STEP_SUMMARY was written
            self.assertTrue(gh_summary.is_file(), "GITHUB_STEP_SUMMARY file must exist")
            summary_content = gh_summary.read_text(encoding="utf-8")
            self.assertIn("## ✅ ChatGPT / Codex Plugin Autopilot Summary", summary_content)
            self.assertIn("Discovered Workflow Candidates", summary_content)
            self.assertIn("skills-only", summary_content)

    def test_entrypoint_handles_missing_directory_gracefully(self):
        with tempfile.TemporaryDirectory(prefix="action-missing-") as temp_dir:
            temp_path = Path(temp_dir)
            gh_output = temp_path / "github_output.txt"
            non_existent = temp_path / "non_existent_folder"

            env = {
                **os.environ,
                "ACTION_PATH": str(ROOT),
                "GITHUB_OUTPUT": str(gh_output),
            }

            # With fail-on-error=false, should return 0
            cmd = [
                "python3",
                str(ENTRYPOINT),
                "--path", str(non_existent),
                "--fail-on-error", "false",
            ]
            proc = subprocess.run(cmd, env=env, text=True, capture_output=True, cwd=str(ROOT))
            self.assertEqual(proc.returncode, 0)
            self.assertIn("ok=false", gh_output.read_text(encoding="utf-8"))

            # With fail-on-error=true, should return 1
            cmd_fail = [
                "python3",
                str(ENTRYPOINT),
                "--path", str(non_existent),
                "--fail-on-error", "true",
            ]
            proc_fail = subprocess.run(cmd_fail, env=env, text=True, capture_output=True, cwd=str(ROOT))
            self.assertEqual(proc_fail.returncode, 1)

    def test_entrypoint_package_mode_creates_artifact_and_checksum(self):
        with tempfile.TemporaryDirectory(prefix="action-package-") as temp_dir:
            temp_path = Path(temp_dir)
            out_dir = temp_path / "dist"
            gh_output = temp_path / "github_output.txt"

            env = {
                **os.environ,
                "ACTION_PATH": str(ROOT),
                "GITHUB_OUTPUT": str(gh_output),
            }

            cmd = [
                "python3",
                str(ENTRYPOINT),
                "--path", str(ROOT),
                "--action", "package",
                "--output-dir", str(out_dir),
                "--fail-on-error", "true",
            ]
            proc = subprocess.run(cmd, env=env, text=True, capture_output=True, cwd=str(ROOT))
            self.assertEqual(proc.returncode, 0, f"STDOUT: {proc.stdout}\nSTDERR: {proc.stderr}")

            # Verify packaged ZIP exists
            zips = list(out_dir.glob("*.zip"))
            self.assertEqual(len(zips), 1, f"Expected 1 zip, found {zips}")
            self.assertGreater(zips[0].stat().st_size, 1000)

            # Verify output variables
            output_content = gh_output.read_text(encoding="utf-8")
            self.assertIn("ok=true", output_content)
            self.assertIn("plugin_path=", output_content)
            self.assertIn("sha256=", output_content)


if __name__ == "__main__":
    unittest.main()

SHA-256: 7062416f9518fa099567682843542388bf96be08e6fc69e6a753db44f703841a