diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml new file mode 100644 index 0000000..7bf64a0 --- /dev/null +++ b/.github/workflows/ci-docker.yml @@ -0,0 +1,62 @@ +name: Continuous Integration - Docker + +on: + pull_request: + branches: + - main + push: + branches: + - main + - feature/** + +permissions: + contents: read + +jobs: + test-docker: + name: Docker Tests + runs-on: ubuntu-latest + + services: + registry: + image: registry:2 + ports: + - 5001:5000 + + env: + TEST_TAG: localhost:5001/actions/yq-yaml-parser-action:latest + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Setup Docker BuildX + id: setup-buildx + uses: docker/setup-buildx-action@v3 + with: + install: true + driver-opts: network=host + + - name: Build the Container + id: build + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ env.TEST_TAG }} + + - name: Run the Container + id: run + env: + INPUT_YAML_FILE_PATH: ./yq-test-action.yml + run: | + docker run \ + --workdir /github/workspace \ + --volume "${{ github.workspace }}":/github/workspace \ + --env GITHUB_OUTPUT="/github/workspace/github_output.txt" \ + --env INPUT_YAML_FILE_PATH="${{ env.INPUT_YAML_FILE_PATH }}" \ + --rm ${{ env.TEST_TAG }} + echo "" + echo "Run Output:" + cat ${{ github.workspace }}/github_output.txt diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml new file mode 100644 index 0000000..5ed3676 --- /dev/null +++ b/.github/workflows/ci-test.yml @@ -0,0 +1,100 @@ +name: Continuous Integration - Test Action + +on: + pull_request: + branches: + - main + push: + branches: + - main + - feature/** + +permissions: + contents: read + +jobs: + test-action: + name: Action Test Output + runs-on: ubuntu-latest + + outputs: + comment-line: ${{ steps.action.outputs.test-action_comment-line }} + to-dont-read: ${{ steps.action.outputs.test-action_to-dont-read }} + multiline: ${{ steps.action.outputs.test-action_multiline }} + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Test Action + id: action + uses: ./ + with: + file-path: ./yq-test-action.yml + filtering-keys: | + test-action_comment-line + test-action_to-rename + test-action_multiline + renaming-outputs: | + test-action_to-rename=test-action_renamed + + test-action-output-comment-line: + name: Action Test Output - Comment Line + needs: test-action + runs-on: ubuntu-latest + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Test Output Comment Line + id: test-output-comment-line + run: | + test_name="Test Output Comment Line" + expected="./app =" + .github/scripts/test-action-output.sh \ + "$test_name" \ + "$expected" \ + "${{ needs.test-action.outputs.comment-line }}" + + test-action-output-dont-read: + name: Action Test Output - Don't Read + needs: test-action + runs-on: ubuntu-latest + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Test Output Don't Read + id: test-output-dont-read + run: | + test_name="Test Output Don't Read" + expected='' + .github/scripts/test-action-output.sh \ + "$test_name" \ + "$expected" \ + "${{ needs.test-action.outputs.to-dont-read }}" + + test-action-output-multiline: + name: Action Test Output - Multiline + needs: test-action + runs-on: ubuntu-latest + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4 + + - name: Test Output Multiline + id: test-output-multiline + run: | + test_name="Test Output Multiline" + expected="### Heading\n\n* Bullet C:\\\n* Driver D:\\\\\n* Points" + expected=$(printf '%s' "${expected}" | sed -e 's/\\n/\n/g') + .github/scripts/test-action-output.sh \ + "$test_name" \ + "$expected" \ + "${{ needs.test-action.outputs.multiline }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 36dfe2a..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,112 +0,0 @@ -name: Continuous Integration - -on: - pull_request: - branches: - - main - push: - branches: - - main - - feature/v1 - -permissions: - contents: read - -jobs: - test-docker: - name: Docker Tests - runs-on: ubuntu-latest - - services: - registry: - image: registry:2 - ports: - - 5001:5000 - - env: - TEST_TAG: localhost:5001/actions/yq-yaml-parser-action:latest - - steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Setup Docker BuildX - id: setup-buildx - uses: docker/setup-buildx-action@v3 - with: - install: true - driver-opts: network=host - - - name: Build the Container - id: build - uses: docker/build-push-action@v6 - with: - context: . - push: true - tags: ${{ env.TEST_TAG }} - - - name: Run the Container - id: run - env: - INPUT_YAML_FILE_PATH: ./yq-test-action.yml - run: | - docker run \ - --workdir /github/workspace \ - --volume "${{ github.workspace }}":/github/workspace \ - --volume "${{ runner.temp }}/_runner_file_commands":${{ runner.temp }}/_runner_file_commands \ - --env GITHUB_OUTPUT="$GITHUB_OUTPUT" \ - --env INPUT_YAML_FILE_PATH="${{ env.INPUT_YAML_FILE_PATH }}" \ - --rm ${{ env.TEST_TAG }} - - test-action: - name: GitHub Actions Test Output - runs-on: ubuntu-latest - - outputs: - comment-line: ${{ steps.action.outputs.test-action_comment-line }} - multiline: ${{ steps.action.outputs.test-action_multiline }} - steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Test Action - id: action - uses: ./ - with: - file-path: ./yq-test-action.yml - - test-action-output-comment-line: - name: GitHub Actions Test Output - Comment Line - needs: test-action - runs-on: ubuntu-latest - - steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Test Output Comment Line - id: test-output-comment-line - run: | - test_name="Test Output Comment Line" - expected_result="./app =" - .github/scripts/test-action-output.sh "$test_name" "$expected_result" "${{ needs.test-action.outputs.comment-line }}" - - test-action-output-multiline: - name: GitHub Actions Test Output - Multiline - needs: test-action - runs-on: ubuntu-latest - - steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Test Output Multiline - id: test-output-multiline - run: | - test_name="Test Output Multiline" - expected_result=$(printf "%b" "### Heading\n\n* Bullet C:\\\\\\\\ E:\\\\\n* Driver D:\\\\\n* Points") - .github/scripts/test-action-output.sh "$test_name" "$expected_result" "${{ needs.test-action.outputs.multiline }}" diff --git a/README.md b/README.md index e028a90..3a353c6 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ -# yq YAML parser action +# YAML parser action [![GitHub Super-Linter](https://github.com/actions-betaon/yq-yaml-parser/actions/workflows/linter.yml/badge.svg)](https://github.com/super-linter/super-linter) -![CI](https://github.com/actions-betaon/yq-yaml-parser/actions/workflows/ci.yml/badge.svg) +![CI Docker](https://github.com/actions-betaon/yq-yaml-parser/actions/workflows/ci-docker.yml/badge.svg) +![CI Test](https://github.com/actions-betaon/yq-yaml-parser/actions/workflows/ci-test.yml/badge.svg) This action reads values from a YAML file setting as action outputs. -To learn how this action was built, see [Creating a Docker container action](https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action). - ## Usage Here's an example of how to use this action in a workflow file: @@ -21,6 +20,14 @@ on: description: "Path to the yaml file to parser" required: true type: string + yaml-filtering-keys: + description: "Read using specific keys" + required: false + type: string + yaml-renaming-outputs: + description: "Used to rename the default output name" + required: false + type: string jobs: yq-yaml-parser: @@ -33,13 +40,17 @@ jobs: uses: actions-betaon/yq-yaml-parser@v1.0.0 with: file-path: '${{ inputs.yaml-file-path }}' + filtering-keys: '${{ inputs.yaml-filtering-keys }}' + renaming-outputs: '${{ inputs.yaml-renaming-outputs }}' ``` ## Inputs -| Input | Description | Default | +| Input | Description | Required | | ----------- | ------------------------------- | ----------- | -| `file-path` | Path to the YAML file to parse as output | | +| `file-path` | Path to the YAML file to parse as output | true | +| `filtering-keys` | The YAML key names list to filter as read | false | +| `renaming-outputs` | The YAML rename "keyname=output" output list | false | ## Outputs diff --git a/action.yml b/action.yml index 05fba2f..49bf703 100644 --- a/action.yml +++ b/action.yml @@ -1,4 +1,4 @@ -name: yq-yaml-parser +name: yq yaml parser description: Convert a yaml to GitHub Actions outputs author: BetaOn Actions @@ -8,11 +8,28 @@ branding: inputs: file-path: - description: "Path to the yaml file to read" + description: Path to the yaml file to read required: true + filtering-keys: + description: | + Read using specific keys + filtering-keys: | + key1_nested + key2_nested_0 + If not provided, all keys will be read + required: false + renaming-outputs: + description: | + Can be used to rename the default output name + renaming-outputs: | + key1_nested=my_output + key2_nested_0=my_output_2 + required: false runs: using: docker image: Dockerfile env: INPUT_YAML_FILE_PATH: "${{ inputs.file-path }}" + INPUT_YAML_FILTERING_KEYS: "${{ inputs.filtering-keys }}" + INPUT_YAML_RENAMING_OUTPUTS: "${{ inputs.renaming-outputs }}" diff --git a/entrypoint.sh b/entrypoint.sh index aea1926..6a612e1 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,9 +1,81 @@ #!/bin/ash -l # shellcheck shell=dash -_yaml_to_properties() { - local yaml_file="$1" - yq -o p --properties-separator '=' '... comments = ""' "$yaml_file" +_yaml_keys_names_outputs_values_default() { + local file="$1" + local dotReplacement="$2" + + properties=$(yq -o p --properties-separator "=" '... comments = ""' "$file") + + echo "$properties" | while read -r propertyLine; do + keyName="${propertyLine%%=*}" + keyNameOutput=$(_replace_dots "$keyName" "$dotReplacement") + keyNameOutputValue="${propertyLine#*=}" + echo "$keyNameOutput=$keyNameOutputValue" + done +} + +_yaml_keys_names_outputs_values_filter() { + local keysNamesOutputsValues="$1" + local keysNamesOutputsFilter="$2" + + echo "$keysNamesOutputsValues" | while read -r keyNameOutputValueLine; do + keyNameOutput="${keyNameOutputValueLine%%=*}" + if echo "$keysNamesOutputsFilter" | grep -Fxq -- "$keyNameOutput"; then + echo "$keyNameOutputValueLine" + fi + done +} + +_yaml_keys_names_outputs_values_rename() { + local keysNamesOutputsValues="$1" + local keysNamesOutputsRename="$2" + + echo "$keysNamesOutputsValues" | while read -r keyNameOutputValueLine; do + keyNameOutputSearch="${keyNameOutputValueLine%%=*}" + + keyNameOutputRenameValue=$(_yaml_keys_names_outputs_values_rename_value "$keyNameOutputSearch" "$keysNamesOutputsRename") + if [ -n "$keyNameOutputRenameValue" ]; then + keyNameOutputValue="${keyNameOutputValueLine#*=}" + echo "$keyNameOutputRenameValue=$keyNameOutputValue" + else + echo "$keyNameOutputValueLine" + fi + done +} + +_yaml_keys_names_outputs_values_rename_value() { + local keyNameOutputSearch="$1" + local keysNamesOutputsRename="$2" + + echo "$keysNamesOutputsRename" | while read -r keyNameOutputRenameLine; do + keyNameOutputRename="${keyNameOutputRenameLine%%=*}" + + if [ "$keyNameOutputRename" = "$keyNameOutputSearch" ]; then + keyNameOutputRenameValue="${keyNameOutputRenameLine#*=}" + echo "$keyNameOutputRenameValue" + break + fi + done +} + +_yaml_keys_names_outputs_values() { + local file="$1" + local filteringKeys="$2" + local renamingOutptus="$3" + local dotReplacement="$4" + + keysNamesValuesOutputsResult=$(_yaml_keys_names_outputs_values_default "$file" "$dotReplacement") + + if [ -n "$filteringKeys" ]; then + keysNamesValuesOutputsResult=$(_yaml_keys_names_outputs_values_filter "$keysNamesValuesOutputsResult" "$filteringKeys") + fi + + if [ -n "$renamingOutptus" ]; then + keysNamesValuesOutputsResult=$(_yaml_keys_names_outputs_values_rename "$keysNamesValuesOutputsResult" "$renamingOutptus" "$dotReplacement") + fi + + echo "$keysNamesValuesOutputsResult" } _replace_dots() { @@ -12,49 +84,46 @@ _replace_dots() { echo "${string}" | sed "s/\./${replacement}/g" } -_property_value_to_multiline() { - local propertyValue="$1" - local lineMark="#LN#" - - propertyValueMultiLine=$(echo "$propertyValue" | sed "s/\\\\n/$lineMark/g") - propertyValueMultiLine=$(echo "$propertyValueMultiLine" | sed 's/\\/\\\\/g') - propertyValueMultiLine=$(echo "$propertyValueMultiLine" | sed "s/$lineMark/\n/g") - propertyValueMultiLine=$(echo "$propertyValueMultiLine" | sed '${/^$/d;}') - echo "$propertyValueMultiLine" -} - _set_github_output() { - local propertyName="$1" - local propertyValue="$2" + local keyNameOutput="$1" + local keyNameOutputValue="$2" - if echo "$propertyValue" | grep -q '\\n'; then - propertyValueMultiLine=$(_property_value_to_multiline "$propertyValue") + keyNameOutputValueGitHubOutput=$(printf '%s' "${keyNameOutputValue}" | sed -e 's/\\n/\n/g') + keyNameOutputValueGitHubOutputLineCount=$(echo "$keyNameOutputValueGitHubOutput" | wc -l) + if [ "$keyNameOutputValueGitHubOutputLineCount" -gt 1 ]; then { - echo "$propertyName<>"$GITHUB_OUTPUT" else - echo "$propertyName=$propertyValue" >>"$GITHUB_OUTPUT" + echo "$keyNameOutput=$keyNameOutputValueGitHubOutput" >>"$GITHUB_OUTPUT" fi } _set_github_outputs() { - local properties="$1" - local propertyNameDotReplace="$2" + local yamlFile="$1" + local filteringKeys="$2" + local renamingOutputs="$3" + local dotReplacement="$4" - echo "$properties" | while read -r propertyLine; do - propertyName=$(_replace_dots "${propertyLine%%=*}" "$propertyNameDotReplace") - propertyValue="${propertyLine#*=}" - _set_github_output "$propertyName" "$propertyValue" + keysNamesOutputsValues=$(_yaml_keys_names_outputs_values "$yamlFile" "$filteringKeys" "$renamingOutputs" "$dotReplacement") + + echo "$keysNamesOutputsValues" | while read -r keyNameOutputValueLine; do + keyNameOutput="${keyNameOutputValueLine%%=*}" + keyNameOutputValue="${keyNameOutputValueLine#*=}" + _set_github_output "$keyNameOutput" "$keyNameOutputValue" done } set -e -_propertyNameDotReplace="_" -_yqProperties=$(_yaml_to_properties "$INPUT_YAML_FILE_PATH") +_dotReplacement="_" -_set_github_outputs "$_yqProperties" "$_propertyNameDotReplace" +_set_github_outputs \ + "$INPUT_YAML_FILE_PATH" \ + "$INPUT_YAML_FILTERING_KEYS" \ + "$INPUT_YAML_RENAMING_OUTPUTS" \ + "$_dotReplacement" exit 0 diff --git a/yq-test-action.yml b/yq-test-action.yml index fd5e1a2..44dd5b1 100644 --- a/yq-test-action.yml +++ b/yq-test-action.yml @@ -1,9 +1,11 @@ test-action: # comment - comment-line: ./app = #comment line + comment-line: ./app = #comment line + to-dont-read: this is not read + to-rename: this is will be renamed multiline: | ### Heading - * Bullet C:\\ E:\ - * Driver D:\ + * Bullet C:\ + * Driver D:\\ * Points \ No newline at end of file