Skip to content

Code refactor; adds more tests#19

Open
kenorb wants to merge 87 commits intomasterfrom
dev
Open

Code refactor; adds more tests#19
kenorb wants to merge 87 commits intomasterfrom
dev

Conversation

@kenorb
Copy link
Member

@kenorb kenorb commented May 16, 2025

Summary by Sourcery

Refactor documentation, CI/CD pipelines, testing infrastructure, and role metadata to streamline development, enhance linting, and broaden platform support.

Enhancements:

  • Expand supported platforms and refine role metadata, dependencies, and default settings for greater stability and clarity.

CI:

  • Upgrade pre-commit hooks and GitHub workflows with additional linters, dynamic callbacks, report generation, and reviewdog integration.
  • Switch to the built-in Ansible callback plugin with YAML formatting across CI and local configs.

Documentation:

  • Overhaul README with badges, requirements, installation instructions, role variables, and testing guides.

Tests:

  • Consolidate Molecule scenarios with standardized callbacks and result formats, and introduce a Docker-based test playbook and inventory for multi-OS validation.

Chores:

  • Normalize Jinja2 template whitespace and update .ansible.cfg, .yamllint, and .markdownlint configurations to align with project standards.

Summary by CodeRabbit

  • New Features

    • Docker-based multi-platform test harness and additional Molecule scenarios.
    • Automated dependency updates enabled.
  • Bug Fixes

    • Increased various timeouts and wait periods for more reliable runs.
  • Documentation

    • Expanded README with requirements, install, variables, and testing guidance.
    • Added contributor guidelines and review standards.
  • Chores

    • Upgraded and reorganized linters, pre-commit hooks, and CI workflows.

✏️ Tip: You can customize this high-level summary in your review settings.

kenorb and others added 30 commits September 2, 2024 21:46
@kenorb kenorb changed the title Code refactor (@coderabbigai) Code refactor (@coderabbitai) May 17, 2025
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @kenorb - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (2)
.github/copilot-instructions.md (1)

83-86: ⚠️ Potential issue

Incomplete Testing Approach
The “Testing Approach” section ends abruptly and lacks detail on actual test steps (e.g., idempotency checks, lint validation, Molecule commands). Please complete this section before merging.

.pre-commit-config.yaml (1)

49-56: 🛠️ Refactor suggestion

Reorder hooks to maintain lexicographical order
The jumanjihouse/pre-commit-hooks entry should precede pre-commit/pre-commit-hooks to comply with the project’s sorting rule.

-  - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v5.0.0
+  - repo: https://github.com/jumanjihouse/pre-commit-hooks
+    rev: 3.0.0
     hooks:
       - id: forbid-binary
       - id: git-check     # Configure in .gitattributes
       - id: require-ascii
       - id: script-must-have-extension

+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v5.0.0
+    hooks:
+      - id: check-added-large-files
+      - id: check-byte-order-marker
+      - id: check-case-conflict
+      - id: check-executables-have-shebangs
+      - id: check-merge-conflict
+      - id: check-yaml
+      - id: end-of-file-fixer
+      - id: trailing-whitespace
♻️ Duplicate comments (2)
templates/4/ea.ini.j2 (1)

2-4: Confirm handling of template whitespace
The removal of Jinja2 whitespace control hyphens (-) in the loop disables trimming around the block, which may introduce extra newlines or spaces in the rendered ea.ini file. Ensure that the MetaTrader platform correctly parses the resulting format.

templates/5/tester.ini.j2 (1)

5-10: Confirm whitespace control changes and normalize indentation
As in other templates, the whitespace-trimming hyphens have been removed, disabling block trimming—verify the rendered output is still valid for the target system. Additionally, the Jinja2 tags contain inconsistent inner spacing; consider normalizing them (e.g., {% for ... %} without extra spaces) to improve readability and satisfy j2lint.

🧹 Nitpick comments (30)
molecule/requirements.txt (1)

3-5: Pinning pipenv version for reproducibility

Currently pipenv has no version constraint, which may lead to untested upstream changes. Consider pinning to a known working release:

- pipenv
+ pipenv>=2023.9.26
tasks/main.yml (1)

119-126: Consider parameterizing timeout values

While increasing the wait_for timeout to 120s addresses longer startup times, embedding literal values reduces flexibility. Expose a variable (e.g., mt_runner_log_wait_timeout) so users can adjust this without modifying the role:

-        timeout: 120
+        timeout: "{{ mt_runner_log_wait_timeout }}"

Then define mt_runner_log_wait_timeout in defaults/main.yml with a default of 120.

templates/4/tester.ini.j2 (2)

5-7: Review whitespace control removal

Removing the trim modifiers (-{%/-%}) reintroduces blank lines around the loop, which may affect the rendered INI format. If unwanted empty lines appear, consider enabling Jinja2’s trim_blocks or lstrip_blocks globally or per-template:

#jinja2: trim_blocks:True, lstrip_blocks:True

6-6: Use Jinja2 default filter for clarity

Instead of (value or ''), the default filter is more idiomatic:

{{ key }}={{ value|default('') }}
.github/dependabot.yml (1)

9-12: Sort mapping keys lexicographically
Under the updates rule, the keys should follow alphabetical order (directory, package-ecosystem, schedule) to maintain consistency across YAML manifests.

molecule/default/converge.yml (1)

4-7: Align play mapping keys alphabetically
Within the play definition, reorder the fields to follow alphabetical order (gather_facts, hosts, name, roles, vars) so they adhere to the repository’s YAML guidelines.

molecule/default/molecule.yml (1)

20-22: Reorder callback default options alphabetically
In config_options.defaults, alphabetical ordering would be:

remote_tmp:
result_format:
stdout_callback:

Reordering these makes key discovery and maintenance easier.

molecule/mt4/molecule.yml (1)

23-25: Lexicographically order defaults keys
For consistency, consider sorting the keys under config_options.defaults alphabetically:

- stdout_callback: ansible.builtin.default
- result_format: yaml
- remote_tmp: /tmp/.ansible-tmp-$${USER}
+ remote_tmp: /tmp/.ansible-tmp-$${USER}
+ result_format: yaml
+ stdout_callback: ansible.builtin.default
tests/inventory/docker-containers.yml (1)

6-29: Extract common host variables to group_vars
The ansible_connection and ansible_python_interpreter settings are duplicated across most hosts. Consider defining them once under a vars: section in the docker_containers group to DRY up the inventory, then override only the NixOS interpreter path:

   docker_containers:
-    hosts:
+    vars:
+      ansible_connection: docker
+      ansible_python_interpreter: /usr/bin/python3
+    hosts:
       mt-runner-on-ubuntu-latest:
         ansible_connection: docker
         ansible_host: mt-runner-on-ubuntu-latest
         ansible_python_interpreter: /usr/bin/python3
@@
       mt-runner-on-nixos-latest:
         ansible_connection: docker
         ansible_host: mt-runner-on-nixos-latest
-        ansible_python_interpreter: /nix/var/nix/profiles/default/bin/python3
+        ansible_python_interpreter: /nix/var/nix/profiles/default/bin/python3

This centralizes defaults and reduces repetition.

molecule/mt5-ea/molecule.yml (1)

23-25: Lexicographically order defaults keys
For consistency, sort the keys under config_options.defaults alphabetically:

- stdout_callback: ansible.builtin.default
- result_format: yaml
- remote_tmp: /tmp/.ansible-tmp-$${USER}
+ remote_tmp: /tmp/.ansible-tmp-$${USER}
+ result_format: yaml
+ stdout_callback: ansible.builtin.default
.github/workflows/reviewdog.yml (1)

5-8: Consider adding manual trigger support
Optionally include workflow_dispatch under on: to allow manual runs of this workflow:

on:
  pull_request:
  push:
