From 02bbd1048600a85c3454ccfdd73e7fd24d8185d8 Mon Sep 17 00:00:00 2001 From: Max Theilig Date: Tue, 9 Jan 2024 11:11:03 +0100 Subject: [PATCH 1/5] initial committ --- .github/workflows/RenderAllDiagrams.yml | 105 +++++++++++ .github/workflows/RenderPlantUML.yml | 45 +++++ .vscode/keybindings.json | 11 ++ .vscode/tasks.json | 15 ++ .../images/Gematik_Logo_Flag.png | Bin .../docs/Beispiel_MedikationsAbgleich.xlsx | Bin 0 -> 104323 bytes Material/imgsrc/drawio/Klassendiagramm.drawio | 1 + .../imgsrc/plantuml/amts_data_objects.puml | 10 ++ README.md | 2 + scripts/build_with_replace_includes.sh | 67 +++++++ scripts/release_publish.py | 170 ++++++++++++++++++ scripts/setup.sh | 4 + 12 files changed, 430 insertions(+) create mode 100644 .github/workflows/RenderAllDiagrams.yml create mode 100644 .github/workflows/RenderPlantUML.yml create mode 100644 .vscode/keybindings.json create mode 100644 .vscode/tasks.json rename Gematik_Logo_Flag.png => ImplementationGuide/images/Gematik_Logo_Flag.png (100%) create mode 100644 Material/docs/Beispiel_MedikationsAbgleich.xlsx create mode 100644 Material/imgsrc/drawio/Klassendiagramm.drawio create mode 100644 Material/imgsrc/plantuml/amts_data_objects.puml create mode 100644 scripts/build_with_replace_includes.sh create mode 100644 scripts/release_publish.py diff --git a/.github/workflows/RenderAllDiagrams.yml b/.github/workflows/RenderAllDiagrams.yml new file mode 100644 index 0000000..cfba559 --- /dev/null +++ b/.github/workflows/RenderAllDiagrams.yml @@ -0,0 +1,105 @@ +name: Render All Diagrams + +on: + push: + branches: + - '**' + paths: + - 'Material/imgsrc/plantuml/**' + - 'Material/imgsrc/drawio/**' + + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + # Installs Java distribution for running the plantUML jar + - name: Install Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '11' + check-latest: true + + # Install graphviz for plantuml + - name: Setup Graphviz + uses: ts-graphviz/setup-graphviz@v1 + + # Download plantUML jar + - name: Download plantuml file + run: | + wget -O plantuml.jar "https://github.com/plantuml/plantuml/releases/download/v1.2023.10/plantuml-1.2023.10.jar" + + # Runs a single command using the runners shell + - name: Generate images + run: | + imagedir=ImplementationGuide/images/diagrams + mkdir -p $imagedir + rm -rf ImplementationGuide/images/diagrams/* + for fullname in $(find Material/imgsrc/plantuml/ -type f -name '*.puml') + do + echo "Fullname: ${fullname}" + base=$(basename "${fullname}" .puml) + dir=$(dirname $fullname) + echo "Basename: ${base}" + outdir=$(dirname $fullname | sed s+src/plantuml+${imagedir}+) + echo "Outdir: ${outdir}" + mkdir -p $outdir + plantoutdir="${PWD}/${outdir}" + echo "PlantOutdir: ${plantoutdir}" + + # PlantUML arguments: + # -v for verbose output (Debugging) + # -checkmetadata checks whether the target png/svg has the same source + # and if there are no changes, doesn't regenerate the image file + # -o sets the output folder for the png/svg files + plantargs="-v -checkmetadata -o ${plantoutdir} ${fullname}" + + # separate calls are needed, because only one file type can be set + # per call + java -jar plantuml.jar -tpng ${plantargs} + java -jar plantuml.jar -tsvg ${plantargs} + + # method with pipes + #cat "${fullname}" | java -jar plantuml.jar -p -tpng -checkmetadata > "${outdir}/${base}.png" + #cat "${fullname}" | java -jar plantuml.jar -p -tsvg -checkmetadata > "${outdir}/${base}.svg" + done + tree ./images + + # creates png files from draw io image files + - name: Export drawio files as png + uses: rlespinasse/drawio-export-action@v2 + with: + path: ./src/drawio/ + output: . + format: png + action-mode: all + + # creates svg files from draw io image files + - name: Export drawio files + uses: rlespinasse/drawio-export-action@v2 + with: + path: ./src/drawio/ + output: . + format: svg + action-mode: all + + # copies the created png & svg files to the images/diagrams folder and deletes the drawio files + - name: Copy draw io + run: | + imagedir=images/diagrams + cp -RT ./src/drawio $imagedir + find $imagedir -name '*.drawio' -exec rm -rv {} \; + tree ./images + + # add and commit the new generated files + - name: Add & Commit + uses: EndBug/add-and-commit@v9 + with: + add: 'ImplementationGuide/images/diagrams/' diff --git a/.github/workflows/RenderPlantUML.yml b/.github/workflows/RenderPlantUML.yml new file mode 100644 index 0000000..4d2b744 --- /dev/null +++ b/.github/workflows/RenderPlantUML.yml @@ -0,0 +1,45 @@ +name: Render PlantUML diagrams + +on: + push: + branches: + - '**' + paths: + - '**/Material/imgsrc/**/*.puml' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install dependencies + run: | + sudo apt-get install -y graphviz + wget http://sourceforge.net/projects/plantuml/files/plantuml.jar/download -O plantuml.jar + + - name: Render and Move SVG files + run: | + # Find all unique directories containing *.puml files under any /imgsrc/ folder + directories=$(find . -path "*/imgsrc/*.puml" -exec dirname {} \; | sort -u) + for dir in $directories; do + # Generate the corresponding out directory path + out_dir=${ImplementationGuide/diagrams} + mkdir -p $out_dir + + # Render SVGs from PUMLs + find $dir -name "*.puml" -exec java -jar plantuml.jar -tsvg {} \; + + # Move SVGs to out directory + find $dir -name "*.svg" -exec mv {} $out_dir \; + done + + - name: Commit and push + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add -A + git commit -m "Add rendered SVG diagrams" || exit 0 + git push \ No newline at end of file diff --git a/.vscode/keybindings.json b/.vscode/keybindings.json new file mode 100644 index 0000000..79192d7 --- /dev/null +++ b/.vscode/keybindings.json @@ -0,0 +1,11 @@ +[ + { + "key": "f5", + "command": "workbench.action.tasks.runTask", + "args": "buildWithReplaceIncludes" + }, + { + "key": "f5", + "command": "-workbench.action.debug.start" + } +] diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..7359920 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "buildWithReplaceIncludes", + "type": "shell", + "command": "./resources/scripts/build_with_replace_includes.sh", + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/Gematik_Logo_Flag.png b/ImplementationGuide/images/Gematik_Logo_Flag.png similarity index 100% rename from Gematik_Logo_Flag.png rename to ImplementationGuide/images/Gematik_Logo_Flag.png diff --git a/Material/docs/Beispiel_MedikationsAbgleich.xlsx b/Material/docs/Beispiel_MedikationsAbgleich.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8d7eb95e149d65076d00fe1993b64cee14c6ad94 GIT binary patch literal 104323 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 literal 0 HcmV?d00001 diff --git a/Material/imgsrc/drawio/Klassendiagramm.drawio b/Material/imgsrc/drawio/Klassendiagramm.drawio new file mode 100644 index 0000000..c6d9cc5 --- /dev/null +++ b/Material/imgsrc/drawio/Klassendiagramm.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Material/imgsrc/plantuml/amts_data_objects.puml b/Material/imgsrc/plantuml/amts_data_objects.puml new file mode 100644 index 0000000..e7333b4 --- /dev/null +++ b/Material/imgsrc/plantuml/amts_data_objects.puml @@ -0,0 +1,10 @@ +```plantuml +@startuml component +actor client +node app +database db + +db -> app +app -> client +@enduml +``` \ No newline at end of file diff --git a/README.md b/README.md index 1119369..28e851f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![Include Gematik Logo](ImplementationGuide/images/Gematik_Logo_Flag.png) + # About This template standardizes the development of fhir resources with .fsh resources. It should reduce time for setup and ease the development process. diff --git a/scripts/build_with_replace_includes.sh b/scripts/build_with_replace_includes.sh new file mode 100644 index 0000000..745893f --- /dev/null +++ b/scripts/build_with_replace_includes.sh @@ -0,0 +1,67 @@ +#!/bin/bash +echo "Start building source files" + +# check prerequisites +required_asciidoctor_version="2.0.20" +actual_asciidoctor_version=$(asciidoctor --version) +if ! grep -q "$required_asciidoctor_version" <<<"$actual_asciidoctor_version"; then + echo "Incorrect asciidoctor version. Expected $required_asciidoctor_version but found $actual_asciidoctor_version" + exit 1 +fi + +required_asciidoctor_diagram_version="2.2.14" +actual_asciidoctor_diagram_version=$(gem list | grep "asciidoctor-diagram (") +if ! grep -q "$required_asciidoctor_diagram_version" <<<"$actual_asciidoctor_diagram_version"; then + echo "Incorrect asciidoctor diagram version. Expected $required_asciidoctor_diagram_version but found $actual_asciidoctor_diagram_version" + exit 1 +fi + +# STAGE_1: creates images from the puml files and will store them in /puml/images + +# prepare +cd "$(dirname "$0")" || exit +# rm ../../images/puml_* + +# loop through all puml files and create the image +for filename in $(find ../../puml -name '*.puml'); do + + filebase=$(basename -- "$filename") # test.adoc + name="${filebase%.*}" # test + + if ! git diff --quiet -- "$filename"; then + echo "$filebase has been modified. Creating Puml" + + pumlPath=../puml/${name}.puml + newFileRoot=../puml/${name} + newFileName=${newFileRoot//-source/} + echo "Creating Puml ${name}" + + tempAdocFile=../../docs_sources/${name}.adoc + + # creates a temporary adoc file in order to render with asciidoctor-diagram + touch ${tempAdocFile} + echo "[plantuml, target=../../images/puml_${name}, format=png] +.... +include::${pumlPath}[] +...." >${tempAdocFile} + asciidoctor -r asciidoctor-diagram -o ../puml/$newFileName ../../docs_sources/${name}.adoc + rm ../../docs_sources/${name}.adoc + fi + +done + +# cleanup temp files +if [ -d "../puml" ]; then + rm -r ../puml +fi + +# STAGE_2 this creates new adoc files in /docs/resources + +for filename in $(find ../../docs_sources -name '*.adoc'); do + newFileName=${filename//-source/} + newFileName=${newFileName//_sources/} + asciidoctor-reducer $filename -o $newFileName +done + +# Echo that the process is finished +echo "Finished building source files" diff --git a/scripts/release_publish.py b/scripts/release_publish.py new file mode 100644 index 0000000..92e9cca --- /dev/null +++ b/scripts/release_publish.py @@ -0,0 +1,170 @@ +import re +import subprocess +import os +import argparse +from datetime import date + +class FileWithVersionToUpdate: + def __init__(self, filename, version_regex) -> None: + self.filename = filename + self.version_regex = version_regex + self.location = None + + def set_file_location(self, location): + self.location = location + +class FileWithDateToUpdate: + def __init__(self, filename, date_regex) -> None: + self.filename = filename + self.date_regex = date_regex + self.location = None + + def set_file_location(self, location): + self.location = location + +# class FileWithDateToUpdate: +# def __init__(self, filename, date_regex, format) -> None: +# self.filename = filename +# self.date_regex = date_regex +# self.location = None +# self.format = format +# def set_file_location(self, location): +# self.location = location + + + + +def get_new_release_version_from_branch_name() -> str: + git_branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip().decode() + return git_branch + +def replace_version_in_files(files : list, new_release_version: str): + if files is None: + print("Error: No Files found!") + return + + for file in files: + replace_version_in_file(file,new_release_version) + +def replace_version_in_file(file: FileWithVersionToUpdate,new_release_version: str): + with open(file.location, 'r') as input_file: + input_text = input_file.read() + + output_text = re.sub(file.version_regex, rf'\g<1>{new_release_version}\g<3>', input_text) + print(f"Info: Replaced version with '{new_release_version}' in file '{file.location}'.") + + with open(file.location, 'w') as output_file: + output_file.write(output_text) + +def replace_date_in_files(files : list, new_release_date: str): + if files is None: + print("Error: No Files found!") + return + + for file in files: + replace_date_in_file(file,new_release_date) + +def replace_date_in_file(file: FileWithVersionToUpdate, new_date: str): + with open(file.location, 'r') as input_file: + input_text = input_file.read() + + #output_text = re.sub(file.date_regex, rf'\g<1>{new_date.strftime(file.format)}\g<3>', input_text) #see https://www.programiz.com/python-programming/datetime#:~:text=Python%20format%20datetime&text=It%27s%20more%20common%20to%20use,()%20methods%20to%20handle%20this. + output_text = re.sub(file.date_regex, rf'\g<1>{new_date}\g<3>', input_text) + print(f"Info: Replaced date with '{new_date}' in file '{file.location}'.") + + with open(file.location, 'w') as output_file: + output_file.write(output_text) + +def get_file_to_update_version_list(): + file_list = [] + file_list.append(FileWithVersionToUpdate('package.json', r'("version":\s*")([\d\.]+.*)(")')) + file_list.append(FileWithVersionToUpdate('sushi-config.yaml', r'(version:\s*")(\d+\.\d+\.\d+.*)(")')) + file_list.append(FileWithVersionToUpdate('sushi-config.yaml', r'(version:\s*)(\d+\.\d+\.\d+.*)()')) + file_list.append(FileWithVersionToUpdate('ruleset.fsh', r'(\*\s*version\s*=\s*")([\d\.]+.*)(")')) + file_list.append(FileWithVersionToUpdate('ruleset.fsh', r'(\*\s*\^version\s*=\s*")([\d\.]+.*)(")')) + file_list.append(FileWithVersionToUpdate('Einfuehrung.md', r'(Version: \s*)(\d+\.\d+\.\d+.*)()')) + file_list.append(FileWithVersionToUpdate('ImplementierungsleitfadenIsiK_basismodul.json', r'("version":\s*")([\d\.]+.*)(")')) + file_list.append(FileWithVersionToUpdate('ImplementierungsleitfadenIsiK_Terminplanung.json', r'("version":\s*")([\d\.]+.*)(")')) + return file_list + +def get_file_to_update_date_list(): + file_list = [] + #file_list.append(FileWithDateToUpdate('ruleset.fsh', r'(date\s*=\s*")(\d+\-\d+\-\d+)(")'), '%m/%d/%Y' ) + #file_list.append(FileWithDateToUpdate('Einfuehrung.md', r'(Datum: \s*)(\d+\.\d+\.\d+)()') , '%m/%d/%Y') + file_list.append(FileWithDateToUpdate('ruleset.fsh', r'(\*\s*date\s*=\s*")(\d+\-\d+\-\d+)(")')) + file_list.append(FileWithDateToUpdate('ruleset.fsh', r'(\*\s*\^date\s*=\s*")(\d+\-\d+\-\d+)(")')) + file_list.append(FileWithDateToUpdate('Einfuehrung.md', r'(Datum:\s*)(\d+\.\d+\.\d+.*)()')) + return file_list + + +def locate_files_in_current_project(files: list): + return_list = [] + for current_file in files: + file_location = find_file(current_file.filename, ".") + if file_location is not None: + current_file.set_file_location(file_location) + return_list.append(current_file) + else: + print(f"Warning: File '{current_file.filename}' not found.") + return return_list + +def find_file(name, path="."): + for root, dirs, files in os.walk(path): + + if name in files: + print(f"Info: Found '{name}' in {root}.") + return os.path.join(root, name) + return None + +def get_latest_release_tag(): + cmd = 'git describe --abbrev=0 --tags --match "v*.*.*" HEAD' + try: + output = subprocess.check_output(cmd, shell=True) + return output.decode().strip() + except subprocess.CalledProcessError: + return None + +def output_commit_messages_since_last_release(): + latest_release_tag = get_latest_release_tag() + if latest_release_tag is None: + print("Warning: No release tag found.") + return + + cmd = f'git log --pretty=format:"%s" {latest_release_tag}..HEAD' + try: + output = subprocess.check_output(cmd, shell=True) + print(output.decode()) + except subprocess.CalledProcessError: + print("Warning: Failed to get commit messages.") + +def main(): + today = date.today() + + parser = argparse.ArgumentParser(description='Update release version number') + parser.add_argument('-b', '--branch', action='store_true', help='get new version from branch name') + parser.add_argument('-v', '--version', type=str, help='specify new version number') + parser.add_argument('-o', '--output', action='store_true', help='output commit messages since last release') + # TODO new argument -d if not date_time now + + args = parser.parse_args() + + if args.version: + new_release_version = args.version + elif args.branch: + new_release_version = get_new_release_version_from_branch_name() + else: + parser.error('No new release version specified. Please use either -v or -b to specify the new release version.') + + if args.output: + output_commit_messages_since_last_release() + + file_to_update_version_list = get_file_to_update_version_list() + file_version_list = locate_files_in_current_project(file_to_update_version_list) + replace_version_in_files(file_version_list, new_release_version) + + file_to_update_date_list = get_file_to_update_date_list() + file_date_list = locate_files_in_current_project(file_to_update_date_list) + replace_date_in_files(file_date_list, today) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/scripts/setup.sh b/scripts/setup.sh index 849557a..196c20e 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -1,6 +1,10 @@ #!/bin/bash rm ./Resources/input/fsh/*.fsh rm ./Resources/fsh-generated/resources/* +rm ./Material/docs/* +rm ./Material/docs/imgsrc/drawio/* +rm ./Material/docs/imgsrc/plantuml/* +rm ./ImplementationGuide/diagrams/* rm ./README.md cat Readme_template.md USAGE.md > ./README.md rm Readme_template.md From f816a6204e2ebdcec87ea272e6b8384222448279 Mon Sep 17 00:00:00 2001 From: Max Theilig Date: Tue, 9 Jan 2024 11:21:58 +0100 Subject: [PATCH 2/5] debug --- .github/workflows/RenderPlantUML.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/RenderPlantUML.yml b/.github/workflows/RenderPlantUML.yml index 4d2b744..102c318 100644 --- a/.github/workflows/RenderPlantUML.yml +++ b/.github/workflows/RenderPlantUML.yml @@ -23,10 +23,11 @@ jobs: - name: Render and Move SVG files run: | # Find all unique directories containing *.puml files under any /imgsrc/ folder - directories=$(find . -path "*/imgsrc/*.puml" -exec dirname {} \; | sort -u) + directories=$(find . -path "*/imgsrc/*/*.puml" -exec dirname {} \; | sort -u) for dir in $directories; do # Generate the corresponding out directory path - out_dir=${ImplementationGuide/diagrams} + out_dir=${/ImplementationGuide/diagrams} + echo $out_dir mkdir -p $out_dir # Render SVGs from PUMLs From bb9ef3b43e0a9084152a48f1878edc71663db000 Mon Sep 17 00:00:00 2001 From: Max Theilig Date: Tue, 9 Jan 2024 11:29:51 +0100 Subject: [PATCH 3/5] g --- ImplementationGuide/diagrams/test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ImplementationGuide/diagrams/test.txt diff --git a/ImplementationGuide/diagrams/test.txt b/ImplementationGuide/diagrams/test.txt new file mode 100644 index 0000000..e69de29 From 008cecf918b040bc90b98c48a9f0cd7b66c2493b Mon Sep 17 00:00:00 2001 From: Max Theilig Date: Tue, 9 Jan 2024 13:35:26 +0100 Subject: [PATCH 4/5] next --- .github/workflows/RenderAllDiagrams.yml | 9 ++++----- .github/workflows/RenderPlantUML.yml | 7 ++++--- .github/workflows/main.yml | 12 ++++++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/.github/workflows/RenderAllDiagrams.yml b/.github/workflows/RenderAllDiagrams.yml index cfba559..6657eb4 100644 --- a/.github/workflows/RenderAllDiagrams.yml +++ b/.github/workflows/RenderAllDiagrams.yml @@ -2,12 +2,11 @@ name: Render All Diagrams on: push: - branches: - - '**' - paths: - - 'Material/imgsrc/plantuml/**' - - 'Material/imgsrc/drawio/**' + paths: + - '**/Material/imgsrc/**/*.puml' + - '**/Material/imgsrc/**/*.drawio' + # Allows you to run this workflow manually from the Actions tab workflow_dispatch: jobs: diff --git a/.github/workflows/RenderPlantUML.yml b/.github/workflows/RenderPlantUML.yml index 102c318..fa4fb51 100644 --- a/.github/workflows/RenderPlantUML.yml +++ b/.github/workflows/RenderPlantUML.yml @@ -2,11 +2,12 @@ name: Render PlantUML diagrams on: push: - branches: - - '**' paths: - '**/Material/imgsrc/**/*.puml' + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + jobs: build: runs-on: ubuntu-latest @@ -42,5 +43,5 @@ jobs: git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add -A - git commit -m "Add rendered SVG diagrams" || exit 0 + git commit -m "Add rendered PlantUML diagrams" || exit 0 git push \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6db33ce..61545d7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,11 +4,11 @@ name: CI (FHIR Validation) # Controls when the action will run. on: - # Triggers the workflow on push or pull request events but only for the master branch + # Triggers the workflow on all push or pull request events but only for the main branches push: - branches: [ master ] + branches: [ main* ] pull_request: - branches: [ master ] + branches: [ main* ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -38,7 +38,6 @@ jobs: JAVA_VALIDATION_ENABLED: true OUTPUT_FORMAT: RAW JAVA_VALIDATION_OPTIONS: -allow-example-urls true - JAVA_VALIDATOR_VERSION: 6.0.11 SIMPLIFIER_USERNAME: ${{ secrets.SIMPLIFIER_USERNAME }} SIMPLIFIER_PASSWORD: ${{ secrets.SIMPLIFIER_PASSWORD }} SUSHI_ENABLED: true @@ -46,6 +45,11 @@ jobs: SUSHI_OPTIONS: Resources/ EXPECTED_FAILS: VALIDATION_CONFORMANCE_DOTNET VALIDATION_CONFORMANCE_JAVA VALIDATION_EXAMPLES_JAVA + # - name: Add & Commit + # uses: EndBug/add-and-commit@v7 + # with: + # add: 'Resources/fsh-generated/resources/' + - name: Check for Uncommitted Changes run: | git diff --exit-code 'Resources/fsh-generated/resources'|| (echo "Es gibt Änderungen durch die Pipeline. Lokale Sushi Konfiguration prüfen!" && exit 1) \ No newline at end of file From 66d69d16ef8c19d41292ceec3879bb86df59acb5 Mon Sep 17 00:00:00 2001 From: Max Theilig Date: Tue, 9 Jan 2024 13:39:21 +0100 Subject: [PATCH 5/5] workflow dispatch --- .github/workflows/RenderAllDiagrams.yml | 2 +- .github/workflows/RenderPlantUML.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/RenderAllDiagrams.yml b/.github/workflows/RenderAllDiagrams.yml index 6657eb4..4790914 100644 --- a/.github/workflows/RenderAllDiagrams.yml +++ b/.github/workflows/RenderAllDiagrams.yml @@ -5,7 +5,7 @@ on: paths: - '**/Material/imgsrc/**/*.puml' - '**/Material/imgsrc/**/*.drawio' - + # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/.github/workflows/RenderPlantUML.yml b/.github/workflows/RenderPlantUML.yml index fa4fb51..2c4e120 100644 --- a/.github/workflows/RenderPlantUML.yml +++ b/.github/workflows/RenderPlantUML.yml @@ -4,7 +4,7 @@ on: push: paths: - '**/Material/imgsrc/**/*.puml' - + # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -43,5 +43,5 @@ jobs: git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add -A - git commit -m "Add rendered PlantUML diagrams" || exit 0 + git commit -m "Add rendered PlantUML to SVG diagrams" || exit 0 git push \ No newline at end of file