--- title: GitHub CI description: Mount GitHub Actions workflows, runs, jobs, logs, and artifacts as a read-only Mirage filesystem. icon: circle-play --- The GitHub CI resource mounts GitHub Actions workflows and runs as a read-only virtual filesystem. For token setup, see [GitHub CI Setup](/python/setup/github_ci). ## Config ```python import os from mirage import MountMode, Workspace from mirage.resource.github_ci import GitHubCIConfig, GitHubCIResource config = GitHubCIConfig( token=os.environ["GITHUB_TOKEN"], owner="my-org", repo="my-repo", ) resource = GitHubCIResource(config=config) ws = Workspace({"/ci": resource}, mode=MountMode.READ) ``` ## Filesystem Layout ```text /ci/ workflows/ _.json runs/ _/ run.json jobs/ _.json _.log annotations.jsonl artifacts/ _.zip ``` Example: ```text /ci/ workflows/ CI_12345678.json Deploy_87654321.json runs/ CI_9876543210/ run.json jobs/ build_11111111.json build_11111111.log test_22222222.json test_22222222.log annotations.jsonl artifacts/ coverage-report_55555.zip ``` ### Workflows `/ci/workflows/` lists all workflows defined in the repository. Each `.json` file contains the workflow metadata (name, path, state). ### Runs `/ci/runs/` lists recent workflow runs within the configured time window (default 30 days). The `created` API parameter filters server-side. Each run directory contains: - `run.json` - run metadata (status, conclusion, event, branch, actor, timing) - `jobs/` - one `.json` and `.log` pair per job - `annotations.jsonl` - check annotations (warnings, errors) across all jobs - `artifacts/` - downloadable build artifacts ### Jobs Each job has two files: - `_.json` - job metadata with steps and timing - `_.log` - full job log (plain text) ### Artifacts Artifacts are served as `.zip` files matching the GitHub API download format. ## Cache The GitHub CI resource uses `IndexCacheStore` with `remote_time`-based fingerprinting. Completed runs and jobs are effectively immutable and benefit from long cache TTL. ## Example ```python import asyncio import os from dotenv import load_dotenv from mirage import MountMode, Workspace from mirage.resource.github_ci import GitHubCIConfig, GitHubCIResource load_dotenv(".env.development") async def main(): config = GitHubCIConfig( token=os.environ["GITHUB_TOKEN"], owner="my-org", repo="my-repo", ) resource = GitHubCIResource(config=config) ws = Workspace({"/ci": resource}, mode=MountMode.READ) # List top-level r = await ws.execute("ls /ci/") print(await r.stdout_str()) # List workflows r = await ws.execute("ls /ci/workflows/") print(await r.stdout_str()) # List recent runs r = await ws.execute("ls /ci/runs/") print(await r.stdout_str()) # Read run metadata r = await ws.execute("cat /ci/runs/CI_9876543210/run.json") print(await r.stdout_str()) # List jobs for a run r = await ws.execute("ls /ci/runs/CI_9876543210/jobs/") print(await r.stdout_str()) # Read job log r = await ws.execute("cat /ci/runs/CI_9876543210/jobs/build_11111111.log") print(await r.stdout_str()) # Read annotations r = await ws.execute("cat /ci/runs/CI_9876543210/annotations.jsonl") print(await r.stdout_str()) # Tree view r = await ws.execute("tree -L 2 /ci/") print(await r.stdout_str()) # Find all failed job logs r = await ws.execute("find /ci/runs/ -name '*.log'") print(await r.stdout_str()) if __name__ == "__main__": asyncio.run(main()) ``` ## Shell Commands Standard commands available on the mounted GitHub CI tree: | Command | Notes | | --------------- | ------------------------------ | | `ls` | List workflows, runs, jobs | | `cat` | Read JSON metadata or job logs | | `head` / `tail` | First/last N lines | | `wc` | Line/word/byte counts | | `stat` | File metadata (type, IDs) | | `find` | Recursive search with `-name` | | `tree` | Directory tree view | ## Working with CI Data ```bash # Check run status via jq cat /ci/runs/CI_9876543210/run.json | jq '.conclusion' # List all job names ls /ci/runs/CI_9876543210/jobs/ | grep '.json$' # Tail a job log for recent output tail -n 50 /ci/runs/CI_9876543210/jobs/build_11111111.log # Count annotations wc -l /ci/runs/CI_9876543210/annotations.jsonl # Find all .log files find /ci/ -name "*.log" ```