Skip to content

Instantly share code, notes, and snippets.

@Fleshgrinder
Last active October 6, 2022 14:45
Show Gist options
  • Save Fleshgrinder/3a1f00b2d10e8ca8612d70a0b5b453a7 to your computer and use it in GitHub Desktop.
Save Fleshgrinder/3a1f00b2d10e8ca8612d70a0b5b453a7 to your computer and use it in GitHub Desktop.

Revisions

  1. Fleshgrinder revised this gist Oct 6, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gh-delete-workflow.sh
    Original file line number Diff line number Diff line change
    @@ -93,7 +93,7 @@ case ${#workflow_names[@]} in

    1)
    readonly workflow_name=${workflow_names[0]}
    readonly workflow_path=${workflow_path[0]}
    readonly workflow_path=${workflow_paths[0]}
    readonly workflow_id=${workflow_ids[0]}
    printf 'There is only one workflow %b%s %b(%s)%b...\n' "$CYAN" "$workflow_name" "$DIM" "$workflow_id" "$RESET"
    ;;
  2. Fleshgrinder revised this gist Sep 28, 2022. 2 changed files with 5 additions and 4 deletions.
    4 changes: 0 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +0,0 @@
    There is no button in the interface of GitHub (and as it seems also no API) with which workflows can be deleted.
    They are eventually removed automatically, but in case you want to clean up your Actions UI it is sometimes nice
    to have the possibility to get rid of workflows that are not required anymore. This interactive script allows you
    to achieve exactly that by deleting each individual run of a workflow, after which GitHub deletes the workflow.
    5 changes: 5 additions & 0 deletions gh-delete-workflow.sh
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,11 @@
    #!/usr/bin/env bash
    set -Eeuo pipefail

    # There is no button in the interface of GitHub (and as it seems also no API) with which workflows can be deleted.
    # They are eventually removed automatically, but in case you want to clean up your Actions UI it is sometimes nice
    # to have the possibility to get rid of workflows that are not required anymore. This interactive script allows you
    # to achieve exactly that by deleting each individual run of a workflow, after which GitHub deletes the workflow.

    declare -ir CONCURRENCY=${CONCURRENCY:-8}

    # region https://no-color.org/
  3. Fleshgrinder revised this gist Sep 28, 2022. No changes.
  4. Fleshgrinder revised this gist Feb 23, 2022. 1 changed file with 10 additions and 9 deletions.
    19 changes: 10 additions & 9 deletions gh-delete-workflow.sh
    Original file line number Diff line number Diff line change
    @@ -27,11 +27,10 @@ fi

    dry_run=false
    yes=false
    for arg in "$@"; do
    case "$arg" in
    while (($# > 0)); do
    case "$1" in
    -d | --dry-run)
    dry_run=true
    shift
    ;;

    -h | --help)
    @@ -53,20 +52,19 @@ HELP

    -y | --yes)
    yes=true
    shift
    ;;

    --)
    break
    ;;
    -*)
    printf -- '%bUnknown option: %s%b\n' "$RED" "$arg" "$RESET"
    shift
    printf -- '%bUnknown option: %s%b\n' "$RED" "$1" "$RESET"
    ;;
    *)
    break
    ;;
    esac
    shift
    done
    readonly dry_run yes

    @@ -76,10 +74,11 @@ if ! command -v gh &>/dev/null; then
    fi

    workflow_names=()
    workflow_paths=()
    workflow_ids=()
    while read -r workflow; do
    eval "$workflow"
    done < <(gh api '/repos/{owner}/{repo}/actions/workflows' --jq '.workflows |= sort_by(.name) | .workflows[] | "workflow_names+=('"'"'\(.name)'"'"');workflow_ids+=(\(.id))"')
    done < <(gh api '/repos/{owner}/{repo}/actions/workflows' --jq '.workflows |= sort_by(.name) | .workflows[] | "workflow_names+=('"'"'\(.name)'"'"');workflow_paths+=('"'"'\(.path)'"'"');workflow_ids+=(\(.id))"')

    case ${#workflow_names[@]} in
    0)
    @@ -89,13 +88,14 @@ case ${#workflow_names[@]} in

    1)
    readonly workflow_name=${workflow_names[0]}
    readonly workflow_path=${workflow_path[0]}
    readonly workflow_id=${workflow_ids[0]}
    printf 'There is only one workflow %b%s %b(%s)%b...\n' "$CYAN" "$workflow_name" "$DIM" "$workflow_id" "$RESET"
    ;;

    *)
    for ((i = 0; i < ${#workflow_names[@]}; i++)); do
    printf -- '%b[%i]%b %s %b(%s)%b\n' "$CYAN" $((i + 1)) "$RESET" "${workflow_names[$i]}" "$DIM" "${workflow_ids[$i]}" "$RESET_DIM"
    printf -- '%b[%i]%b %s %b%s (%s)%b\n' "$CYAN" $((i + 1)) "$RESET" "${workflow_names[$i]}" "$DIM" "${workflow_paths[$i]}" "${workflow_ids[$i]}" "$RESET_DIM"
    done

    while :; do
    @@ -113,14 +113,15 @@ case ${#workflow_names[@]} in
    done

    readonly workflow_name=${workflow_names[$selection]}
    readonly workflow_path=${workflow_paths[$selection]}
    readonly workflow_id=${workflow_ids[$selection]}
    ;;
    esac
    unset workflow_names workflow_ids

    if [[ "$dry_run" == false && "$yes" == false ]]; then
    # shellcheck disable=SC2016
    printf -- 'Are you sure you want to delete workflow %b%s %b(%s)%b? %bYou cannot recover from this!%b [y/n] ' "$CYAN" "$workflow_name" "$DIM" "$workflow_id" "$RESET" "$RED" "$RESET"
    printf -- 'Are you sure you want to delete workflow %b%s %b%s (%s)%b? %bYou cannot recover from this!%b [y/n] ' "$CYAN" "$workflow_name" "$DIM" "$workflow_path" "$workflow_id" "$RESET" "$RED" "$RESET"
    read -rN1 reply
    if [[ "$reply" != y ]]; then
    case "$reply" in
  5. Fleshgrinder revised this gist Feb 7, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gh-delete-workflow.sh
    Original file line number Diff line number Diff line change
    @@ -38,7 +38,7 @@ for arg in "$@"; do
    cat <<HELP
    Delete GitHub Actions Workflows from this repository.
    Usage: gh-delete-workflow (-h|--help)
    Usage: gh-delete-workflow [option]...
    Options:
    -d --dry-run Print what would be deleted, but do not delete anything.
  6. Fleshgrinder created this gist Feb 7, 2022.
    4 changes: 4 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,4 @@
    There is no button in the interface of GitHub (and as it seems also no API) with which workflows can be deleted.
    They are eventually removed automatically, but in case you want to clean up your Actions UI it is sometimes nice
    to have the possibility to get rid of workflows that are not required anymore. This interactive script allows you
    to achieve exactly that by deleting each individual run of a workflow, after which GitHub deletes the workflow.
    151 changes: 151 additions & 0 deletions gh-delete-workflow.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,151 @@
    #!/usr/bin/env bash
    set -Eeuo pipefail

    declare -ir CONCURRENCY=${CONCURRENCY:-8}

    # region https://no-color.org/
    if [[ "${NO_COLOR:-}" == '' ]]; then
    readonly RESET='\033[0m'
    readonly DIM='\033[2m'
    readonly RESET_DIM='\033[22m'
    readonly BOLD='\033[1m'
    readonly RESET_BOLD='\033[22m'
    readonly CYAN='\033[36m'
    readonly RED='\033[31m'
    readonly GREEN='\033[32m'
    else
    readonly RESET=
    readonly DIM=
    readonly RESET_DIM=
    readonly BOLD=
    readonly RESET_BOLD=
    readonly CYAN=
    readonly RED=
    readonly GREEN=
    fi
    # endregion

    dry_run=false
    yes=false
    for arg in "$@"; do
    case "$arg" in
    -d | --dry-run)
    dry_run=true
    shift
    ;;

    -h | --help)
    cat <<HELP
    Delete GitHub Actions Workflows from this repository.
    Usage: gh-delete-workflow (-h|--help)
    Options:
    -d --dry-run Print what would be deleted, but do not delete anything.
    -h --help Show this help and exit.
    -y --yes I know what I am doing, stop asking me questions!
    Environment:
    CONCURRENCY=$CONCURRENCY Sets the concurrency level for requests.
    HELP
    exit 0
    ;;

    -y | --yes)
    yes=true
    shift
    ;;

    --)
    break
    ;;
    -*)
    printf -- '%bUnknown option: %s%b\n' "$RED" "$arg" "$RESET"
    shift
    ;;
    *)
    break
    ;;
    esac
    done
    readonly dry_run yes

    if ! command -v gh &>/dev/null; then
    printf -- '%bCould not find gh in PATH, make sure it is available: https://cli.github.com/%b\n' "$RED" "$RESET" >&2
    exit 1
    fi

    workflow_names=()
    workflow_ids=()
    while read -r workflow; do
    eval "$workflow"
    done < <(gh api '/repos/{owner}/{repo}/actions/workflows' --jq '.workflows |= sort_by(.name) | .workflows[] | "workflow_names+=('"'"'\(.name)'"'"');workflow_ids+=(\(.id))"')

    case ${#workflow_names[@]} in
    0)
    echo 'Nothing to delete, this repository does not have any workflows.'
    exit 0
    ;;

    1)
    readonly workflow_name=${workflow_names[0]}
    readonly workflow_id=${workflow_ids[0]}
    printf 'There is only one workflow %b%s %b(%s)%b...\n' "$CYAN" "$workflow_name" "$DIM" "$workflow_id" "$RESET"
    ;;

    *)
    for ((i = 0; i < ${#workflow_names[@]}; i++)); do
    printf -- '%b[%i]%b %s %b(%s)%b\n' "$CYAN" $((i + 1)) "$RESET" "${workflow_names[$i]}" "$DIM" "${workflow_ids[$i]}" "$RESET_DIM"
    done

    while :; do
    printf -- '%bWhich workflow [1..%i]? ' "$CYAN" ${#workflow_names[@]}
    read -r selection
    if ((1 <= selection && selection <= ${#workflow_names[@]})); then
    printf -- "%b" "$RESET"
    ((selection--))
    readonly selection
    break
    else
    # shellcheck disable=SC2016
    printf -- '%bSelection `%s` is invalid, %bMUST%b be one of [1..%i], try again...%b\n' "$RED" "$selection" "$BOLD" "$RESET_BOLD" "${#workflow_names[@]}" "$RESET" >&2
    fi
    done

    readonly workflow_name=${workflow_names[$selection]}
    readonly workflow_id=${workflow_ids[$selection]}
    ;;
    esac
    unset workflow_names workflow_ids

    if [[ "$dry_run" == false && "$yes" == false ]]; then
    # shellcheck disable=SC2016
    printf -- 'Are you sure you want to delete workflow %b%s %b(%s)%b? %bYou cannot recover from this!%b [y/n] ' "$CYAN" "$workflow_name" "$DIM" "$workflow_id" "$RESET" "$RED" "$RESET"
    read -rN1 reply
    if [[ "$reply" != y ]]; then
    case "$reply" in
    n) response='\nOK' ;;
    $'\n') response='You did not enter anything' ;;
    *) response='\nAssuming you meant n' ;;
    esac
    printf -- '%b%b, aborting...%b\n' "$RED" "$response" "$RESET"
    exit 0
    fi
    unset reply
    echo
    fi

    i=0
    while read -r run_id; do
    if [[ "$dry_run" == true ]]; then
    printf -- '%b💀 run %s%b\n' "$RED" "$run_id" "$RESET"
    else
    gh api -X DELETE "/repos/{owner}/{repo}/actions/runs/$run_id" &
    fi
    if ((++i == CONCURRENCY)); then
    i=0
    wait
    fi
    done < <(gh api --paginate "/repos/{owner}/{repo}/actions/workflows/$workflow_id/runs" --jq '.workflow_runs[] | .id')
    wait
    printf -- '%bDone%b\n' "$GREEN" "$RESET"