diff --git a/.github/workflows/scripts.run-with-summary.yml b/.github/workflows/scripts.run-with-summary.yml
new file mode 100644
index 0000000..b2d0245
--- /dev/null
+++ b/.github/workflows/scripts.run-with-summary.yml
@@ -0,0 +1,47 @@
+# Test the scripts.
+name: Run with Summary
+on:
+ pull_request:
+ branches:
+ - main
+
+# Settings for run-with-summary script.
+env:
+ FILE: report-${{ github.run_id }}.md
+ SUMMARY: |
+ - Environment: https://pr${{ github.event.number }}.demo.site
+ - Pull Request: ${{github.event.pull_request.html_url }}
+
+ ${{ github.event.pull_request.title }}
+ ${{ github.event.pull_request.body }}
+
+ DEBUG: yes
+ PATH: ./src:./bin:./vendor/bin:/usr/local/bin:/usr/bin:/bin
+
+jobs:
+
+ run-with-summary:
+ name: run-with-summary success
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: run-with-summary
+ env:
+ HEADING: "Running Tests"
+ SUCCESS: "Test Command Succeeded :white_check_mark:"
+ ERROR: "Test Command Failed! :x:"
+ run: |
+ run-with-summary ls -la >> $GITHUB_STEP_SUMMARY
+
+ run-with-summary-fail:
+ name: run-with-summary failure
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: run-with-summary failure
+ env:
+ HEADING: "Confirming command failure"
+ SUCCESS: "Command Succeeded :white_check_mark:"
+ ERROR: "Command Failed, as expected :x:"
+ run: |
+ run-with-summary ping w3.org -c5 | tee -a $GITHUB_STEP_SUMMARY
diff --git a/README.md b/README.md
index af7193c..8e96223 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,85 @@
# goatscripts
Bash to basics.
-# Example
+These scripts are things I've been using in different places over the years.
+
+Help yourself.
+
+## Run With Summary
+
+`run-with-summary `
+
+Executes a command and prints a markdown summary.
+
+Useful for CI systems like GitHub Actions.
+
+## Examples
+
+```shell
+ run-with-summary ping w3.org -c5
+```
+
+To customize the report header text, show extra info in the table, or print the summary in the command run, use these env vars.
```shell
-run-with-summary ping google.com -c2
+SUCCESS="Deploy complete" \
+ERROR="Deploy failed" \
+DEBUG=1 \
+SUMMARY=1 \
+ run-with-summary deploy.sh
+```
+
+To output the results of a command to GitHub Actions summary, add this step to your workflow:
+
+```yaml
+- name: Deploy script
+ env:
+ SUCCESS: "Deploy complete"
+ ERROR: "Deploy failed"
+ SUMMARY: |
+ - Environment: https://pr${{ github.event.number }}.demo.site
+ - Pull Request: ${{github.event.pull_request.html_url }}
+
+ ${{ github.event.pull_request.title }}
+ ${{ github.event.pull_request.body }}
+
+ run: |
+ run-with-summary deploy.sh
```
-DEBUG=1 SUMMARY=1 ./src/run-with-summary ping google.com -c2
-PING google.com (142.250.81.238): 56 data bytes
-64 bytes from 142.250.81.238: icmp_seq=0 ttl=119 time=10.933 ms
-64 bytes from 142.250.81.238: icmp_seq=1 ttl=119 time=9.472 ms
-
---- google.com ping statistics ---
-2 packets transmitted, 2 packets received, 0.0% packet loss
-round-trip min/avg/max/stddev = 9.472/10.203/10.933/0.730 ms
-# Command executed
+
+
+Example Output
+
+# Command complete
+
+Any markdown at all can be put into the SUMMARY env var.
+
```
-ping google.com -c2
+ping w3.org -c5
```
```
-PING google.com (142.250.81.238): 56 data bytes
-64 bytes from 142.250.81.238: icmp_seq=0 ttl=119 time=10.933 ms
-64 bytes from 142.250.81.238: icmp_seq=1 ttl=119 time=9.472 ms
+PING w3.org (104.18.22.19): 56 data bytes
+64 bytes from 104.18.22.19: icmp_seq=0 ttl=59 time=9.480 ms
+64 bytes from 104.18.22.19: icmp_seq=1 ttl=59 time=13.510 ms
+64 bytes from 104.18.22.19: icmp_seq=2 ttl=59 time=12.989 ms
+64 bytes from 104.18.22.19: icmp_seq=3 ttl=59 time=15.017 ms
+64 bytes from 104.18.22.19: icmp_seq=4 ttl=59 time=13.225 ms
---- google.com ping statistics ---
-2 packets transmitted, 2 packets received, 0.0% packet loss
-round-trip min/avg/max/stddev = 9.472/10.203/10.933/0.730 ms
+--- w3.org ping statistics ---
+5 packets transmitted, 5 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = 9.480/12.844/15.017/1.825 ms
```
-| Command | `ping google.com -c2`
+| Command | `ping w3.org -c5`
|------------|-----------------------
| Exit Code | `0`
-| Start Time | 2025-10-02 21:10:48 EDT
-| End Time | 2025-10-02 21:10:49 EDT
-| Duration | 1s
+| Start Time | 2025-10-03 07:24:40 EDT
+| End Time | 2025-10-03 07:24:40 EDT
+| Duration | 4s
| User | jonpugh
| Host | macbookpro.lan
| Directory | /Users/jonpugh/Work/Operations/goatscripts
-Markdown report saved to /tmp/summary.md
\ No newline at end of file
+Markdown report saved to /tmp/summary.md
+
diff --git a/src/run-with-summary b/src/run-with-summary
index c6f7686..2058cb5 100755
--- a/src/run-with-summary
+++ b/src/run-with-summary
@@ -1,61 +1,74 @@
-#!/bin/bash
-
-# Customize the success and error messages.
-success_message=${SUCCESS:-"Command executed"}
-error_message=${ERROR:-"Command failed"}
-
-# Print extra stuff like user and hostname in the summary.
-debug=${DEBUG:-""}
-
-# Print the markdown summary after the command output.
-echo_summary=${SUMMARY:-""}
+#!/usr/bin/env bash
usage() {
cat <<'USAGE'
-Usage: run-with-summary [options] --
+Usage: run-with-summary
-Executes the given command, streams its output, and writes a Markdown summary to /tmp/summary.md.
+Executes the given command, streams its output, and writes a Markdown summary to $FILE.
Environment variables:
- SUCCESS Custom success heading (default: "Command executed").
- ERROR Custom error heading (default: "Command failed").
+ HEADING Custom text for the h1 tag. (default: "Running Command...")
+ SUMMARY Short text to display below the header.
+ SUCCESS Custom success message (default: "Command succeeded").
+ ERROR Custom error message (default: "Command failed").
DEBUG If set (non-empty), include User/Host/Directory in the summary.
- SUMMARY If set (non-empty), echo the Markdown summary to stdout after execution.
+ FILE Markdown report file (default: /tmp/summary.md
Examples:
- run-with-summary ls -la
- SUCCESS="Deploy complete" SUMMARY=1 run-with-summary -- make deploy
+ run-with-summary scripts/deploy.sh
+
+ HEADING="Deployment" \
+ SUMMARY="Deploy script running as an example." \
+ SUCCESS="Deploy successful! :rocket:" \
+ ERROR="DEPLOY FAILED! :x:" \
+ DEBUG=1 \
+ FILE=reports/$(date).md \
+ run-with-summary scripts/deploy.sh
+
USAGE
}
+set -e
+
+# Customize the success and error messages.
+command="$@"
+heading_message=${HEADING:-"Command executed"}
+summary=${SUMMARY:-"Started $(date)"}
+success_message=${SUCCESS:-"Command executed successfully."}
+error_message=${ERROR:-"Command failed"}
+
+# Print extra stuff like user and hostname in the summary.
+debug=${DEBUG:-""}
+
+# Print the markdown summary after the command output.
+temp_report_file=${FILE:-"/tmp/summary.md"}
+
+if [ -z "$command" ]; then
+ usage
+ exit 1
+fi
+
# Format output into markdown report
format_output() {
local command="$1"
- local output="$2"
- local exit_code="$3"
- local start_time="$4"
- local end_time="$5"
+ local exit_code="$2"
+ local start_time="$3"
+ local end_time="$4"
local duration=$((end_time - start_time))
+
+ local start_date=$(date -d "@$start_time" '+%Y-%m-%d %H:%M:%S %Z' 2>/dev/null || date -r $start_time '+%Y-%m-%d %H:%M:%S %Z')
+ local end_date=$(date -d "@$end_time" '+%Y-%m-%d %H:%M:%S %Z' 2>/dev/null || date -r $end_time '+%Y-%m-%d %H:%M:%S %Z')
- local heading_message="$error_message"
+ local message="$error_message"
if [ "$exit_code" -eq 0 ]; then
- heading_message="$success_message"
+ message="$success_message"
fi
- echo "# ${heading_message}"
- echo "\`\`\`"
- echo "$command"
- echo "\`\`\`"
- echo
- echo "\`\`\`"
- echo "$output"
- echo "\`\`\`"
- echo
echo "| Command | \`$command\`"
echo "|------------|-----------------------"
echo "| Exit Code | \`$exit_code\`"
- echo "| Start Time | $(date -r $start_time '+%Y-%m-%d %H:%M:%S %Z')"
- echo "| End Time | $(date -r $end_time '+%Y-%m-%d %H:%M:%S %Z')"
+ echo "| Start Time | $start_date"
+ echo "| End Time | $end_date"
echo "| Duration | ${duration}s"
if [[ -n $debug ]]; then
@@ -63,42 +76,42 @@ format_output() {
echo "| Host | $(hostname -f)"
echo "| Directory | $(pwd)"
fi
+ echo
+ echo $message
}
-# Get the command from arguments
-command="$@"
-# Secondary help guard: if exactly one argument and it is -h/--help, show usage and exit 0
-if [ "$command" = "-h" ] || [ "$command" = "--help" ]; then
- usage
- exit 0
-fi
-
-if [ -z "$command" ]; then
- usage
- exit 1
-fi
# Record start time
start_time=$(date '+%s')
# Execute command and show output in real time while capturing it
-echo "Executing: $command"
+# Use a temporary file to store output
+temp_output_file=$(mktemp)
+
+if [[ -n ${heading_message} ]]; then
+ echo "# ${heading_message}"
+fi
+
+if [[ -n ${summary} ]]; then
+ echo "${summary}"
+fi
+
+echo "\`\`\`"
+echo "$command"
+echo "\`\`\`"
+echo
+echo "\`\`\`"
+
set -o pipefail
-output=$(eval "$command" 2>&1 | tee >(cat >&2))
-exit_code=$?
+$command
+exit_code=${PIPESTATUS[0]}
+echo "\`\`\`"
-# Record end time
end_time=$(date '+%s')
# Generate markdown report
-formatted_output=$(format_output "$command" "$output" "$exit_code" "$start_time" "$end_time")
-echo "$formatted_output" > /tmp/summary.md
-
-if [[ -n $echo_summary ]]; then
- echo "$formatted_output"
-fi
-echo
-echo "Markdown report saved to /tmp/summary.md"
+format_output "$command" "$exit_code" "$start_time" "$end_time"
-exit "$exit_code"
\ No newline at end of file
+# Exit same as command.
+exit "$exit_code"