+ workflow_dispatch:
requirements.yml (1)

5-10: Consider pinning versions for all collections
Currently only community.general is version-constrained. To avoid unexpected breaking changes when new major versions are released, consider adding version constraints for the other collections (community.docker, community.windows, ansible.windows). For example:

- name: community.docker
  version: ">=5.0.0,<6.0.0"
defaults/main.yml (2)

29-30: Use lookup and no_log for environment-sourced credentials
While ansible_facts.env works, the recommended pattern is:

Login: "{{ lookup('env','MT_RUNNER_MT4_LOGIN') | default('12345') }}"

And in your playbook/task using these vars, set no_log: true to avoid exposing secrets in logs.


35-35: Explicitly define ProxyPassword value
An empty value without quotes will be parsed as null. If you intend an empty string, use:

ProxyPassword: ""

Also consider adding # pragma: allowlist secret for consistency.

.github/workflows/test.yml (2)

24-27: Simplify checkout path usage
You override the default clone directory with path: ${{ github.repository }} and then adjust working-directory. Unless you need a nested layout, consider removing path: so all steps can use the repo root without working-directory.


64-66: Validate debug condition for tmate
The if: ${{ failure() && runner.debug == '1' }} check depends on runner.debug being exactly '1'. Review the Actions docs to confirm that debug mode sets runner.debug to '1' (not 'true'), or update the condition accordingly.

README.md (4)

43-48: Grammar: add missing article in Docker section header.

Line reads “Steps to test role on Docker containers.” Consider changing to “Steps to test the role on Docker containers.”


51-55: Markdown formatting: unindent fenced code block under list.

The fenced block under “1. Install the current role…” is indented, which may break some renderers. For consistency, dedent the triple backticks to the list level:

-    ```shell
+   ```shell
     ansible-galaxy install -r requirements.yml
     jinja2 requirements-local.yml.j2 -D "pwd=$PWD" -o requirements-local.yml
     ansible-galaxy install -r requirements-local.yml
-    ```
+   ```

57-61: Grammar: include article for “symbolic link”.

Change “using symbolic link” to “using a symbolic link” for grammatical correctness:

-Alternatively, for development purposes, you can consider using symbolic link, e.g.
+Alternatively, for development purposes, you can consider using a symbolic link, e.g.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~57-~57: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...rposes, you can consider using symbolic link, e.g. ```shell ln -vs "$PWD" ~...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)


70-73: Grammar: enhance clarity in Molecule section.

Consider rewording to “To test this role using Molecule, run:” for consistency and clarity.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~72-~72: Possible missing article found.
Context: ...ml ### Molecule To test using Molecule, run: shell molecule test ``` ## L...

(AI_HYDRA_LEO_MISSING_A)

.github/workflows/molecule.yml (1)

51-55: Consider removing sudo for chmod.

On GitHub runners, file permissions can typically be changed by the runner user without sudo. You can simplify to:

- run: sudo chmod 644 molecule-${{ matrix.scenario }}-report.html
+ run: chmod 644 molecule-${{ matrix.scenario }}-report.html
tests/playbooks/docker-containers.yml (1)

35-65: Optional refactor: consolidate Python installation.

You have three separate raw+apt tasks per OS. Consider merging into a single task using the package module with a conditional map to reduce repetition:

- name: Install Python 3 and pip
  ansible.builtin.package:
    name:
      - python3
      - python3-pip
      - python3-setuptools
    state: present
  when: >
    container_image is search("ubuntu") or
    container_image is search("debian") or
    container_image is search("alpine") or
    container_image is search("nixos")
.github/prompts/code-review.prompt.md (2)

3-3: Grammar: add missing article “the”.

Change “Your goal is to review Ansible role code” to “Your goal is to review the Ansible role code”.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~3-~3: You might be missing the article “the” here.
Context: ...view Guidelines Your goal is to review Ansible role code to ensure it meets high-quali...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


19-19: Improve variety in directive verbs.

Lines 17–19 all start with “Ensure”; consider replacing one with “Verify” or “Check” to enhance readability.

🧰 Tools
🪛 LanguageTool

[style] ~19-~19: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...aml](../../.markdownlint.yaml) rules. - Ensure Ansible playbooks and roles pass `ansib...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

.github/copilot-instructions.md (4)

14-22: Clarify secure configuration handling
Consider specifying patterns for secure variable handling (e.g., using Ansible Vault or lookup('env', ...)) and explicitly advising against default or hardcoded credentials.


23-31: Clarify intended audience for response guidelines
These “General Approach” instructions appear to guide Copilot’s output formatting rather than contributor behavior. You may want to prefix the section to clarify its audience or move it to a dedicated file for AI assistant configuration.


40-46: Explicit ansible-lint rule enforcement
Good inclusion of the fqcn[keyword] rule; for completeness, consider adding other critical rules such as no-bare-variables or error-noshell.


58-74: Project-specific environment notes
The platform-specific package manager instructions and Codespaces references are clear. Consider specifying the exact Nix channel or version to avoid ambiguity for Nix users.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~68-~68: A determiner appears to be missing. Consider inserting it.
Context: ...lightweight Nix environments Notes: - Project utilizes Codespaces with config file at...

(AI_EN_LECTOR_MISSING_DETERMINER)

.pre-commit-config.yaml (2)

37-47: Maintain built-in hook coverage
The selection of built-in pre-commit-hooks is comprehensive. Consider adding check-docstring-first-line for Python files to enforce docstring conventions.


62-66: Enhance detect-secrets configuration
Consider adding a secrets_baseline or excluding known false positives to reduce noise in CI and speed up scans.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c9bd1a and 69fd2f1.

⛔ Files ignored due to path filters (12)
  • .ansible-lint is excluded by none and included by none
  • .ansible.cfg is excluded by none and included by none
  • .devcontainer/devcontainer.json is excluded by none and included by none
  • .devcontainer/requirements.txt is excluded by none and included by none
  • .github/actionlint-matcher.json is excluded by none and included by none
  • .gitignore is excluded by none and included by none
  • .vscode/tasks.json is excluded by none and included by none
  • .yamllint is excluded by none and included by none
  • LICENSE is excluded by none and included by none
  • Pipfile is excluded by none and included by none
  • Pipfile.lock is excluded by !**/*.lock and included by none
  • ansible.cfg is excluded by none and included by none
📒 Files selected for processing (30)
  • .coderabbit.yaml (1 hunks)
  • .github/copilot-instructions.md (1 hunks)
  • .github/dependabot.yml (1 hunks)
  • .github/prompts/code-review.prompt.md (1 hunks)
  • .github/workflows/check.yml (1 hunks)
  • .github/workflows/molecule.yml (2 hunks)
  • .github/workflows/reviewdog.yml (1 hunks)
  • .github/workflows/test.yml (1 hunks)
  • .markdownlint.yaml (1 hunks)
  • .pre-commit-config.yaml (2 hunks)
  • README.md (1 hunks)
  • defaults/main.yml (2 hunks)
  • meta/main.yml (2 hunks)
  • molecule/default/converge.yml (1 hunks)
  • molecule/default/molecule.yml (2 hunks)
  • molecule/default/requirements.yml (0 hunks)
  • molecule/mt4/molecule.yml (2 hunks)
  • molecule/mt4/requirements.yml (0 hunks)
  • molecule/mt5-ea/molecule.yml (2 hunks)
  • molecule/mt5-ea/requirements.yml (0 hunks)
  • molecule/requirements.txt (1 hunks)
  • requirements-local.yml.j2 (1 hunks)
  • requirements.yml (1 hunks)
  • tasks/main.yml (1 hunks)
  • templates/4/ea.ini.j2 (1 hunks)
  • templates/4/tester.ini.j2 (1 hunks)
  • templates/5/tester.ini.j2 (1 hunks)
  • tests/inventory/docker-containers.yml (1 hunks)
  • tests/playbooks/docker-containers.yml (1 hunks)
  • vars/main.yml (1 hunks)
💤 Files with no reviewable changes (3)
  • molecule/mt5-ea/requirements.yml
  • molecule/mt4/requirements.yml
  • molecule/default/requirements.yml
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.yml`: - For Ansible files, review the YAML code against the Ansible best practices and point out any mismatches. - Ensure keys are in lexicographical order when possible.

