From 4fbb2dff3b1e2be33ded955f3aea55d1c228ea1d Mon Sep 17 00:00:00 2001 From: Eduardo Fraga Date: Wed, 29 Jul 2026 08:03:37 -0300 Subject: [PATCH 1/4] feat(tests): add smoke tests and CI automation --- .github/workflows/test.yaml | 66 ++++++++++++++++++++++++++++--------- AGENTS.md | 30 +++++++++++++++++ tests/smoke_ansible.sh | 17 ++++++++++ tests/smoke_build.sh | 11 +++++++ tests/smoke_playbook.sh | 17 ++++++++++ tests/smoke_python.sh | 14 ++++++++ tests/smoke_shell.sh | 21 ++++++++++++ tests/test.yml | 7 ++++ 8 files changed, 168 insertions(+), 15 deletions(-) create mode 100644 AGENTS.md create mode 100755 tests/smoke_ansible.sh create mode 100755 tests/smoke_build.sh create mode 100755 tests/smoke_playbook.sh create mode 100755 tests/smoke_python.sh create mode 100755 tests/smoke_shell.sh create mode 100644 tests/test.yml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8d00f7c..8b9af20 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,18 +1,54 @@ -name: Run +name: Smoke tests on: - workflow_dispatch: - inputs: - command: - description: "Command to execute" - required: true - default: "ansible-playbook" - -jobs: - run: + push: + branches: ["**"] + pull_request: + branches: ["master"] + workflow_dispatch: + +jobs: + smoke: runs-on: ubuntu-latest - steps: - - uses: eftechcombr/ansible-cli-github-action@master - with: - command: "ansible --version" - + steps: + - uses: actions/checkout@v4 + + - name: Build Docker image + run: docker build -t ansible-cli-smoke:test . + + - name: smoke_build — image built + run: docker image inspect ansible-cli-smoke:test > /dev/null + + - name: smoke_ansible — CLI version checks + run: | + docker run --rm ansible-cli-smoke:test "ansible --version" + docker run --rm ansible-cli-smoke:test "ansible-playbook --version" + docker run --rm ansible-cli-smoke:test "ansible-inventory --help" + + - name: smoke_python — dependency imports + run: | + docker run --rm ansible-cli-smoke:test "python -c 'import winrm; print(\"winrm ok\")'" + docker run --rm ansible-cli-smoke:test "python -c 'import ansible; print(\"ansible ok\")'" + + - name: smoke_shell — eval passthrough + run: | + OUTPUT=$(docker run --rm ansible-cli-smoke:test "echo hello from ansible") + [ "$OUTPUT" = "hello from ansible" ] || { echo "FAIL: $OUTPUT"; exit 1; } + + - name: smoke_shell — exit code propagation + run: | + set +e + docker run --rm ansible-cli-smoke:test "exit 42" + RC=$? + set -e + [ "$RC" -eq 42 ] || { echo "FAIL: expected 42, got $RC"; exit 1; } + + - name: smoke_playbook — syntax check + run: | + docker run --rm -v ${{ github.workspace }}/tests:/tests:ro ansible-cli-smoke:test \ + "ansible-playbook --syntax-check /tests/test.yml" + + - name: smoke_playbook — ping localhost + run: | + docker run --rm -v ${{ github.workspace }}/tests:/tests:ro ansible-cli-smoke:test \ + "ansible-playbook -i 'localhost,' -c local /tests/test.yml" diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..87f18a4 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,30 @@ +# AGENTS.md + +## Dev environment tips +- Build the Docker image with `docker build -t ansible-cli-smoke:test .` before running tests. +- Use `docker compose build` for the Compose-based build. + +## Testing instructions +- Run all smoke tests: `tests/smoke_build.sh && tests/smoke_ansible.sh && tests/smoke_python.sh && tests/smoke_shell.sh && tests/smoke_playbook.sh` +- Or run individual tests: `tests/smoke_build.sh` (must run first — sets image tag), then any of `tests/smoke_ansible.sh`, `tests/smoke_python.sh`, `tests/smoke_shell.sh`, `tests/smoke_playbook.sh` +- CI runs all smoke tests via `.github/workflows/test.yaml` on every push and PR. + +## PR instructions +- Follow Conventional Commits (for example, `feat(scaffolding): add doc links`). +- Cross-link new scaffolds in `docs/README.md` and `agents/README.md` so future agents can find them. +- Attach sample CLI output or generated markdown when behaviour shifts. +- Confirm the built artefacts in `dist/` match the new source changes. + +## Repository map +- `action.yml` — GitHub Action metadata (inputs, branding, Docker runtime config) +- `docker-compose.yaml` — local dev convenience for building and tagging the image +- `Dockerfile` — builds the container from `python:3.11-slim` +- `entrypoint.sh` — container entrypoint, executes `eval $1` +- `README.md` — user-facing documentation +- `requirements.txt` — Python dependencies (`ansible`, `pywinrm[credssp]`) +- `tests/` — smoke test scripts and test fixtures + +## AI Context References +- Documentation index: `.context/docs/README.md` +- Agent playbooks: `.context/agents/README.md` +- Contributor guide: `CONTRIBUTING.md` diff --git a/tests/smoke_ansible.sh b/tests/smoke_ansible.sh new file mode 100755 index 0000000..a7d4ea3 --- /dev/null +++ b/tests/smoke_ansible.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +. /tmp/ansible_smoke_image 2>/dev/null || IMG_LABEL="ansible-cli-smoke:test" + +echo "=== smoke_ansible: Ansible CLI tools ===" + +echo " -> ansible --version" +docker run --rm "$IMG_LABEL" "ansible --version" + +echo " -> ansible-playbook --version" +docker run --rm "$IMG_LABEL" "ansible-playbook --version" + +echo " -> ansible-inventory --help" +docker run --rm "$IMG_LABEL" "ansible-inventory --help" + +echo "PASS: smoke_ansible" diff --git a/tests/smoke_build.sh b/tests/smoke_build.sh new file mode 100755 index 0000000..abff463 --- /dev/null +++ b/tests/smoke_build.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +echo "=== smoke_build: Docker image build ===" + +IMG_LABEL="ansible-cli-smoke:test" + +docker build -t "$IMG_LABEL" . + +echo "PASS: smoke_build" +echo "IMG_LABEL=$IMG_LABEL" > /tmp/ansible_smoke_image diff --git a/tests/smoke_playbook.sh b/tests/smoke_playbook.sh new file mode 100755 index 0000000..9ba6703 --- /dev/null +++ b/tests/smoke_playbook.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +. /tmp/ansible_smoke_image 2>/dev/null || IMG_LABEL="ansible-cli-smoke:test" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +echo "=== smoke_playbook: Ansible playbook parsing and local run ===" + +echo " -> syntax check" +docker run --rm -v "$SCRIPT_DIR:/tests:ro" "$IMG_LABEL" \ + "ansible-playbook --syntax-check /tests/test.yml" + +echo " -> ping localhost" +docker run --rm -v "$SCRIPT_DIR:/tests:ro" "$IMG_LABEL" \ + "ansible-playbook -i 'localhost,' -c local /tests/test.yml" + +echo "PASS: smoke_playbook" diff --git a/tests/smoke_python.sh b/tests/smoke_python.sh new file mode 100755 index 0000000..63afb66 --- /dev/null +++ b/tests/smoke_python.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +. /tmp/ansible_smoke_image 2>/dev/null || IMG_LABEL="ansible-cli-smoke:test" + +echo "=== smoke_python: Python dependency imports ===" + +echo " -> import winrm" +docker run --rm "$IMG_LABEL" "python -c \"import winrm; print('winrm version:', winrm.__version__)\"" + +echo " -> import ansible" +docker run --rm "$IMG_LABEL" "python -c \"import ansible; print('ansible loaded ok')\"" + +echo "PASS: smoke_python" diff --git a/tests/smoke_shell.sh b/tests/smoke_shell.sh new file mode 100755 index 0000000..a6ef121 --- /dev/null +++ b/tests/smoke_shell.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -e + +. /tmp/ansible_smoke_image 2>/dev/null || IMG_LABEL="ansible-cli-smoke:test" + +echo "=== smoke_shell: eval passthrough + exit codes ===" + +echo " -> echo passthrough" +OUTPUT=$(docker run --rm "$IMG_LABEL" "echo hello from ansible") +echo " output: $OUTPUT" +[ "$OUTPUT" = "hello from ansible" ] || { echo "FAIL: unexpected output"; exit 1; } + +echo " -> exit code propagation (expect exit 42)" +set +e +docker run --rm "$IMG_LABEL" "exit 42" +RC=$? +set -e +echo " exit code: $RC" +[ "$RC" -eq 42 ] || { echo "FAIL: expected 42, got $RC"; exit 1; } + +echo "PASS: smoke_shell" diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..232ac4f --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,7 @@ +--- +- name: Smoke test connectivity + hosts: localhost + gather_facts: false + tasks: + - name: Verify reachability + ping: From 3b756fb8e37f0a70c693f19bf210638f34db7f71 Mon Sep 17 00:00:00 2001 From: Eduardo Fraga Date: Wed, 29 Jul 2026 08:28:28 -0300 Subject: [PATCH 2/4] docs: update documentation for smoke tests and CI automation --- .context/docs/development-workflow.md | 52 ++++++++++++++++++ .context/docs/testing-strategy.md | 78 +++++++++++++++++++++++++++ .context/docs/tooling.md | 75 ++++++++++++++++++++++++++ README.md | 28 ++++++++-- 4 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 .context/docs/development-workflow.md create mode 100644 .context/docs/testing-strategy.md create mode 100644 .context/docs/tooling.md diff --git a/.context/docs/development-workflow.md b/.context/docs/development-workflow.md new file mode 100644 index 0000000..bb5d89d --- /dev/null +++ b/.context/docs/development-workflow.md @@ -0,0 +1,52 @@ +--- +type: doc +name: development-workflow +description: Day-to-day engineering processes, branching, and contribution guidelines +category: workflow +generated: 2026-07-29 +status: filled +--- + +# Development Workflow + +## Prerequisites + +- Docker +- Git + +## Local Development + +1. Clone the repository +2. Build the Docker image: + ```bash + docker compose build + ``` +3. Run the full smoke test suite: + ```bash + tests/smoke_build.sh && tests/smoke_ansible.sh && tests/smoke_python.sh && tests/smoke_shell.sh && tests/smoke_playbook.sh + ``` +4. Or test a single command: + ```bash + docker run --rm eftechcombr/ansible-cli-github-action "ansible --version" + ``` + +## Making Changes + +- Edit the appropriate file (`Dockerfile`, `entrypoint.sh`, `requirements.txt`, `action.yml`) +- Rebuild and run the smoke test suite locally +- Update `README.md` if the interface changes +- Verify all five smoke tests pass before committing + +## CI/CD + +The repository has two workflows (see `.github/workflows/`): + +- **test.yaml** — Runs automatically on every push (any branch) and pull request (targeting master). Executes all five smoke tests: build, ansible CLI, Python imports, shell passthrough, and playbook execution. Can also be triggered manually via `workflow_dispatch`. +- **build.yaml** — Manually triggered workflow that builds the Docker image using `docker/build-push-action` (no push). + +## Contribution Guidelines + +- Follow conventional commits for PR titles +- Test changes locally with the full smoke test suite +- Ensure all five smoke tests pass +- Update `README.md` for any interface or input changes diff --git a/.context/docs/testing-strategy.md b/.context/docs/testing-strategy.md new file mode 100644 index 0000000..3e05b21 --- /dev/null +++ b/.context/docs/testing-strategy.md @@ -0,0 +1,78 @@ +--- +type: doc +name: testing-strategy +description: Test frameworks, patterns, coverage requirements, and quality gates +category: testing +generated: 2026-07-29 +status: filled +--- + +# Testing Strategy + +## Approach + +This project is a thin Docker-based GitHub Action. Testing focuses on three areas: + +1. **Container build** — ensure the Docker image builds successfully +2. **Command execution** — verify that Ansible is installed and runnable inside the container +3. **Runtime behavior** — verify shell passthrough, exit code propagation, and playbook execution + +Smoke tests are implemented as standalone shell scripts in `tests/` that can be run locally or in CI. + +## Tests + +### Local Testing + +Build the image first, then run the full smoke test suite: + +```bash +tests/smoke_build.sh && tests/smoke_ansible.sh && tests/smoke_python.sh && tests/smoke_shell.sh && tests/smoke_playbook.sh +``` + +Individual smoke tests can also be run independently: + +```bash +tests/smoke_build.sh # must run first — sets image tag +tests/smoke_ansible.sh # checks ansible, ansible-playbook, ansible-inventory +tests/smoke_python.sh # checks Python dependency imports (winrm, ansible) +tests/smoke_shell.sh # checks eval passthrough and exit code propagation +tests/smoke_playbook.sh # checks playbook syntax checking and localhost ping +``` + +Alternatively, build and test with Docker Compose: + +```bash +docker compose build +docker run --rm eftechcombr/ansible-cli-github-action "ansible --version" +``` + +### CI Testing (GitHub Actions) + +The workflow in `.github/workflows/test.yaml` runs all five smoke tests automatically on every push (any branch) and pull request (targeting master). It can also be triggered manually via `workflow_dispatch`. + +The CI pipeline executes the same checks as the local smoke scripts: + +- **smoke_build** — verifies the Docker image is built +- **smoke_ansible** — runs `ansible --version`, `ansible-playbook --version`, `ansible-inventory --help` +- **smoke_python** — imports `winrm` and `ansible` Python packages +- **smoke_shell** — verifies command output passthrough and exit code propagation +- **smoke_playbook** — runs `ansible-playbook --syntax-check` and a ping playbook against localhost + +## Quality Gates + +- Docker image must build without errors +- `ansible --version` must exit with code 0 +- `ansible-playbook --version` must exit with code 0 +- `ansible-inventory --help` must exit with code 0 +- Python `winrm` and `ansible` module imports must succeed +- Shell command output must pass through correctly +- Shell exit codes must propagate correctly +- Playbook syntax checking must pass +- Playbook must run successfully against localhost with the `local` connection plugin + +## What We Don't Test + +- Ansible playbook correctness (the action is a runner, not a linter) +- Specific Ansible modules or features (upstream Ansible tests those) +- Remote host connectivity or SSH configuration +- Multi-node playbook orchestration diff --git a/.context/docs/tooling.md b/.context/docs/tooling.md new file mode 100644 index 0000000..a47f419 --- /dev/null +++ b/.context/docs/tooling.md @@ -0,0 +1,75 @@ +--- +type: doc +name: tooling +description: Scripts, IDE settings, automation, and developer productivity tips +category: tooling +generated: 2026-07-29 +status: filled +--- + +# Tooling + +## Docker Compose + +`docker-compose.yaml` provides a quick way to build and tag the image: + +```bash +docker compose build +``` + +## VS Code Settings + +`.vscode/settings.json` contains: + +```json +{ + "kiroAgent.configureMCP": "Enabled" +} +``` + +## GitHub Actions + +The CI workflow runs automatically: + +- **Test** (`.github/workflows/test.yaml`) — triggered on every push (any branch) and pull request (targeting master). Runs all five smoke tests: build, ansible CLI, Python imports, shell passthrough, and playbook execution. Also supports manual trigger via `workflow_dispatch`. +- **Build** (`.github/workflows/build.yaml`) — manually triggered workflow that builds the Docker image using `docker/build-push-action` (no push to registry). + +## Smoke Tests + +Five standalone shell scripts live in `tests/`: + +| Script | What It Tests | +|---|---| +| `smoke_build.sh` | Docker image builds successfully | +| `smoke_ansible.sh` | Ansible CLI tools are present and runnable | +| `smoke_python.sh` | Python dependencies (`winrm`, `ansible`) are importable | +| `smoke_shell.sh` | Command passthrough and exit code propagation | +| `smoke_playbook.sh` | Playbook syntax checking and localhost execution | + +Run the full suite: + +```bash +tests/smoke_build.sh && tests/smoke_ansible.sh && tests/smoke_python.sh && tests/smoke_shell.sh && tests/smoke_playbook.sh +``` + +## Quick Reference + +```bash +# Build locally +docker compose build +# or +docker build -t ansible-cli-smoke:test . + +# Run all smoke tests +tests/smoke_build.sh && tests/smoke_ansible.sh && tests/smoke_python.sh && tests/smoke_shell.sh && tests/smoke_playbook.sh + +# Run a command +docker run --rm eftechcombr/ansible-cli-github-action "ansible --version" + +# Interactive shell (for debugging) +docker run --rm -it --entrypoint /bin/bash eftechcombr/ansible-cli-github-action +``` + +## No Package Manager + +This project has no `package.json` — all dependencies are Python-based and managed via `requirements.txt`. diff --git a/README.md b/README.md index 9d65861..86840f5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Ansible CLI Github Action -This action is based on `ubuntu:bionic` image. -You can execute all `Ansible` related actions i.e, `ansible` or `ansible-playbook`. -You can also execute standard `Linux` commands as base `Docker` image is `ubuntu`. +This action is based on the `python:3.11-slim` image. +You can execute all Ansible-related commands: `ansible`, `ansible-playbook`, `ansible-galaxy`, and others. +You can also execute standard Linux commands as the base image includes a shell environment. ## Inputs @@ -12,8 +12,26 @@ You can also execute standard `Linux` commands as base `Docker` image is `ubuntu ## Example usage -``` -uses: actions/ansible-cli-action@latest +```yaml +uses: eftechcombr/ansible-cli-github-action@latest with: command: "ansible-playbook main.yml" ``` + +## Testing + +Run the smoke test suite locally to verify the Docker image builds and all Ansible tools work correctly: + +```bash +tests/smoke_build.sh && tests/smoke_ansible.sh && tests/smoke_python.sh && tests/smoke_shell.sh && tests/smoke_playbook.sh +``` + +The smoke tests cover: + +- Docker image build +- Ansible CLI version checks (`ansible`, `ansible-playbook`, `ansible-inventory`) +- Python dependency imports (`winrm`, `ansible`) +- Shell command passthrough and exit code propagation +- Playbook syntax checking and localhost execution + +CI runs these tests automatically on every push and pull request via GitHub Actions. From e83152cb83eb1a7edec336c80ed7feac852004c1 Mon Sep 17 00:00:00 2001 From: Eduardo Fraga Date: Wed, 29 Jul 2026 09:03:43 -0300 Subject: [PATCH 3/4] docs: add connection examples for Windows, Linux, and self-hosted runners --- .context/docs/examples.md | 199 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 .context/docs/examples.md diff --git a/.context/docs/examples.md b/.context/docs/examples.md new file mode 100644 index 0000000..5173a27 --- /dev/null +++ b/.context/docs/examples.md @@ -0,0 +1,199 @@ +## Examples + +### Example 1: Windows connection via WinRM + +This example runs an Ansible playbook against a Windows target over WinRM. The `pywinrm[credssp]` package is pre-installed in the action's Docker image, so no additional setup is required. + +**Inventory (`inventory.ini`):** + +```ini +[windows] +windows-server-01.example.com + +[windows:vars] +ansible_connection=winrm +ansible_winrm_transport=ntlm +ansible_user=Administrator +ansible_password={{ windows_admin_password }} +ansible_winrm_server_cert_validation=ignore +``` + +**Playbook (`win-ping.yml`):** + +```yaml +--- +- name: Verify Windows host connectivity + hosts: windows + tasks: + - name: Test WinRM connection + ansible.windows.win_ping: +``` + +**Workflow (`.github/workflows/windows-check.yml`):** + +```yaml +name: Windows Connectivity Check + +on: + schedule: + - cron: "0 6 * * *" + workflow_dispatch: + +jobs: + winrm-ping: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run WinRM ping playbook + uses: eftechcombr/ansible-cli-github-action@master + with: + command: > + ansible-playbook win-ping.yml + -i inventory.ini + -e windows_admin_password=${{ secrets.WINDOWS_ADMIN_PASSWORD }} +``` + +The `ansible-playbook` command passes the inventory file and injects the Windows administrator password via the `-e` flag, keeping the secret out of the repository. Because `pywinrm[credssp]` is bundled in the image, WinRM connections work without any additional pip install steps. + +--- + +### Example 2: Linux connection via SSH + +This example covers both playbook and ad-hoc command execution against Linux targets over SSH. + +**Inventory (`inventory.yml`):** + +```yaml +all: + hosts: + web-01.example.com: + web-02.example.com: + vars: + ansible_connection: ssh + ansible_user: ubuntu + ansible_ssh_private_key_file: /tmp/ssh_key +``` + +**Playbook (`ping.yml`):** + +```yaml +--- +- name: Verify Linux host connectivity + hosts: all + tasks: + - name: Test SSH connection + ansible.builtin.ping: +``` + +**Workflow (`.github/workflows/linux-check.yml`):** + +```yaml +name: Linux Connectivity Check + +on: + push: + branches: [main] + workflow_dispatch: + +jobs: + ssh-ping: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install SSH key + run: | + mkdir -p /tmp + echo "${{ secrets.SSH_PRIVATE_KEY }}" > /tmp/ssh_key + chmod 600 /tmp/ssh_key + + - name: Run playbook + uses: eftechcombr/ansible-cli-github-action@master + with: + command: > + ansible-playbook ping.yml + -i inventory.yml + + - name: Ad-hoc ping test + uses: eftechcombr/ansible-cli-github-action@master + with: + command: ansible all -i inventory.yml -m ping +``` + +The first step writes the SSH private key to disk (sourced from a GitHub secret), then sets restrictive permissions so that Ansible's SSH client accepts it. The playbook step executes `ansible-playbook` against all hosts, and the ad-hoc step demonstrates how to run a single module directly with `ansible ... -m ping`. + +--- + +### Example 3: Connection via GitHub Actions self-hosted runner + +A self-hosted runner is a machine you deploy and manage yourself to run GitHub Actions workflows. It connects to GitHub and picks up jobs intended for its runner group. Self-hosted runners are useful when you need access to internal networks, on-premises infrastructure, or resources not exposed to the public internet. For more details, see the [GitHub documentation on self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners). + +When a job targets a self-hosted runner, the `eftechcombr/ansible-cli-github-action` container runs directly on that machine. Because this action is Docker-based, the runner only needs Docker installed -- it does not need Ansible or Python installed on the host itself. The action's image provides everything required. + +Use a self-hosted runner label in the `runs-on` field to target your runner fleet: + +```yaml +runs-on: [self-hosted, linux, production] +``` + +**Inventory (`inventory.yml`):** + +```yaml +all: + hosts: + db-primary.internal.example.com: + db-replica.internal.example.com: + vars: + ansible_connection: ssh + ansible_user: admin + ansible_ssh_private_key_file: /etc/runner/keys/ansible_rsa +``` + +**Playbook (`health-check.yml`):** + +```yaml +--- +- name: Database infrastructure health check + hosts: all + tasks: + - name: Ensure PostgreSQL is accepting connections + ansible.builtin.wait_for: + port: 5432 + host: "{{ inventory_hostname }}" + timeout: 10 + + - name: Collect uptime + ansible.builtin.shell: uptime + register: result + + - name: Report uptime + ansible.builtin.debug: + msg: "{{ inventory_hostname }} uptime: {{ result.stdout }}" +``` + +**Workflow (`.github/workflows/internal-health.yml`):** + +```yaml +name: Internal Infrastructure Health Check + +on: + schedule: + - cron: "*/15 * * * *" + workflow_dispatch: + +jobs: + health-check: + runs-on: [self-hosted, linux, production] + steps: + - uses: actions/checkout@v4 + + - name: Run health check playbook against internal hosts + uses: eftechcombr/ansible-cli-github-action@master + with: + command: > + ansible-playbook health-check.yml + -i inventory.yml +``` + +Because the workflow runs on a self-hosted runner inside the internal network, it can resolve `db-primary.internal.example.com` and `db-replica.internal.example.com` -- hosts that would not be reachable from GitHub-hosted runners. The action's Docker image supplies Ansible and all dependencies, so no additional setup is needed on the runner host. From 4e9eb38b1290ba56a74c25e6e5ab65e4112b5d17 Mon Sep 17 00:00:00 2001 From: Eduardo Fraga Date: Wed, 29 Jul 2026 13:30:59 -0300 Subject: [PATCH 4/4] docs: add Windows, Linux, and self-hosted runner examples to README --- README.md | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 86840f5..78f3f7d 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,190 @@ You can also execute standard Linux commands as the base image includes a shell **Required** Command to execute. Default `"ansible-playbook"`. -## Example usage +## Examples +### 1. Windows connection via WinRM + +Run a playbook against a Windows target over WinRM. The `pywinrm[credssp]` package is pre-installed in the action's Docker image. + +**Inventory (`inventory.ini`):** +```ini +[windows] +windows-server-01.example.com + +[windows:vars] +ansible_connection=winrm +ansible_winrm_transport=ntlm +ansible_user=Administrator +ansible_password={{ windows_admin_password }} +ansible_winrm_server_cert_validation=ignore +``` + +**Playbook (`win-ping.yml`):** ```yaml -uses: eftechcombr/ansible-cli-github-action@latest -with: - command: "ansible-playbook main.yml" +--- +- name: Verify Windows host connectivity + hosts: windows + tasks: + - name: Test WinRM connection + ansible.windows.win_ping: ``` +**Workflow (`.github/workflows/windows-check.yml`):** +```yaml +name: Windows Connectivity Check + +on: + schedule: + - cron: "0 6 * * *" + workflow_dispatch: + +jobs: + winrm-ping: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run WinRM ping playbook + uses: eftechcombr/ansible-cli-github-action@master + with: + command: > + ansible-playbook win-ping.yml + -i inventory.ini + -e windows_admin_password=${{ secrets.WINDOWS_ADMIN_PASSWORD }} +``` + +--- + +### 2. Linux connection via SSH + +Connect to Linux targets over SSH using a playbook or ad-hoc commands. + +**Inventory (`inventory.yml`):** +```yaml +all: + hosts: + web-01.example.com: + web-02.example.com: + vars: + ansible_connection: ssh + ansible_user: ubuntu + ansible_ssh_private_key_file: /tmp/ssh_key +``` + +**Playbook (`ping.yml`):** +```yaml +--- +- name: Verify Linux host connectivity + hosts: all + tasks: + - name: Test SSH connection + ansible.builtin.ping: +``` + +**Workflow (`.github/workflows/linux-check.yml`):** +```yaml +name: Linux Connectivity Check + +on: + push: + branches: [main] + workflow_dispatch: + +jobs: + ssh-ping: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install SSH key + run: | + mkdir -p /tmp + echo "${{ secrets.SSH_PRIVATE_KEY }}" > /tmp/ssh_key + chmod 600 /tmp/ssh_key + + - name: Run playbook + uses: eftechcombr/ansible-cli-github-action@master + with: + command: > + ansible-playbook ping.yml + -i inventory.yml + + - name: Ad-hoc ping test + uses: eftechcombr/ansible-cli-github-action@master + with: + command: ansible all -i inventory.yml -m ping +``` + +--- + +### 3. Connection via GitHub Actions self-hosted runner + +A self-hosted runner is a machine you deploy and manage yourself to run GitHub Actions workflows. Use one when you need access to internal networks or resources not exposed to the public internet. Because this action is Docker-based, the runner only needs Docker installed -- not Ansible or Python. + +Target your runner with a label in `runs-on`: +```yaml +runs-on: [self-hosted, linux, production] +``` + +**Inventory (`inventory.yml`):** +```yaml +all: + hosts: + db-primary.internal.example.com: + db-replica.internal.example.com: + vars: + ansible_connection: ssh + ansible_user: admin + ansible_ssh_private_key_file: /etc/runner/keys/ansible_rsa +``` + +**Playbook (`health-check.yml`):** +```yaml +--- +- name: Database infrastructure health check + hosts: all + tasks: + - name: Ensure PostgreSQL is accepting connections + ansible.builtin.wait_for: + port: 5432 + host: "{{ inventory_hostname }}" + timeout: 10 + + - name: Collect uptime + ansible.builtin.shell: uptime + register: result + + - name: Report uptime + ansible.builtin.debug: + msg: "{{ inventory_hostname }} uptime: {{ result.stdout }}" +``` + +**Workflow (`.github/workflows/internal-health.yml`):** +```yaml +name: Internal Infrastructure Health Check + +on: + schedule: + - cron: "*/15 * * * *" + workflow_dispatch: + +jobs: + health-check: + runs-on: [self-hosted, linux, production] + steps: + - uses: actions/checkout@v4 + + - name: Run health check playbook against internal hosts + uses: eftechcombr/ansible-cli-github-action@master + with: + command: > + ansible-playbook health-check.yml + -i inventory.yml +``` + +Because the workflow runs on a self-hosted runner inside the internal network, it can resolve `db-primary.internal.example.com` -- hosts that would not be reachable from GitHub-hosted runners. The action's Docker image supplies Ansible and all dependencies, so no additional setup is needed on the runner host. + ## Testing Run the smoke test suite locally to verify the Docker image builds and all Ansible tools work correctly: