Skip to content

Update actionlint Workflow #239

Update actionlint Workflow

Update actionlint Workflow #239

name: Update actionlint Workflow
# Overview: This GitHub Actions workflow is designed to update the actionlint workflow and configuration files by pulling the latest version from the Homebrew/brew repository. It runs on a schedule and can also be triggered manually.
on:
schedule:
# Run daily at midnight UTC
- cron: '0 0 * * *'
# Allow running manually
# For more details: https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow?tool=webui
workflow_dispatch:
env:
repository_owner: PikachuEXE
# NOTE: Using Homebrew/homebrew-core’s actionlint workflow and configuration for this tap, after evaluating alternatives in Homebrew/brew and Homebrew/actions. Homebrew/homebrew-core’s workflow—leveraging a Docker container—was the only fully functional option, likely due to its preconfigured environment.
source_repository_path: "Homebrew/homebrew-core"
source_repository_branch: master
jobs:
update-workflow:
runs-on: macos-14
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Get Latest Workflow and Configuration from ${{ env.source_repository_path }}
run: |
# Download actionlint workflow and configuration
echo "Getting the latest actionlint workflow and configuration from ${{ env.source_repository_path }} repository."
# Use raw GitHub download for its strong ETag, an HTTP header identifying a resource’s version.
# GitHub API provides a weak ETag.
# Both lack useful last-modified (curl --remote-time) and content-disposition (curl --remote-header-name) HTTP headers.
# Specify file details
file_paths=(
".github/actionlint.yaml" # actionlint configuration
".github/workflows/actionlint.yml" # actionlint workflow file
)
# Iterate over file paths
for file_path in "${file_paths[@]}"; do
# Construct the ETag file path
directory_path="${file_path%/*}"
base_name="${file_path##*/}"
# Replace hyphen and dot with underscore in the basename
transformed_base_name="${base_name//[-.]/_}"
# Determine the prefix based on the directory path
case "$directory_path" in
*".github/workflows")
prefix="ghw"
;;
*".github")
prefix="gh"
;;
*)
# Provide a default value for unexpected cases
prefix="unexpected"
;;
esac
etag_file_path=".github/etags/${prefix}_$transformed_base_name.txt"
# Save the current ETag value before downloading
if [ -r "$etag_file_path" ]; then
previous_etag=$(< "$etag_file_path")
else
# Remove any existing unreadable ETag file
rm -f "$etag_file_path"
# Ensure that the ETag directory exists
mkdir -p ".github/etags"
previous_etag=""
fi
# Download the file only if its ETag has changed
if ! curl --fail --silent --show-error --location \
--retry 3 --retry-all-errors \
--etag-save "$etag_file_path" \
--output "/dev/null" \
--url "https://raw.githubusercontent.com/${{ env.source_repository_path }}/${{ env.source_repository_branch }}/$file_path"; then
echo "Error saving ETag for $file_path."
echo "::error::cURL error: Failed to save ETag for $file_path."
exit 1 # Exit with an error code to fail the workflow
fi
if ! curl --fail --silent --show-error --location \
--retry 3 --retry-all-errors --remove-on-error \
--etag-compare "$etag_file_path" \
--remote-name --clobber \
--output-dir "$directory_path" --create-dirs \
--url "https://raw.githubusercontent.com/${{ env.source_repository_path }}/${{ env.source_repository_branch }}/$file_path"; then
echo "Error downloading $file_path from ${{ env.source_repository_path }} repository."
echo "::error::cURL error: Failed to download $file_path."
exit 1 # Exit with an error code to fail the workflow
fi
# Read the ETag value after downloading
current_etag=$(< "$etag_file_path")
# Check that the ETag value is nonempty
if test -n "$current_etag"; then
echo "current_etag exists and is non-empty. Continuing..."
else
echo "current_etag is empty or does not exist. Exiting..."
exit 1 # Exit with an error code to fail the workflow
fi
# Check if the ETag values differ
if [ "$previous_etag" != "$current_etag" ]; then
echo "$file_path was downloaded."
# Export variable for the processing steps
echo "${prefix}_${transformed_base_name}_downloaded=true" >> "$GITHUB_ENV"
else
echo "$file_path up-to-date. No changes detected."
# Export variable for the processing steps
echo "${prefix}_${transformed_base_name}_downloaded=false" >> "$GITHUB_ENV"
fi
done
echo "All files up-to-date or downloaded successfully."
- name: Update Repository Owner Check in actionlint Workflow
run: |
if [ "${ghw_actionlint_yml_downloaded}" = "true" ]; then
echo "Updating repository owner in actionlint workflow."
# Replace 'Homebrew' with 'PikachuEXE' in .github/workflows/actionlint.yml
file=".github/workflows/actionlint.yml"
# Check the current state of the condition before attempting a substitution
expected_condition="github.repository_owner == 'Homebrew'"
current_upstream_condition="$(yq eval '.jobs.workflow_syntax.if' "$file")"
# Isolate the repository owner name:
# yq eval '.jobs.workflow_syntax.if' "$file" | sed -n "s/.*github.repository_owner == '\(.*\)'.*/\1/p"
# Warn and overwrite if condition is unexpected
if [ "$current_upstream_condition" != "$expected_condition" ]; then
# Use GitHub Actions annotation
line="$(yq eval '.jobs.workflow_syntax.if | line' "$file")"
echo "::warning file=${file},line=${line}::Unexpected 'workflow_syntax' condition in downloaded workflow"
echo "Upstream: $current_upstream_condition"
echo "Expected: $expected_condition"
# Replace entire condition
if ! yq eval ".jobs.workflow_syntax.if = \"github.repository_owner == '${{ env.repository_owner }}'\"" "$file" --inplace --exit-status; then
echo "ERROR: An error occurred during the yq operation in 'workflow_syntax' step."
exit 1 # Exit with an error code to fail the workflow
fi
# Continue with substitution if condition is as expected
else
if ! yq eval '.jobs.workflow_syntax.if |= sub("Homebrew"; "${{ env.repository_owner }}")' "$file" --inplace --exit-status; then
echo "ERROR: An error occurred during the yq operation in 'workflow_syntax' step."
exit 1 # Exit with an error code to fail the workflow
fi
fi
echo "Repository Owner Check substitution successful."
fi
- name: Get Token
id: get_workflow_token
uses: peter-murray/workflow-application-token-action@v4
with:
application_id: ${{ secrets.APPLICATION_ID }}
application_private_key: ${{ secrets.APPLICATION_PRIVATE_KEY }}
revoke_token: true
- name: Create Pull Request
id: create-pr
uses: peter-evans/create-pull-request@v7
with:
token: "${{ steps.get_workflow_token.outputs.token }}"
commit-message: '[create-pull-request] Update actionlint workflow'
delete-branch: true
title: 'Update actionlint workflow'
body: |
Updated actionlint workflow and/or configuration.
- Pulled the latest version from the [Homebrew/homebrew-core][hc] repository
- Auto-generated by [create-pull-request][cpr]
[hc]:
https://github.com/Homebrew/homebrew-core
(https://github.com/Homebrew/homebrew-core)
[cpr]:
https://github.com/peter-evans/create-pull-request
(https://github.com/peter-evans/create-pull-request)
labels: |
actionlint
workflow-update
automated pr
- name: Display PR Information
if: ${{ steps.create-pr.outputs.pull-request-number }}
run: |
echo "${{ steps.create-pr.outputs.pull-request-operation }} Pull Request Number: ${{ steps.create-pr.outputs.pull-request-number }}"
echo "Pull Request URL: ${{ steps.create-pr.outputs.pull-request-url }}"
- name: Goodbye Message
run: echo "Workflow completed. Goodbye!"