**/*.yml: - For Ansible files, review the YAML code against the Ansible best practices and point out any mismatches.

  • Ensure keys are in lexicographical order when possible.
  • vars/main.yml
  • molecule/default/converge.yml
  • molecule/default/molecule.yml
  • tasks/main.yml
  • molecule/mt5-ea/molecule.yml
  • tests/inventory/docker-containers.yml
  • molecule/mt4/molecule.yml
  • requirements.yml
  • defaults/main.yml
  • meta/main.yml
  • tests/playbooks/docker-containers.yml
🪛 GitHub Actions: Test
requirements.yml

[error] 1-1: Ansible-galaxy role 'ea31337.wine' failed to install due to git clone error: 'git+https' is not a valid git command. Command exited with code 128.

🪛 GitHub Actions: Check
requirements.yml

[error] 1-1: Ansible-lint failed due to role installation error: 'git clone git+https://github.com/EA31337/ansible-role-wine.git' failed with 'git: remote-git+https is not a git command' causing exit code 128.

🪛 LanguageTool
README.md

[uncategorized] ~57-~57: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...rposes, you can consider using symbolic link, e.g. ```shell ln -vs "$PWD" ~...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)


[uncategorized] ~72-~72: Possible missing article found.
Context: ...ml ### Molecule To test using Molecule, run: shell molecule test ``` ## L...

(AI_HYDRA_LEO_MISSING_A)

.github/prompts/code-review.prompt.md

[uncategorized] ~3-~3: You might be missing the article “the” here.
Context: ...view Guidelines Your goal is to review Ansible role code to ensure it meets high-quali...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[style] ~19-~19: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...aml](../../.markdownlint.yaml) rules. - Ensure Ansible playbooks and roles pass `ansib...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

.github/copilot-instructions.md

[uncategorized] ~68-~68: A determiner appears to be missing. Consider inserting it.
Context: ...lightweight Nix environments Notes: - Project utilizes Codespaces with config file at...

(AI_EN_LECTOR_MISSING_DETERMINER)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test (mt4)
🔇 Additional comments (58)
vars/main.yml (1)

2-2: Added file-level comment for clarity

Including a descriptive comment at the top of vars/main.yml improves maintainability by clarifying this file’s purpose within the role’s structure.

molecule/requirements.txt (1)

7-7:

Details

❓ Verification inconclusive

Verify that requests==2.31.0 is compatible and secure

Ensure this version aligns with other project dependencies and has no known security vulnerabilities in the context of Molecule testing.

Run:


🏁 Script executed:

#!/bin/bash
pip install pip-audit
pip-audit

Length of output: 4729


🏁 Script executed:

#!/bin/bash
# Install pip-audit if not already available and audit the Molecule requirements file
pip install pip-audit
python3 -m pip_audit -r molecule/requirements.txt

Length of output: 4377


Action Required: Manual Verification of requests==2.31.0

The automated audit couldn’t run in this environment (missing python3-venv). Please confirm that pinning requests==2.31.0 in molecule/requirements.txt:

  • Has no known security vulnerabilities
  • Is compatible with the other dependencies used for Molecule testing

To verify locally:

  1. Install a virtual-env backend (e.g. sudo apt install python3-venv).
  2. Run:
    python3 -m pip install pip-audit
    python3 -m pip_audit -r molecule/requirements.txt
  3. Address any flagged issues or upgrade/downgrade accordingly.
.github/workflows/check.yml (1)

19-19: Approved pre-commit Action version bump

Updating to pre-commit/action@v3.0.1 ensures you receive the latest fixes.

.markdownlint.yaml (1)

1-14: Configuration aligns with standards
The markdownlint rules are clear, and the ignore list and rule overrides are correctly specified.

molecule/mt4/molecule.yml (3)

6-7: Enable lint checks in Molecule scenario
Uncommenting yamllint and ansible-lint ensures code style checks run during the Molecule test lifecycle.


19-21: Standardize Ansible callback plugin and output format
Switching to the built-in ansible.builtin.default callback and YAML-formatted results aligns with the project CI conventions.


27-28: Add wine_release group variable
Introducing wine_release: stable in group_vars.all provides clarity on the Wine distribution version used for testing.

molecule/mt5-ea/molecule.yml (3)

6-7: Enable lint checks in Molecule scenario
Uncommenting yamllint and ansible-lint ensures code style checks run during the Molecule test lifecycle.


19-21: Standardize Ansible callback plugin and output format
Switching to the built-in ansible.builtin.default callback and YAML-formatted results aligns with other scenarios and CI conventions.


27-28: Add wine_release group variable
Defining wine_release: stable in group_vars.all clarifies the Wine release channel used across the test inventory.

.github/workflows/reviewdog.yml (1)

1-6: Approve reviewdog workflow setup
The workflow correctly triggers on pull_request and push and integrates actionlint with a custom problem matcher.

requirements.yml (1)

12-18: Verify role version alignment
The role ea31337.metatrader is pinned at v1.0.3 here. Please ensure this matches exactly the version in meta/main.yml to prevent drift.

defaults/main.yml (2)

25-25: Great: mark sensitive defaults as secrets
Adding # pragma: allowlist secret to FTPPassword will prevent false positives in your secret-scanning tools.


147-147: Confirm extended timeout meets CI expectations
The default timeout was increased from 120 to 600 seconds. Please verify this aligns with your Molecule/CI job timeouts so tests don’t hang unexpectedly.

requirements-local.yml.j2 (2)

1-4: Usage comments are clear and helpful
The instructions for rendering and installing the local requirements file are concise and correct.


6-11: Local role source template looks solid
The file://{{ pwd }} URI with a pin to HEAD is appropriate for local testing. Key order (name, scm, src, version) is alphabetical.

.github/workflows/test.yml (2)

33-36: Verify Jinja2 CLI availability in test environment
The workflow invokes jinja2 to render the template—ensure your .devcontainer/requirements.txt or equivalent includes a Jinja2 CLI package (e.g., jinja2-cli) so this step won’t fail.


43-45: Local requirements installation is well-structured
Rendering the template and cleaning up requirements-local.yml in one step is efficient and clear.

meta/main.yml (6)

3-7: Ensure dependency version stays in sync
The ea31337.metatrader role version is pinned to v1.0.3 here. Please verify this matches the version in requirements.yml to prevent inconsistent role installations.


9-10: Author and company metadata looks good
Changing author to kenorb and adding a company field is valid per Ansible Galaxy spec.


15-26: Galaxy tags are alphabetically sorted
Your expansion of galaxy_tags follows lexicographical order, which helps maintain clarity and consistency.


27-27: SPDX-compliant license identifier
Using GPL-3.0-or-later is correct and aligns with best practices for licensing.


33-37: Debian platform versions are ordered
You’ve explicitly listed Debian versions in lexicographical order, including older releases—good attention to detail.


41-45: Ubuntu platform versions are ordered
The Ubuntu versions are similarly sorted and comprehensive.

.coderabbit.yaml (1)

1-51: Configuration aligns with schema and project standards.

The new .coderabbit.yaml strictly follows the defined CodeRabbit configuration schema, enables the intended features (auto-review, path filters, linting tools), and applies sensible defaults. No invalid or unexpected fields were introduced.

README.md (8)

1-4: Title and badges are clear and correctly formatted.

The header clearly names the role and includes the CodeRabbit PR Reviews and License badges with valid links.


8-19: Requirements section is comprehensive and accurate.

The list of prerequisites (Ansible, Python, root access, supported OSes) is clear and correctly formatted.


22-28: Galaxy install instructions are correct.

The “Install from Ansible Galaxy” subsection clearly shows the command needed to install the role.


30-36: GitHub install instructions are correct.

The “Install from GitHub” subsection and its code block are accurate and well-formatted.


38-42: Role Variables section is concise and links correctly.

The pointer to defaults/main.yml is valid and helps users find all default settings.


63-68: Docker service step is clear.

The instructions to ensure Docker is running and the ansible-playbook command are correct and sufficient.


74-76: Molecule test command is correct.

The code block for molecule test is accurate and well-formatted.


78-82: License section is correct.

The GPL v3 reference and link to LICENSE are clear and accurate.

.github/workflows/molecule.yml (8)

7-13: Trigger filters for pull_request are properly scoped.

The paths-ignore block excludes non-workflow changes as intended.


15-21: Trigger filters for push are properly scoped.

Mirroring paths-ignore under push ensures consistency.


24-25: Job key normalization and naming is clear.

The job identifier was changed to lowercase test and name: Test was added for readability.


37-37: Verify custom checkout path necessity.

You’re checking out under path: ${{ github.repository }}; confirm downstream steps rely on that path. If not required, consider using the default workspace location.


41-42: Conditional callback setting is correct.

The ANSIBLE_STDOUT_CALLBACK expression toggles between debug and yaml based on the debug flag as expected.


49-50: Conditional Molecule options and working directory are correct.

The use of ${{ runner.debug == '1' && '--verbose' || '' }} and removal of quoted molecule_working_dir is valid.


56-60: Verify HTML-to-Markdown conversion action.

The patrick-werner/fhir-html-validation-to-markdown action is specialized for FHIR validation; ensure it correctly converts Molecule reports or switch to a generic HTML-to-Markdown tool.


61-62: Tmate debug step gating is correct.

The condition failure() && runner.debug == '1' properly restricts tmate to failure+debug situations.

tests/playbooks/docker-containers.yml (5)

1-13: Play definitions follow Ansible best practices.

The two-play structure (Configure Docker container and Install ea31337.mt_runner role) is correct, facts gathering is appropriately managed, and become_method: su is chosen for compatibility.


14-34: Docker container setup tasks are solid.

Using community.docker modules with delegation and retries ensures robust container lifecycle management.


66-75: Variables mapping is clear.

The container_image_map and default fallback ensure that inventory hostnames map to the intended images.


79-87: Role import task is straightforward.

Using ansible.builtin.import_role for installation is appropriate and idempotent.


88-94: Post-tasks stop containers gracefully.

Stopping containers in post_tasks with failed_when: false prevents tear-down failures from blocking results.

.github/copilot-instructions.md (4)

3-11: Comprehensive expertise requirements
The list of required expertise is clear and covers all critical areas for contributors (Ansible, Python, Jinja2, Molecule, Linux distros, YAML).


32-39: Strong Ansible best practices
The idempotency reminder, indentation guidance, and standard role structure align well with community standards.


48-57: Well-defined YAML guidelines
The rules for blank lines, indentation, line length, and lexicographical ordering will help maintain consistency across YAML files.


75-82: Key variable management
Good reminder to keep defaults/main.yml, vars/main.yml, and README.md in sync when variables change.

.pre-commit-config.yaml (8)

1-3: Lexicographical order reminder
The note about keeping hooks in lexicographical order is useful. Ensure it’s updated whenever hooks are added or removed.


6-11: yamllint hook upgrade
Upgrading to v1.37.1 with explicit -c .yamllint and -s flags is appropriate for enforcing YAML standards.


12-16: ansible-lint version bump
Updating ansible-lint to v25.4.0 aligns with the latest community recommendations.


17-21: Add j2lint hook
Introducing j2lint v1.2.0 will help catch Jinja2 template errors early in the CI pipeline.


22-26: Add codespell hook
Including codespell v2.4.1 is a great choice to catch common typos across the repository.


27-31: Add gitleaks hook
Pinning gitleaks to v8.24.2 enhances secret scanning and reduces the risk of credential leaks.


32-36: Add markdownlint hook
Upgrading markdownlint-cli to v0.44.0 will bolster Markdown quality checks, especially for the newly overhauled documentation.


57-61: Add actionlint hook
Including rhysd/actionlint v1.7.7 will validate the GitHub Actions workflows themselves—excellent for preventing CI configuration errors.

@kenorb kenorb changed the title Code refactor (@coderabbitai) Code refactor May 17, 2025
@kenorb kenorb changed the title Code refactor Code refactor; adds more tests May 17, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
tests/inventory/docker-containers.yml (1)

5-29: Consider ordering hosts alphabetically.

Per coding guidelines, keys should be in lexicographical order when possible. The hosts could be reordered as: alpine-latest, debian-latest, nixos-latest, ubuntu-jammy, ubuntu-latest, ubuntu-noble.

tests/playbooks/docker-containers.yml (2)

90-91: Unused variable controller_python.

The controller_python variable is defined in Play 2 but not referenced by any task in this play. Consider removing it if not needed.

Proposed fix
 - name: Install ea31337.mt_runner role on all containers
   hosts: docker_containers
   gather_facts: true
   tags: always
-  vars:
-    controller_python: "{{ ansible_playbook_python }}"
   tasks:

2-84: Consider reordering play-level keys alphabetically.

Per coding guidelines, keys should be in lexicographical order when possible. The current order is become, become_method, gather_facts, hosts, pre_tasks, tags, vars, vars_files. Suggested order: become, become_method, gather_facts, hosts, pre_tasks, tags, vars, vars_files — actually this is mostly sorted except hosts should come before pre_tasks. Consider: become, become_method, gather_facts, hosts, pre_tasks, tags, vars, vars_files.

.github/workflows/molecule.yml (1)

53-56: Consider handling missing report file gracefully.

The chmod command will fail if the report file doesn't exist (e.g., if Molecule fails early). Consider adding a file existence check.

Proposed fix
       - if: always()
         name: Ensure report file permissions are correct
-        run: sudo chmod 644 molecule-${{ matrix.scenario }}-report.html
+        run: |
+          if [ -f molecule-${{ matrix.scenario }}-report.html ]; then
+            sudo chmod 644 molecule-${{ matrix.scenario }}-report.html
+          fi
         working-directory: ${{ github.repository }}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c08e20c and 8ee46ab.

⛔ Files ignored due to path filters (2)
  • .devcontainer/devcontainer.json is excluded by none and included by none
  • .gitignore is excluded by none and included by none
📒 Files selected for processing (5)
  • .github/workflows/molecule.yml
  • molecule/default/molecule.yml
  • molecule/default/prepare.yml
  • tests/inventory/docker-containers.yml
  • tests/playbooks/docker-containers.yml
🧰 Additional context used
📓 Path-based instructions (1)
**/*.yml

