{"id":28200781,"url":"https://github.com/alexandergrooff/spage","last_synced_at":"2025-10-29T18:10:28.268Z","repository":{"id":293269631,"uuid":"875937879","full_name":"AlexanderGrooff/spage","owner":"AlexanderGrooff","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-14T13:14:10.000Z","size":445,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-14T14:40:49.568Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlexanderGrooff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-10-21T06:08:36.000Z","updated_at":"2025-05-14T13:14:15.000Z","dependencies_parsed_at":"2025-05-14T14:41:10.989Z","dependency_job_id":"52d0061a-77ea-4680-922c-a43e6c1f7d7c","html_url":"https://github.com/AlexanderGrooff/spage","commit_stats":null,"previous_names":["alexandergrooff/spage"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AlexanderGrooff/spage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderGrooff%2Fspage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderGrooff%2Fspage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderGrooff%2Fspage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderGrooff%2Fspage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlexanderGrooff","download_url":"https://codeload.github.com/AlexanderGrooff/spage/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexanderGrooff%2Fspage/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259512021,"owners_count":22869327,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-16T21:17:08.075Z","updated_at":"2025-10-29T18:10:28.260Z","avatar_url":"https://github.com/AlexanderGrooff.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spage\n\nThis projects aims to function 'as' Ansible, but hugely more performant. By taking an Ansible playbook + inventory as\ninput, it will generate a Go program that can be compiled for a specific host.\nThe end result is a generated `.go` file that can be compiled and shipped to the target host.\n\nTo create such a program, this project ships the `spage` binary, with which you can target Ansible playbooks + inventories.\n\nKey benefits:\n\n- **(Almost full) Ansible compatibility** - Any playbook that works with Ansible works with Spage\n- **Significantly faster execution** - Compiles to native Go code instead of interpreting Python\n- **No Python dependency** - Single binary that can run anywhere\n- **Extended features** - Built-in parallel execution, automatic rollback on failure, variable usage detection, and\nsupport for external executors (like `temporal`)\n- **Same syntax, but extra keywords** - Uses identical YAML playbook format and module parameters, with extra options\nfor parallel execution with `before`/`after`\n\nSpage works by:\n\n1. Taking your existing Ansible playbooks and inventory files\n2. Generating Go code that implements the same logic\n3. Compiling this into a single binary for your target environment\n4. Executing tasks with native Go modules where possible, falling back to Python for full compatibility\n\n## Installation\n\nThe fastest way to install Spage is using our installation script:\n\n```bash\ncurl -sSL https://spage.dev/install.sh | bash\n```\n\nThis will automatically detect your OS and architecture, download the latest release, and install it to `/usr/local/bin/spage`.\n\nFor other installation methods (manual download, Go install, building from source), see the [Installation Guide](https://spage.dev/docs/installation).\n\n## Usage\n\nYou can use Spage in two ways:\n\n1. Generate the Go code that you can then compile and run (using the `spage generate` command)\n2. Run directly across an inventory (using the `spage run` command)\n\n```bash\n# Generate the Go code that you can then compile and run\nspage generate --playbook playbook.yaml --output generated_tasks.go\ngo build -o spage_playbook generated_tasks.go\n./spage_playbook --inventory inventory.yaml\n\n# Or run directly across an inventory\nspage run --inventory inventory.yaml --playbook playbook.yaml\n```\n\n## FAQ\n\n### Q: What is Spage?\n\n**A: Spage is a high-performance drop-in replacement for Ansible** that compiles your\nplaybooks into Go programs. You can then utilize the Golang toolchain to compile and run the playbook, either locally\nor on the target host.\n\n### Q: Why should I use Spage?\n\n**A: Spage is a drop-in replacement for Ansible** that compiles your playbooks into Go programs. You can then utilize the\nGolang toolchain to compile and run the playbook, either locally or on the target host.\n\nIf you're familiar with Ansible but want to improve performance, compile to a binary, get\nrid of the Python dependency or want to adopt different execution models\nsuch as running in Temporal, Spage is for you.\nInstead of running `ansible-playbook playbook.yaml`, you can run\n`spage run playbook.yaml` or `spage generate playbook.yaml -o generated_tasks.go \u0026\u0026 go run generated_tasks.go`.\nTypical variables such as `--become`, `--inventory`, `--tags`, `--extra-vars` are supported.\n\n### Q: Why is it called Spage?\n\n**A: It's a reference to [Factorio: Space Age](https://www.factorio.com/space-age/buy).** I built Spage when Space Age was\nnot yet released, and I wanted something to do. So while waiting for the release, I\nfound a very funny Reddit comment calling it Spage, and thus Spage was born.\n\n### Q: I have module `x.y.z` from an Ansible Galaxy collection. Is this supported in Spage?\n\n**A: Yes, absolutely!** Spage supports **any** Ansible module, including those from Ansible Galaxy collections, through\nits Python fallback mechanism. See the [Python Fallback Mechanism](#python-fallback-mechanism) section for more details.\n\n## Python Fallback Mechanism\n\nSpage includes a sophisticated Python fallback mechanism that allows it to execute any Ansible module, even those not\nnatively implemented in Go. This ensures 100% compatibility with the Ansible ecosystem while maintaining performance benefits.\n\n### When Python Fallback is Used\n\nThe Python fallback automatically activates when:\n\n- A module name is not found in Spage's native Go modules\n- You explicitly use the `ansible_python` module type\n- Community collections or custom modules are referenced (e.g., `community.general.setup`, `custom.namespace.module`)\n\n### How It Works\n\n1. **Module Detection**: Spage first attempts to find a native Go implementation of the requested module.\n2. **Fallback Activation**: If no native module exists, the Python fallback mechanism engages.\n3. **Playbook Generation**: A temporary Ansible playbook is generated, containing the required module and its parameters.\n4. **Remote Execution**: Spage executes the playbook on the target host using `ansible-playbook`.\n\n### Usage Examples\n\n```yaml\n# The 'command' module is supported natively by Spage, so it doesn't use the Python fallback\n- name: Get Python requirements info\n  command:\n    cmd: echo \"Hello world!\"\n\n# Community collection module is not (yet) supported by Spage, so it uses the Python fallback\n- name: Get Python requirements info\n  community.general.python_requirements_info:\n    dependencies: []\n\n# Custom namespace module is also using the Python fallback\n- name: Use custom module\n  my_company.custom_collection.special_module:\n    param1: value1\n    param2: value2\n\n# Explicit Python fallback\n- name: Force usage of Python fallback for ping module\n  ansible_python:\n    module_name: ping\n    args:\n      data: pong\n```\n\n### Limitations\n\n- Requires Python 3 and pip on the executing host for collection installation\n- Some complex Ansible plugins may have additional dependencies\n\n## Differences between Spage and Ansible\n\nSpage is a drop-in replacement for Ansible, but with some notable differences:\n\n- Playbooks are allowed to start without `- tasks:`. It assumes `hosts: localhost` and runs locally.\n- Tasks are executed in parallel by default based on variable usage.\n- New keywords `before`/`after` are available to control the flow of parallel tasks.\n- The `shell` module has two new parameters: `execute` and `revert`. If you don't specify these options and just use it\nas you would with Ansible, it will not do anything on revert.\n\nTODO:\n\n- Add revert conditions `revert_when`\n- Should we compile assets (templates, files) along with the code?\n- `vars_prompt` on play\n- `gather_facts` on play\n- Logic for `no_log`\n- Plugin support\n- Callback support\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandergrooff%2Fspage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexandergrooff%2Fspage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandergrooff%2Fspage/lists"}