mirror of
https://github.com/haidaraM/ansible-playbook-grapher
synced 2024-11-10 06:04:15 +00:00
feat: Add rendered images to job summary (#112)
This commit is contained in:
parent
4f3982ad5b
commit
3326ab0dde
9 changed files with 116 additions and 21 deletions
37
.github/workflows/testing.yaml
vendored
37
.github/workflows/testing.yaml
vendored
|
@ -8,9 +8,14 @@ on:
|
|||
branches:
|
||||
- main
|
||||
|
||||
permissions: write-all
|
||||
|
||||
jobs:
|
||||
pytest:
|
||||
name: Tests Py${{ matrix.python-version }} - Ansible ${{ matrix.ansible-version }}
|
||||
env:
|
||||
MATRIX_JOB_IDENTIFIER: py${{ matrix.python-version }}-ansible${{ matrix.ansible-version }}
|
||||
SVG_FILES_PATH: tests/generated-svgs
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -19,9 +24,12 @@ jobs:
|
|||
# See https://www.ansible.com/blog/ansible-3.0.0-qa and https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html
|
||||
ansible-version: [ 2.12.9, 2.13.4 ]
|
||||
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
name: Setup Python ${{ matrix.python-version }}
|
||||
|
@ -30,24 +38,43 @@ jobs:
|
|||
|
||||
- name: Install prereqs
|
||||
run: |
|
||||
pip install ansible-core==${{ matrix.ansible-version }} virtualenv setuptools wheel coveralls
|
||||
pip install -r tests/requirements_tests.txt
|
||||
pip install -q ansible-core==${{ matrix.ansible-version }} virtualenv setuptools wheel coveralls
|
||||
pip install -qr tests/requirements_tests.txt
|
||||
pip freeze
|
||||
sudo apt-get install -y graphviz
|
||||
sudo apt-get install -yq graphviz
|
||||
ansible-galaxy install -r tests/fixtures/requirements.yml
|
||||
|
||||
- name: Pytest
|
||||
env:
|
||||
PY_COLORS: "1"
|
||||
COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.head_ref }}
|
||||
run: make test
|
||||
|
||||
- name: Upload generated SVGs as artefacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: generated-svgs-py${{ matrix.python-version }}-ansible${{ matrix.ansible-version }}
|
||||
path: tests/generated_svg/
|
||||
name: generated-svgs-${{ env.MATRIX_JOB_IDENTIFIER }}
|
||||
path: ${{ env.SVG_FILES_PATH }}/
|
||||
if-no-files-found: error # the tests should generate SVGs files
|
||||
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
id: commit-svg-files
|
||||
with:
|
||||
commit_message: Adding SVG for the run ${{ env.MATRIX_JOB_IDENTIFIER }}
|
||||
file_pattern: ${{ env.SVG_FILES_PATH }}/*.svg
|
||||
skip_dirty_check: true
|
||||
add_options: '--force'
|
||||
push_options: '--force'
|
||||
branch: generated-svgs-${{ github.head_ref }}-${{ env.MATRIX_JOB_IDENTIFIER }}
|
||||
create_branch: true
|
||||
|
||||
- name: Publish job summary
|
||||
env:
|
||||
SVG_COMMIT_SHA: ${{ steps.commit-svg-files.outputs.commit_hash }}
|
||||
run: |
|
||||
env
|
||||
python tests/generate-job-summary.py >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Test installation in virtualenv
|
||||
run: make test_install ANSIBLE_VERSION=${{ matrix.ansible-version }}
|
||||
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -108,5 +108,5 @@ venv.bak/
|
|||
.idea
|
||||
.vagrant
|
||||
Vagrantfile
|
||||
generated_svg
|
||||
generated-svgs
|
||||
**/.DS_Store
|
2
Makefile
2
Makefile
|
@ -27,6 +27,6 @@ test:
|
|||
|
||||
clean:
|
||||
@echo "Cleaning..."
|
||||
rm -rf ansible_playbook_grapher.egg-info build dist $(VIRTUALENV_DIR) tests/htmlcov tests/.pytest_cache .eggs tests/generated_svg tests/.coverage
|
||||
rm -rf ansible_playbook_grapher.egg-info build dist $(VIRTUALENV_DIR) tests/htmlcov tests/.pytest_cache .eggs tests/generated-svgs tests/.coverage
|
||||
|
||||
.PHONY: clean test_install
|
26
README.md
26
README.md
|
@ -26,9 +26,9 @@ JavaScript:
|
|||
the files for the others nodes. The cursor will be at the task exact position in the file.
|
||||
Lastly, you can provide your own protocol formats
|
||||
with `--open-protocol-handler custom --open-protocol-custom-formats '{}'`. See the help
|
||||
and [an example.](https://github.com/haidaraM/ansible-playbook-grapher/blob/12cee0fbd59ffbb706731460e301f0b886515357/ansibleplaybookgrapher/graphbuilder.py#L33-L42)
|
||||
and [an example.](https://github.com/haidaraM/ansible-playbook-grapher/blob/12cee0fbd59ffbb706731460e301f0b886515357/ansibleplaybookgrapher/graphbuilder.py#L33-L42).
|
||||
- Filer tasks based on tags
|
||||
- Export the dot file using to generate the graph with Graphviz.
|
||||
- Export the dot file used to generate the graph with Graphviz.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -110,9 +110,14 @@ optional arguments:
|
|||
custom. You should provide a JSON formatted string
|
||||
like: {"file": "", "folder": ""}. Example: If you want
|
||||
to open folders (roles) inside the browser and files
|
||||
(tasks) in vscode, set this to '{"file":
|
||||
(tasks) in vscode, set it to: '{"file":
|
||||
"vscode://file/{path}:{line}:{column}", "folder":
|
||||
"{path}"}'
|
||||
"{path}"}'. path: the absolute path to the file
|
||||
containing the the plays/tasks/roles. line/column: the
|
||||
position of the plays/tasks/roles in the file. You can
|
||||
optionally add the attribute "remove_from_path" to
|
||||
remove some parts of the path if you want relative
|
||||
paths.
|
||||
--open-protocol-handler {default,vscode,custom}
|
||||
The protocol to use to open the nodes when double-
|
||||
clicking on them in your SVG viewer. Your SVG viewer
|
||||
|
@ -145,8 +150,11 @@ optional arguments:
|
|||
<playbook>.svg
|
||||
-s, --save-dot-file Save the dot file used to generate the graph.
|
||||
-t TAGS, --tags TAGS only run plays and tasks tagged with these values
|
||||
-v, --verbose verbose mode (-vvv for more, -vvvv to enable
|
||||
connection debugging)
|
||||
-v, --verbose Causes Ansible to print more debug messages. Adding
|
||||
multiple -v will increase the verbosity, the builtin
|
||||
plugins currently evaluate up to -vvvvvv. A reasonable
|
||||
level to start is -vvv, connection debugging might
|
||||
require -vvvv.
|
||||
|
||||
```
|
||||
|
||||
|
@ -169,8 +177,8 @@ More information [here](https://docs.ansible.com/ansible/latest/reference_append
|
|||
arguments may not appear in the graph.
|
||||
- The rendered SVG graph may sometime display tasks in a wrong order. I cannot control this behavior of Graphviz yet.
|
||||
Always check the edge label to know the tasks order.
|
||||
- The label edge may overlap with each other. The edge labels are positioned so that they are as close as possible to
|
||||
the target nodes. If a single role is used in multiple plays or playbooks, this can happen.
|
||||
- The label of the edges may overlap with each other. They are positioned so that they are as close as possible to
|
||||
the target nodes. If the same role is used in multiple plays or playbooks, the labels can overlap.
|
||||
|
||||
## Contribution
|
||||
|
||||
|
@ -190,7 +198,7 @@ export TEST_VIEW_GENERATED_FILE=1
|
|||
$ make test # run all tests
|
||||
```
|
||||
|
||||
The graphs are generated in the folder `tests/generated_svg`. They are also generated as artefacts
|
||||
The graphs are generated in the folder `tests/generated-svgs`. They are also generated as artefacts
|
||||
in [Github Actions](https://github.com/haidaraM/ansible-playbook-grapher/actions). Feel free to look at them when
|
||||
submitting PRs.
|
||||
|
||||
|
|
|
@ -160,8 +160,12 @@ class PlaybookGrapherCLI(CLI):
|
|||
--open-protocol-handler is set to custom.
|
||||
You should provide a JSON formatted string like: {"file": "", "folder": ""}.
|
||||
Example: If you want to open folders (roles) inside the browser and files (tasks) in
|
||||
vscode, set this to
|
||||
'{"file": "vscode://file/{path}:{line}:{column}", "folder": "{path}"}'
|
||||
vscode, set it to:
|
||||
'{"file": "vscode://file/{path}:{line}:{column}", "folder": "{path}"}'.
|
||||
path: the absolute path to the file containing the the plays/tasks/roles.
|
||||
line/column: the position of the plays/tasks/roles in the file.
|
||||
You can optionally add the attribute "remove_from_path" to remove some parts of the
|
||||
path if you want relative paths.
|
||||
""",
|
||||
)
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from typing import Dict, Optional, Tuple, List, Set
|
||||
from typing import Dict, Optional, Tuple, List
|
||||
|
||||
from ansible.utils.display import Display
|
||||
from graphviz import Digraph
|
||||
|
@ -471,8 +471,11 @@ class GraphvizGraphBuilder:
|
|||
:return:
|
||||
"""
|
||||
if node.path:
|
||||
remove_from_path = self.open_protocol_formats.get("remove_from_path", "")
|
||||
path = node.path.replace(remove_from_path, "")
|
||||
|
||||
url = self.open_protocol_formats[node_type].format(
|
||||
path=node.path, line=node.line, column=node.column
|
||||
path=path, line=node.line, column=node.column
|
||||
)
|
||||
display.vvvv(f"Open protocol URL for node {node}: {url}")
|
||||
return url
|
||||
|
|
30
tests/generate-job-summary.py
Normal file
30
tests/generate-job-summary.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
import glob
|
||||
import os
|
||||
from typing import List
|
||||
|
||||
from jinja2 import Template
|
||||
|
||||
DIR_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
def list_svg_files(path_pattern: str) -> List[str]:
|
||||
"""
|
||||
|
||||
:param path_pattern:
|
||||
:return:
|
||||
"""
|
||||
return glob.glob(path_pattern)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open(os.path.join(DIR_PATH, "job-summary.md.j2")) as template_file:
|
||||
template = Template(template_file.read())
|
||||
|
||||
svg_files = list_svg_files(f"{os.environ['SVG_FILES_PATH']}/*.svg")
|
||||
links = []
|
||||
for f in svg_files:
|
||||
links.append(
|
||||
f"https://raw.githubusercontent.com/{os.environ['GITHUB_REPOSITORY']}/{os.environ['SVG_COMMIT_SHA']}/{f}"
|
||||
)
|
||||
|
||||
print(template.render(svg_files=links))
|
6
tests/job-summary.md.j2
Normal file
6
tests/job-summary.md.j2
Normal file
|
@ -0,0 +1,6 @@
|
|||
### Generated SVG files
|
||||
| Images |
|
||||
|:-------:|
|
||||
{% for svg_file in svg_files -%}
|
||||
| ![svg]({{ svg_file }}) |
|
||||
{% endfor %}
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
import os
|
||||
from _elementtree import Element
|
||||
from typing import Dict, List, Tuple
|
||||
|
@ -32,6 +33,22 @@ def run_grapher(
|
|||
if os.environ.get("TEST_VIEW_GENERATED_FILE") == "1":
|
||||
additional_args.insert(0, "--view")
|
||||
|
||||
if os.environ.get("GITHUB_ACTIONS") == "true":
|
||||
# Setting a custom protocol handler for browsing on github
|
||||
additional_args.insert(0, "--open-protocol-handler")
|
||||
additional_args.insert(1, "custom")
|
||||
|
||||
repo = os.environ["GITHUB_REPOSITORY"]
|
||||
commit_sha = os.environ["COMMIT_SHA"]
|
||||
formats = {
|
||||
"file": f"https://github.com/{repo}/blob/{commit_sha}" + "/{path}#L{line}",
|
||||
"folder": f"https://github.com/{repo}/tree/{commit_sha}" + "/{path}",
|
||||
"remove_from_path": os.environ["GITHUB_WORKSPACE"],
|
||||
}
|
||||
|
||||
additional_args.insert(2, "--open-protocol-custom-formats")
|
||||
additional_args.insert(3, json.dumps(formats))
|
||||
|
||||
if "--open-protocol-handler" not in additional_args:
|
||||
additional_args.insert(0, "--open-protocol-handler")
|
||||
additional_args.insert(1, "vscode")
|
||||
|
@ -42,7 +59,7 @@ def run_grapher(
|
|||
if output_filename: # the default filename is the playbook file name minus .yml
|
||||
# put the generated svg in a dedicated folder
|
||||
output_filename = output_filename.replace("[", "-").replace("]", "")
|
||||
args.extend(["-o", os.path.join(DIR_PATH, "generated_svg", output_filename)])
|
||||
args.extend(["-o", os.path.join(DIR_PATH, "generated-svgs", output_filename)])
|
||||
|
||||
args.extend(additional_args)
|
||||
|
||||
|
|
Loading…
Reference in a new issue