⚙️ CodeRabbit configuration file

**/*.yml: - For Ansible files, review the YAML code against the Ansible best practices and point out any mismatches.

  • Ensure keys are in lexicographical order when possible.

Files:

  • tests/inventory/docker-containers.yml
  • molecule/default/molecule.yml
  • molecule/default/prepare.yml
  • tests/playbooks/docker-containers.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Test (mt5-ea)
  • GitHub Check: Test (mt4)
  • GitHub Check: Test (default)
  • GitHub Check: Test
  • GitHub Check: Test (mt5-ea)
  • GitHub Check: Test (mt4)
  • GitHub Check: Test (default)
  • GitHub Check: Test
🔇 Additional comments (8)
molecule/default/prepare.yml (2)

2-23: LGTM!

The multi-package-manager Python installation approach correctly handles Alpine (apk), Debian/Ubuntu (apt), Fedora (dnf), and openSUSE (zypper) with proper idempotency check via command -v python3 || command -v python. The changed_when: false is appropriate since the task short-circuits when Python already exists.


25-40: LGTM!

The NixOS-specific play correctly handles the unique Nix environment by disabling sandbox mode (required for many container environments) and using nix-env for Python installation.

tests/playbooks/docker-containers.yml (1)

97-103: LGTM!

Using failed_when: false for the container cleanup step is appropriate since container state shouldn't fail the overall playbook execution during teardown.

molecule/default/molecule.yml (3)

5-11: LGTM!

Good secure defaults with ignore-certs: false and ignore-errors: false for dependency management.


27-60: LGTM!

The provisioner configuration is well-structured with appropriate settings for container-based testing. The host_key_checking: false is acceptable for ephemeral test containers, and the NixOS-specific Python interpreter path in host_vars aligns with the inventory definitions.


62-76: Test sequence structure looks intentional.

The duplicate cleanup/destroy steps (lines 66-67 and 75-76) follow Molecule best practices: the first pair ensures a clean slate before testing, and the final pair cleans up after verification.

.github/workflows/molecule.yml (2)

57-61: Verify FHIR action suitability for Molecule reports.

The patrick-werner/fhir-html-validation-to-markdown action appears designed for FHIR validation reports. Confirm it correctly parses Molecule's HTML report format, or consider a more generic HTML-to-Markdown converter.


63-64: LGTM!

The tmate debug session is appropriately gated by both failure() and runner.debug == '1', preventing accidental exposure in normal CI runs.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
lookup_plugins/decode_utf16.py (1)

16-17: Consider simplifying error message formatting.

Using repr(e) produces technical output like "ValueError('message')". For cleaner user-facing errors, consider to_native(e) or to_native(str(e)) which would yield just "message".

🔎 Proposed refactor
         except Exception as e:
-            raise AnsibleError(to_native(repr(e)))
+            raise AnsibleError(to_native(e))
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ee46ab and 8b94586.

📒 Files selected for processing (3)
  • .github/workflows/check.yml
  • .pre-commit-config.yaml
  • lookup_plugins/decode_utf16.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Pre-commit
  • GitHub Check: Test
  • GitHub Check: Test (mt5-ea)
  • GitHub Check: Test (default)
  • GitHub Check: Test (mt4)
  • GitHub Check: Test (default)
  • GitHub Check: Test (mt4)
  • GitHub Check: Test (mt5-ea)
  • GitHub Check: Test
  • GitHub Check: Pre-commit
🔇 Additional comments (5)
lookup_plugins/decode_utf16.py (1)

3-3: LGTM! Clean import consolidation.

The removal of unused imports (to_text, codecs, logging, string) and retention of only to_native correctly reflects actual usage in the error handler on line 17.

.github/workflows/check.yml (3)

10-15: LGTM: actionlint job added successfully.

The new actionlint job is well-structured and uses the standard reviewdog action for GitHub Actions workflow linting.


16-19: Create the missing actionlint matcher file or remove the reference.

This step references .github/actionlint-matcher.json, but the file does not exist in the repository. Either create the matcher file with the appropriate actionlint JSON configuration, or remove this step if the matcher is not needed. Without this file, the workflow will fail when attempting to add the problem matcher.

⛔ Skipped due to learnings
Learnt from: kenorb
Repo: EA31337/ansible-role-mt-runner PR: 19
File: .github/workflows/reviewdog.yml:16-18
Timestamp: 2025-05-29T16:24:13.111Z
Learning: When reviewing GitHub workflows, verify file existence by checking the target branch (often dev or main) rather than assuming files are missing if they're not present in the current PR branch. Users may maintain different files across different branches.

30-30: pre-commit/action v3.0.1 update is valid. The version was released on February 7, 2024, and includes an upgrade to actions/cache v4 (PR #190) along with maintenance-mode guidance.

.pre-commit-config.yaml (1)

22-30: Good additions for code quality and security.

The addition of codespell, gitleaks, and detect-secrets hooks enhances code quality and security scanning. These tools will help catch spelling errors, leaked secrets, and security vulnerabilities.

Also applies to: 73-76

Comment on lines +1 to +2
# Notes:
# - Keep the order of the hooks in lexicographical order.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

The lexicographical order guideline is violated.

The comment states hooks should be in lexicographical order, but jumanjihouse (line 60) appears after pre-commit (line 48), which violates alphabetical ordering. The correct order should be: jumanjihouse before pre-commit, psf, pycqa.

🔎 Suggested reordering

Move the jumanjihouse repository block to appear before the pre-commit repository to maintain lexicographical order:

  - repo: https://github.com/pycqa/flake8
    rev: 7.1.1
    hooks:
      - id: flake8
        args: ["--max-line-length=120"]

+  - repo: https://github.com/jumanjihouse/pre-commit-hooks
+    rev: 3.0.0
+    hooks:
+      - id: forbid-binary
+      - id: git-check     # Configure in .gitattributes
+      - id: require-ascii
+      - id: script-must-have-extension
+
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: check-added-large-files
      - id: check-byte-order-marker
      - id: check-case-conflict
      - id: check-executables-have-shebangs
      - id: check-merge-conflict
      - id: check-yaml
      - id: end-of-file-fixer
      - id: trailing-whitespace

-  - repo: https://github.com/jumanjihouse/pre-commit-hooks
-    rev: 3.0.0
-    hooks:
-      - id: forbid-binary
-      - id: git-check     # Configure in .gitattributes
-      - id: require-ascii
-      - id: script-must-have-extension
-
  - repo: https://github.com/rhysd/actionlint
    rev: v1.7.7

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In .pre-commit-config.yaml around lines 1 to 2, the hooks are not in
lexicographical order: the jumanjihouse repository block (around line 60)
appears after the pre-commit block (around line 48); move the entire
jumanjihouse repository block so it appears before the pre-commit repository
block (and before any psf/pycqa blocks) to restore alphabetical ordering,
ensuring you preserve the block's indentation and contents exactly when cutting
and pasting.

Comment on lines +6 to +10
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.37.1
hooks:
- id: yamllint
args: ["-c", ".yamllint", "-s"]
Copy link

@coderabbitai coderabbitai bot Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .pre-commit-config.yaml

Repository: EA31337/ansible-role-mt-runner

Length of output: 2364


🌐 Web query:

latest stable version yamllint 2025

💡 Result:

The latest stable yamllint release is 1.37.1 (released May 4, 2025). [1][2]

Sources:
[1] PyPI: yamllint release 1.37.1 (May 4, 2025).
[2] Fedora / package changelog showing yamllint 1.37.1 (May 4, 2025).


🌐 Web query:

latest stable version ansible-lint 2025

💡 Result:

The latest stable ansible-lint release is 25.12.2 (uploaded to PyPI on Dec 22, 2025). [1][2]

Sources:
[1] PyPI — ansible-lint release files and upload date.
[2] GitHub — ansible/ansible-lint releases.


🌐 Web query:

latest stable version markdownlint-cli 2025

💡 Result:

The latest stable release is 0.46.0 (published recently). [1][2]

Sources:

  • Package listing showing v0.46.0 as the latest. [1]
  • Project release history (shows prior v0.45.0). [2]

🌐 Web query:

latest stable version black Python formatter 2025

💡 Result:

The latest stable release of the Black formatter is 25.1.0 (released Jan 29, 2025). [1][2]

Sources:

  • PyPI listing for black (25.1.0). [1]
  • psf/black GitHub releases (25.1.0). [2]

🌐 Web query:

latest stable version flake8 2025

💡 Result:

The latest stable flake8 release in 2025 is 7.3.0 (uploaded June 20, 2025). [1][2]

Sources:
[1] PyPI flake8 project page (release files, upload date).
[2] Safety DB / project summary (lists latest version 7.3.0, June 21, 2025).


🌐 Web query:

latest stable version pre-commit-hooks 2025

💡 Result:

The latest stable release of pre-commit-hooks is v6.0.0 (released Aug 9, 2025). [1][2]

Sources:

  • PyPI pre-commit-hooks release (pre_commit_hooks 6.0.0). [1]
  • GitHub releases for pre-commit/pre-commit-hooks (v6.0.0). [2]

🌐 Web query:

latest stable version actionlint 2025

💡 Result:

Latest stable release: v1.7.8 — released Oct 11, 2025. [1]

Sources:
[1] rhysd/actionlint — Releases (GitHub).


Update multiple hook versions that are outdated.

Several hooks are using outdated versions. Update the following:

  • ansible-lint: v25.4.0 → v25.12.2
  • markdownlint-cli: v0.44.0 → v0.46.0
  • black: 24.10.0 → 25.1.0
  • flake8: 7.1.1 → 7.3.0
  • pre-commit-hooks: v5.0.0 → v6.0.0
  • actionlint: v1.7.7 → v1.7.8

yamllint at v1.37.1 is already current.

🤖 Prompt for AI Agents
In .pre-commit-config.yaml around lines 6 to 10, several hooks are pinned to
outdated versions; update the hook revisions to the specified newer versions:
set ansible-lint to v25.12.2, markdownlint-cli to v0.46.0, black to 25.1.0,
flake8 to 7.3.0, pre-commit-hooks to v6.0.0, and actionlint to v1.7.8 (leave
yamllint at v1.37.1 since it is current); modify the corresponding rev fields
for each hook entry so the repo refs point to these new versions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Fix it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
molecule/mt5-ea/molecule.yml (1)

7-11: Keys not in lexicographical order.

The role-file key should come after requirements-file to maintain alphabetical ordering.

🔎 Proposed fix
   options:
     ignore-certs: false
     ignore-errors: false
-    role-file: requirements.yml
     requirements-file: requirements.yml
+    role-file: requirements.yml

As per coding guidelines, YAML keys should be sorted alphabetically when possible.

molecule/mt4/molecule.yml (1)

7-11: Keys not in lexicographical order.

The role-file key should come after requirements-file to maintain alphabetical ordering.

🔎 Proposed fix
   options:
     ignore-certs: false
     ignore-errors: false
-    role-file: requirements.yml
     requirements-file: requirements.yml
+    role-file: requirements.yml

As per coding guidelines, YAML keys should be sorted alphabetically when possible.

tests/playbooks/docker-containers.yml (1)

82-83: Remove unused controller_python variable.

The controller_python variable is defined in this play but never referenced. It appears to be copied from the first play where it's actually used for Docker module delegation.

🔎 Proposed cleanup
- vars:
-   controller_python: "{{ ansible_playbook_python }}"
  tasks:
    - name: Installs ea31337.mt_runner role
      ansible.builtin.import_role:
        name: ea31337.mt_runner
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b94586 and 80155bd.

⛔ Files ignored due to path filters (1)
  • .devcontainer/devcontainer.json is excluded by none and included by none
📒 Files selected for processing (6)
  • meta/main.yml
  • molecule/mt4/molecule.yml
  • molecule/mt5-ea/molecule.yml
  • tests/inventory/docker-containers.yml
  • tests/playbooks/docker-containers.yml
  • vars/main.yml
🧰 Additional context used
📓 Path-based instructions (1)
**/*.yml

