diff --git a/actions/github/env/load/action.yml b/actions/github/env/load/action.yml new file mode 100644 index 000000000..f797d10fd --- /dev/null +++ b/actions/github/env/load/action.yml @@ -0,0 +1,132 @@ +inputs: + head-sha: + type: string + default: + name: + type: string + default: env + run-id: + type: string + default: + check-name: + type: string + default: + template-check-text: + type: string + default: | + ## \($icon) Check is running + + ## The check run can be viewed here: + + # \($icon) [\($data.check.name) (\($summary.title))](\($runLink)) + + template-script-current: + type: string + default: | + OUTPUT=\"$(gh api --jq '.workflow_runs[0].id' repos/\($repo)/actions/workflows/request.yml/runs?head_sha=\($head_sha))\" + +outputs: + data: + value: ${{ steps.data.outputs.value }} + output: + value: ${{ steps.toenv.outputs.value }} + + +runs: + using: composite + steps: + # For dispatch events we have to find the request via the Request workflow + - uses: envoyproxy/toolshed/gh-actions/bson@2d46e676172c17700ec475a69ae0893eb55b484d + name: Find request + id: find-request + if: ${{ inputs.head-sha }} + with: + filter: | + "${{ github.repository }}" as $repo + | "${{ inputs.head-sha }}" as $head_sha + | ("${{ inputs.template-script-current }}" | bash::output) + - name: Download environment data + id: download + uses: envoyproxy/toolshed/gh-actions/github/artifact/download@2d46e676172c17700ec475a69ae0893eb55b484d + with: + name: ${{ inputs.name }} + path: ${{ runner.temp }} + run-id: ${{ steps.find-request.outputs.output || inputs.run-id }} + + - name: Validate environment source + if: ${{ github.event_name == 'workflow_run' }} + uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + with: + input: | + workflow_event: ${{ toJSON(github.event.workflow_run.event) }} + workflow_repo: ${{ toJSON(github.event.workflow_run.repository.full_name) }} + current_repo: ${{ toJSON(github.repository) }} + allowed_events: ["pull_request_target", "push", "schedule"] + input-format: yaml + print-output: true + options: -r + filter: | + .workflow_event as $event + | .workflow_repo as $repo + | .current_repo as $current + | .allowed_events as $allowed + # Check that the workflow run came from the same repository + | if $repo != $current then + error("Environment artifact must come from the same repository. Expected: \($current), Got: \($repo)") + # Check that the workflow run was triggered by an allowed event + elif ($allowed | index($event)) == null then + error("Environment artifact must come from an allowed event type. Allowed: \($allowed), Got: \($event)") + else + "✓ Environment source validation passed" + end + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + name: Load env data + id: data + with: + input-format: json-path + input: ${{ runner.temp }}/${{ inputs.name }}.json + # This is hardcoded to allow use of input templates + filter: | + "${{ inputs.check-name }}" as $checkName + | .check = .checks["\($checkName)"] + | del(.checks) + | . as $data + | $data.summary as $summary + | "${{ github.event.workflow_run.conclusion }}" as $conclusion + | "${{ github.run_id }}" as $runId + | "${{ github.repository }}" as $repo + | if $conclusion != "" and $conclusion != "success" + then "completed" + else "in_progress" end + | . as $status + | $data.config.envoy.icon as $icon + | "https://github.com/\($repo)/actions/runs/\($runId)" as $runLink + | "${{ inputs.template-check-text }}" as $text + | {name: $data.check.name, + head_sha: $data.request.sha, + status: $status, + external_id: "\($runId)", + output: { + summary: "Check is running", + title: "\($data.check.name) (\($status))", + text: $text}} + | if $data.check.id and $data.check.id != "" and $status == "completed" then + .conclusion = "cancelled" + else . end + | . as $check + | $data.run + | if $data.check["check-id"] and $status == "completed" then + with_entries(.value = false) + else . end + | . as $run + | $data + | .run = $run + | {$check, + data: ., + checks: {($checkName): $check}} + + print-result: ${{ fromJSON(env.CI_DEBUG || 'false') && true || false }} + - run: | + # Cleanup temporary env file + rm -rf ${{ runner.temp }}/${{ inputs.name }}.json + shell: bash diff --git a/actions/github/env/save/action.yml b/actions/github/env/save/action.yml new file mode 100644 index 000000000..5990221d0 --- /dev/null +++ b/actions/github/env/save/action.yml @@ -0,0 +1,44 @@ +inputs: + name: + type: string + default: env + env: + type: string + required: true + env-format: + type: string + env-filter: + type: string + + +runs: + using: composite + steps: + - id: path + shell: bash + run: | + # Create temporary directory + OUTPUT_DIR=$(mktemp -d) + echo "directory=${OUTPUT_DIR}" >> $GITHUB_OUTPUT + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + name: Check proxy data + id: env + with: + input: | + ${{ inputs.env }} + input-format: ${{ inputs.env-format }} + filter: ${{ inputs.env-filter || '.' }} + print-result: ${{ fromJSON(env.CI_DEBUG || 'false') && true || false }} + output-path: ${{ steps.path.outputs.directory }}/${{ inputs.name }}.json + + - name: Upload environment data + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: ${{ inputs.name }} + path: ${{ steps.path.outputs.directory }} + + - name: Cleanup temporary directory + shell: bash + run: | + # Cleanup temporary directory + rm -rf ${{ steps.path.outputs.directory }} diff --git a/actions/github/env/summary/action.yml b/actions/github/env/summary/action.yml new file mode 100644 index 000000000..abd1e3579 --- /dev/null +++ b/actions/github/env/summary/action.yml @@ -0,0 +1,179 @@ +inputs: + actor: + type: string + required: true + append: + type: boolean + default: true + base-sha: + type: string + column-filter: + type: string + default: + data: + type: string + required: true + event-name: + type: string + default: Request + event-type: + type: string + default: + icon: + type: string + required: true + indent: + type: number + default: 0 + link: + type: string + required: false + message: + type: string + pr: + type: number + output-path: + type: string + ref: + type: string + sha: + type: string + required: true + tables: + type: string + default: + target-branch: + type: string + required: false + title: + type: string + required: false + +outputs: + linked-title: + value: ${{ steps.title.outputs.value }} + summary: + value: ${{ toJSON(steps.output.outputs.value) }} + title: + value: ${{ steps.title.outputs.value }} + + +runs: + using: composite + steps: + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + id: linked-title + with: + input: | + event: "${{ inputs.event-type }}" + link: "" + repo: ${{ github.repository }} + pr: "${{ inputs.pr }}" + sha: ${{ inputs.sha }} + target-branch: ${{ inputs.target-branch }} + title: "${{ inputs.title }}" + input-format: yaml + options: -r + filter: gfm::event_title + + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + id: title + with: + input: | + event: "${{ inputs.event-type }}" + link: ${{ inputs.link }} + repo: ${{ github.repository }} + pr: "${{ inputs.pr }}" + sha: ${{ inputs.sha }} + target-branch: ${{ inputs.target-branch }} + title: "${{ inputs.title }}" + options: -r + input-format: yaml + filter: gfm::event_title + + # This generates a filter from configuration + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + name: Table filter + id: table-filter + with: + input: ${{ inputs.tables }} + input-format: yaml + options: -r + print-output: ${{ fromJSON(env.CI_DEBUG || 'false') && true || false }} + filter: | + with_entries({key: .key, value: .value.filter}) + | utils::filters + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + name: Tables + id: tables + with: + input: ${{ inputs.data }} + options: -r + filter: | + . as $data + | ${{ steps.table-filter.outputs.value }} + | map(select(length > 0)) as $tableData + | with_entries(select(.value | length > 0)) as $tableData + | $data.config.tables + | with_entries( + del(.value.filter) + | .value.data = $tableData[.key] + | select(.value.data | type != "null")) + | gfm::tables + + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + id: output + with: + input: ${{ toJSON(inputs) }} + options: -r + filter: | + . as $inputs + | .sha as $sha + | if $inputs.pr != "" then + .["base-sha"] as $baseSha + | "![](https://raw.githubusercontent.com/primer/octicons/main/icons/git-pull-request-16.svg)" as $prIcon + | "[#\(.pr)](https://github.com/${{ github.repository }}/pull/\(.pr))" as $prLink + | "[`merge`](https://github.com/${{ github.repository }}/commit/\(.ref))" as $mergeLink + | "[`\(.["target-branch"])@\($baseSha[:7])`](https://github.com/${{ github.repository }}/commit/\($baseSha))" as $commitLink + | "\($prIcon) \($prLink) \($mergeLink) \($commitLink)" + else + "" + end + | . as $pr + | "${{ steps.tables.outputs.value }}" as $tables + | ${{ inputs.actor }} as $actor + | "[`\($sha[:7])`](https://github.com/${{ github.repository }}/commit/\($sha))" as $commitLink + | $inputs.message as $message + | if $message != "" then + ($message | split("\n")[0]) as $title + | ($message | "> " + (split("\n")[1:] | join("\n> "))) as $body + | {title: $title, content: $body} + | gfm::collapse + else "" end + | . as $change + | " + \"\($actor.name)\" @\($actor.name) \($commitLink) \($pr) + + \($change) + + \($tables) + " + | str::indent($inputs.indent // "0" | fromjson) + + - uses: envoyproxy/toolshed/gh-actions/jq@2d46e676172c17700ec475a69ae0893eb55b484d + if: ${{ inputs.output-path }} + with: + input: ${{ steps.output.outputs.value }} + options: -sRr + output-path: ${{ inputs.output-path }} + print-result: ${{ fromJSON(env.CI_DEBUG || 'false') && true || false }} + filter: | + . as $summary + | "${{ inputs.icon }}" as $icon + | "${{ steps.linked-title.outputs.value }}" as $link + | "${{ inputs.event-name }}" as $event_name + | " + ## \($icon) \($event_name) (\($link)) + + \($summary) + "