⚙️ CodeRabbit configuration file

**/*.yml: - For Ansible files, review the YAML code against the Ansible best practices and point out any mismatches.

  • Ensure keys are in lexicographical order when possible.

Files:

  • vars/main.yml
  • molecule/mt5-ea/molecule.yml
  • molecule/mt4/molecule.yml
  • meta/main.yml
  • tests/inventory/docker-containers.yml
  • tests/playbooks/docker-containers.yml
🔇 Additional comments (5)
vars/main.yml (1)

1-8: LGTM! Clean variable structure with proper documentation.

The header comments and sorted keys align with the coding guidelines. The structure is clear and maintainable.

tests/inventory/docker-containers.yml (1)

1-30: LGTM! Inventory structure is correct and well-organized.

The previous ansible_host issue has been addressed. All keys are properly sorted alphabetically, and the Docker connection configuration is appropriate for container-based testing.

molecule/mt5-ea/molecule.yml (1)

12-54: Good enhancements to the Molecule configuration.

The enabled linting steps, callback configuration changes to built-in Ansible defaults, and additional provisioner options improve the testing infrastructure. Key ordering is correct throughout these sections.

molecule/mt4/molecule.yml (1)

12-58: Good enhancements to the Molecule configuration.

The enabled linting steps, callback configuration changes, and playbook references improve the testing infrastructure. Key ordering is correct throughout these sections.

meta/main.yml (1)

1-50: LGTM! Well-structured metadata with proper organization.

The updates enhance the role metadata with:

  • Clear version pinning for dependencies (v1.0.3)
  • Expanded platform support with specific version codenames
  • Comprehensive galaxy tags for better discoverability
  • Proper SPDX license identifier

All keys are correctly sorted alphabetically throughout the file.

Comment on lines +4 to +8
become: >-
{{ (connection_user is defined and connection_user != 'root')
or (ansible_user_id is defined and ansible_user_id != 'root')
or (lookup('env', 'UID') | int != 0)
}}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Verify become logic: lookup('env', 'UID') reads controller environment, not target.

The lookup('env', 'UID') function executes on the Ansible controller, not the target host. If the controller runs as a non-root user, this will set become: true even when connecting to a container as root, which may not be the intended behavior. Consider removing the UID lookup or replacing it with a check that evaluates on the target after facts are gathered.

🔎 Suggested approach

Option 1: Remove the UID lookup and rely only on ansible_user_id (checked after gathering facts in a separate task):

  become: >-
    {{ (connection_user is defined and connection_user != 'root')
-   or (ansible_user_id is defined and ansible_user_id != 'root')
-   or (lookup('env', 'UID') | int != 0)
+   or (ansible_user_id is defined and ansible_user_id != 'root')
    }}

Option 2: Set become conditionally in a post-fact-gathering task rather than at play level.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In tests/playbooks/docker-containers.yml around lines 4 to 8, the become
condition uses lookup('env','UID') which reads the controller UID (not the
remote/container) and can incorrectly force become; remove the UID lookup and
either (a) rely solely on ansible_user_id (evaluated on the target after facts
are gathered) or (b) remove become from the play level and set become
conditionally in a follow-up task after gathering facts (e.g., use a task that
registers ansible_user_id and sets become when that value != 'root').

Comment on lines +41 to +51
- name: Install Python 3 on Alpine
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apk update && apk add --no-cache python3 py3-pip)
changed_when: false
when: container_image is search("alpine")

- name: Install Python 3 on Ubuntu/Debian
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
changed_when: false
when: container_image is search("ubuntu") or container_image is search("debian")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

changed_when: false misrepresents actual package installation changes.

The raw tasks may install packages (python3, py3-pip) when they don't exist, but changed_when: false suppresses this in the output. This masks actual changes and affects idempotency reporting accuracy.

🔎 Suggested fix

Remove changed_when: false or implement proper change detection:

    - name: Install Python 3 on Alpine
      ansible.builtin.raw: |
        test -e "{{ ansible_python_interpreter }}" || (apk update && apk add --no-cache python3 py3-pip)
-     changed_when: false
      when: container_image is search("alpine")

    - name: Install Python 3 on Ubuntu/Debian
      ansible.builtin.raw: |
        test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
-     changed_when: false
      when: container_image is search("ubuntu") or container_image is search("debian")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Install Python 3 on Alpine
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apk update && apk add --no-cache python3 py3-pip)
changed_when: false
when: container_image is search("alpine")
- name: Install Python 3 on Ubuntu/Debian
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
changed_when: false
when: container_image is search("ubuntu") or container_image is search("debian")
- name: Install Python 3 on Alpine
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apk update && apk add --no-cache python3 py3-pip)
when: container_image is search("alpine")
- name: Install Python 3 on Ubuntu/Debian
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
when: container_image is search("ubuntu") or container_image is search("debian")
🤖 Prompt for AI Agents
In tests/playbooks/docker-containers.yml around lines 41 to 51, the two raw
tasks that install Python on Alpine and Ubuntu/Debian set changed_when: false
which hides real package installation changes; remove changed_when: false (or
replace it with a proper register + changed_when that evaluates whether
installation was performed) so Ansible reports changes accurately—specifically,
either delete the changed_when lines so the task result reflects modifications,
or capture the command output/rc in a variable and set changed_when: "output
indicates packages were installed or rc != 0" (i.e., mark changed only when
installation actually occurred).

Comment on lines +41 to +76
- name: Install Python 3 on Alpine
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apk update && apk add --no-cache python3 py3-pip)
changed_when: false
when: container_image is search("alpine")

- name: Install Python 3 on Ubuntu/Debian
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
changed_when: false
when: container_image is search("ubuntu") or container_image is search("debian")

- name: Gather facts
ansible.builtin.setup:

- name: Install Python packages for Ubuntu/Debian
ansible.builtin.apt:
name:
- python3
- python3-pip
- python3-setuptools
state: present
update_cache: true
when: container_image is search("ubuntu") or container_image is search("debian")

tags: always
vars:
controller_python: "{{ ansible_playbook_python }}"
container_image_map:
mt-runner-on-alpine-latest: alpine:latest
mt-runner-on-debian-latest: debian:latest
mt-runner-on-nixos-latest: nixos/nix
mt-runner-on-ubuntu-jammy: ubuntu:jammy
mt-runner-on-ubuntu-latest: ubuntu:latest
mt-runner-on-ubuntu-noble: ubuntu:noble
container_image: "{{ container_image_map[inventory_hostname] | default('ubuntu:latest') }}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify ansible_python_interpreter definition in inventory and check for NixOS Python handling

echo "=== Checking inventory for ansible_python_interpreter definitions ==="
if [ -f "tests/inventory/docker-containers.yml" ]; then
  cat tests/inventory/docker-containers.yml
else
  echo "Inventory file not found"
fi

echo ""
echo "=== Checking if NixOS container has Python installation tasks ==="
rg -n "nixos" tests/playbooks/docker-containers.yml -i

echo ""
echo "=== Checking full playbook for any Python pre_tasks or installation ==="
head -100 tests/playbooks/docker-containers.yml

Repository: EA31337/ansible-role-mt-runner

Length of output: 4863


🏁 Script executed:

#!/bin/bash
# Check if there are any other references to NixOS in the codebase
echo "=== Searching for NixOS handling in the codebase ==="
rg -n "nixos" . -i --type yaml

echo ""
echo "=== Checking Ansible documentation or comments about Python in containers ==="
rg -n "nix-profile" tests/

Repository: EA31337/ansible-role-mt-runner

Length of output: 1104


🌐 Web query:

Does nixos/nix Docker image have Python installed in /root/.nix-profile/bin/python3

💡 Result:

Short answer: No — the official nixos/nix Docker image is minimal and does not put python3 at /root/.nix-profile/bin/python3 by default. The image only contains a small set of runtime packages (nix, bash, coreutils, tar, curl, etc.), and Python binaries will only appear in a profile or PATH if you explicitly install/add them (they may still exist in the Nix store under /nix/store). [1][2]

If you want python3 in /root/.nix-profile/bin, install it inside the container, e.g.:

  • nix profile install nixpkgs#python3
    or
  • nix-shell -p python3 --run '...'.

Sources: [1] Nix Docker image contents (official docs). [2] Example showing python not on PATH in nixos/nix container.


Add NixOS Python installation pre_task and fix key ordering.

Two issues need to be addressed:

  1. NixOS Python is not pre-installed: The nixos/nix image does not ship with Python at /root/.nix-profile/bin/python3 by default. The playbook will fail at the gather_facts step (line 60). Add a pre_task to install Python on NixOS:

    - name: Install Python 3 on NixOS
      ansible.builtin.raw: |
        test -e "{{ ansible_python_interpreter }}" || nix profile install nixpkgs#python3
      changed_when: false
      when: container_image is search("nixos")
  2. Keys in vars block are not in lexicographical order: Per Ansible best practices, reorder them alphabetically:

    • container_image (currently last)
    • container_image_map (currently second)
    • controller_python (currently first)
🤖 Prompt for AI Agents
In tests/playbooks/docker-containers.yml around lines 41 to 76, add a pre_task
to install Python on NixOS so gather_facts won't fail (use a raw task that
checks for ansible_python_interpreter and runs nix profile install
nixpkgs#python3 when container_image is search("nixos"), with changed_when:
false), and reorder the vars block keys into lexicographical order:
container_image, container_image_map, controller_python.

Comment on lines +47 to +64
- name: Install Python 3 on Ubuntu/Debian
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
changed_when: false
when: container_image is search("ubuntu") or container_image is search("debian")

- name: Gather facts
ansible.builtin.setup:

- name: Install Python packages for Ubuntu/Debian
ansible.builtin.apt:
name:
- python3
- python3-pip
- python3-setuptools
state: present
update_cache: true
when: container_image is search("ubuntu") or container_image is search("debian")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Eliminate redundant Python installation for Ubuntu/Debian.

Python3 and python3-pip are installed twice for Ubuntu/Debian containers:

  • Lines 47-51: via raw module
  • Lines 56-64: via apt module (installs python3, python3-pip, and python3-setuptools)

The raw task is necessary before facts can be gathered, but the subsequent apt task reinstalls the same packages. Consider installing only python3-setuptools in the apt task, or skip the apt task entirely if setuptools isn't strictly required.

🔎 Refactored approach

Option 1: Install only setuptools in the apt task:

    - name: Install Python packages for Ubuntu/Debian
      ansible.builtin.apt:
        name:
-         - python3
-         - python3-pip
          - python3-setuptools
        state: present
        update_cache: true
      when: container_image is search("ubuntu") or container_image is search("debian")

Option 2: If setuptools is not required, remove the apt task entirely.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Install Python 3 on Ubuntu/Debian
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
changed_when: false
when: container_image is search("ubuntu") or container_image is search("debian")
- name: Gather facts
ansible.builtin.setup:
- name: Install Python packages for Ubuntu/Debian
ansible.builtin.apt:
name:
- python3
- python3-pip
- python3-setuptools
state: present
update_cache: true
when: container_image is search("ubuntu") or container_image is search("debian")
- name: Install Python 3 on Ubuntu/Debian
ansible.builtin.raw: |
test -e "{{ ansible_python_interpreter }}" || (apt-get update && apt-get install -y python3 python3-pip)
changed_when: false
when: container_image is search("ubuntu") or container_image is search("debian")
- name: Gather facts
ansible.builtin.setup:
- name: Install Python packages for Ubuntu/Debian
ansible.builtin.apt:
name:
- python3-setuptools
state: present
update_cache: true
when: container_image is search("ubuntu") or container_image is search("debian")
🤖 Prompt for AI Agents
In tests/playbooks/docker-containers.yml around lines 47 to 64, Ubuntu/Debian
images install python3 and python3-pip twice (first via raw to bootstrap Python
before setup, then again via the apt task); update the apt task so it does not
reinstall python3/python3-pip—either remove the apt task entirely if setuptools
is not needed, or change the apt task to only install python3-setuptools (and
keep the same when condition) so the raw bootstrap remains the only step that
installs python and pip before gathering facts.

Copy link

Copilot AI commented Jan 5, 2026

@kenorb I've opened a new pull request, #20, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR represents a comprehensive refactoring effort that modernizes the ansible-role-mt-runner project by enhancing CI/CD pipelines, expanding test coverage, improving documentation, and standardizing configurations across the codebase.

Key Changes

  • Enhanced CI/CD infrastructure: Added actionlint integration, upgraded pre-commit hooks (v24.7.0→v25.4.0), introduced dynamic callback plugins with YAML formatting, and added Molecule test report generation
  • Expanded testing framework: Introduced Docker-based multi-platform testing with new playbooks and inventory files, supporting Alpine, Debian, Ubuntu, and NixOS distributions
  • Dependency updates: Upgraded Python docker package from 4.4 to >=7.1, pinned metatrader dependency to v1.0.3, and added new collections (community.docker, community.windows, ansible.windows)

Reviewed changes

Copilot reviewed 41 out of 43 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
.github/workflows/molecule.yml Enhanced with report generation, reviewdog integration, and dynamic debug callbacks
.github/workflows/test.yml New workflow for Docker-based testing across multiple platforms
.github/workflows/check.yml Added actionlint job for GitHub Actions validation
tests/playbooks/docker-containers.yml New Docker-based test playbook for multi-OS validation
tests/inventory/docker-containers.yml Inventory file defining Docker container test targets
molecule/*/molecule.yml Standardized callback plugins, added dependency management, and enhanced configuration
requirements.yml Pinned metatrader dependency to v1.0.3, added new collections with version constraints
defaults/main.yml Increased timeouts (120→600s), added security allowlist comments, cleared ProxyPassword
templates/*/tester.ini.j2 Normalized Jinja2 whitespace control for cleaner template output
meta/main.yml Expanded platform support, updated galaxy tags, pinned dependency version
.pre-commit-config.yaml Added multiple linters (codespell, gitleaks, black, flake8, actionlint, detect-secrets)
README.md Complete overhaul with installation guides, variable documentation, and testing instructions
.devcontainer/devcontainer.json New dev container configuration for consistent development environments
ansible.cfg / .ansible.cfg Standardized callback configuration using built-in default with YAML format
Pipfile / Pipfile.lock New Python dependency management with pipenv
LICENSE Updated copyright information with project description
Comments suppressed due to low confidence (2)

molecule/requirements.txt:3

  • The docker package version requirement has been changed from '==4.4' to '>=7.1', which is a major version jump (from 4.4 to 7.1+). This is a breaking change that could introduce compatibility issues. Ensure that all code using the docker package is compatible with version 7.1+ API changes.
    molecule/requirements.txt:7
  • The requests package is pinned to version 2.31.0, which has known security vulnerabilities (CVE-2023-32681). Consider updating to a newer version (2.32.0 or later) that addresses these security issues.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

config_options:
defaults:
host_key_checking: false
# Use the built-in default callback with result_format instead of community.general.yaml
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The environment variable 'ANSIBLE_STDOUT_CALLBACK' references 'community.general.yaml' in the comment, but the actual value is set to 'ansible.builtin.default'. The comment on line 31 should be updated to reflect the actual callback being used, or if the comment is meant to explain the change, it should be rephrased for clarity.

Suggested change
# Use the built-in default callback with result_format instead of community.general.yaml
# Use the built-in ansible.builtin.default callback with YAML result_format for output

Copilot uses AI. Check for mistakes.
ANSIBLE_FORCE_COLOR: '1'
ANSIBLE_STDOUT_CALLBACK: yaml
MT_RUNNER_MT4_LOGIN: ${{ secrets.MT_RUNNER_MT4_LOGIN || '12345' }}
ANSIBLE_STDOUT_CALLBACK: ${{ runner.debug == '1' && 'debug' || 'ansible.builtin.default' }}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional expression uses 'runner.debug == '1'' which checks for a string value. In GitHub Actions, runner.debug returns a boolean or is undefined. Consider using 'runner.debug == true' or 'runner.debug' instead to properly handle boolean values.

Copilot uses AI. Check for mistakes.
pipenv = "*"
molecule = "*"
molecule-docker = "*"
requests = "==2.31.0"
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requests package is pinned to version 2.31.0, which has known security vulnerabilities (CVE-2023-32681). Consider updating to a newer version (2.32.0 or later) that addresses these security issues.

Suggested change
requests = "==2.31.0"
requests = ">=2.32.0,<3.0.0"

Copilot uses AI. Check for mistakes.
working-directory: ${{ github.repository }}

# Debug with tmate on failure when debug logging is enabled.
- if: ${{ failure() && runner.debug == '1' }}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional expression uses 'runner.debug == '1'' which checks for a string value. In GitHub Actions, runner.debug returns a boolean or is undefined. Consider using 'runner.debug == true' or 'runner.debug' instead to properly handle boolean values.

Suggested change
- if: ${{ failure() && runner.debug == '1' }}
- if: ${{ failure() && runner.debug }}

Copilot uses AI. Check for mistakes.
ProxyEnable: false
ProxyLogin: user45
ProxyPassword: xxx
ProxyPassword:
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ProxyPassword field is now empty, but if this is used in production contexts where proxy authentication is required, tasks might fail. Consider documenting this change or providing a default placeholder value like 'changeme' to make it more explicit that this needs to be set by users.

Suggested change
ProxyPassword:
ProxyPassword: "{{ ansible_facts.env.MT_RUNNER_MT4_PROXY_PASSWORD | default('changeme') }}"

Copilot uses AI. Check for mistakes.
molecule_options: --verbose
molecule_working_dir: "${{ github.repository }}"
- if: ${{ failure() }}
molecule_options: ${{ runner.debug == '1' && '--verbose' || '' }}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional expression uses 'runner.debug == '1'' which checks for a string value. In GitHub Actions, runner.debug returns a boolean or is undefined. Consider using 'runner.debug == true' or 'runner.debug' instead to properly handle boolean values.

Copilot uses AI. Check for mistakes.
with:
input_file: ${{ github.repository }}/molecule-${{ matrix.scenario }}-report.html
# Debug with tmate on failure when debug logging is enabled.
- if: ${{ failure() && runner.debug == '1' }}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional expression uses 'runner.debug == '1'' which checks for a string value. In GitHub Actions, runner.debug returns a boolean or is undefined. Consider using 'runner.debug == true' or 'runner.debug' instead to properly handle boolean values.

Copilot uses AI. Check for mistakes.
sleep: 10
state: present
timeout: 60
timeout: 120
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout has been doubled from 60 to 120 seconds. This change should be consistent with the overall timeout strategy. Consider documenting why this specific timeout increase is necessary for terminal log file creation.

Copilot uses AI. Check for mistakes.
scm: git
src: https://github.com/EA31337/ansible-role-metatrader.git
version: dev
version: v1.0.3 # This should match version in requirements.yml
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency version has been changed from 'dev' to a specific version 'v1.0.3'. Ensure this version matches exactly with the version specified in requirements.yml (line 17). If these versions become out of sync, it could lead to inconsistent dependency resolution.

Suggested change
version: v1.0.3 # This should match version in requirements.yml
version: dev # This should match version in requirements.yml

Copilot uses AI. Check for mistakes.
molecule-docker
pipenv
pre-commit
requests==2.31.0
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requests package is pinned to version 2.31.0, which has known security vulnerabilities (CVE-2023-32681). Consider updating to a newer version (2.32.0 or later) that addresses these security issues.

Suggested change
requests==2.31.0
requests==2.32.3

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants