Skip to content

Create configlet-sync.yml #212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jun 29, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/configlet-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Configlet Auto Sync

on:
workflow_call:

jobs:
sync-docs-metadata:
timeout-minutes: 10
runs-on: ubuntu-24.04

steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

- name: Fetch configlet
run: ./bin/fetch-configlet

- name: Run configlet sync for files
run: ./bin/configlet sync --docs --metadata --filepaths -u -y

- name: Create pull request if changes
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "🤖 Auto-sync docs, metadata, and filepaths"
title: "🤖 Configlet sync: docs, metadata, and filepaths"
body: |
This PR was generated automatically by a scheduled workflow.

It includes updates from `configlet sync` for:
- 📄 Documentation
- 🧭 Metadata
- 🗂️ Filepaths

Please review and merge if everything looks good!
branch: configlet-auto-sync
delete-branch: true

check-test-sync:
timeout-minutes: 10
runs-on: ubuntu-24.04

steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

- name: Fetch configlet
run: ./bin/fetch-configlet

- name: Run configlet sync for test and capture output
id: sync_test
shell: bash {0}
run: |
configlet_raw_output="$(./bin/configlet sync --tests)"
exit_code=$?
printf "exit_code=%d\n" "$exit_code" >> "$GITHUB_OUTPUT"
printf "output<<EOF\n%s\nEOF\n" "$configlet_raw_output" >> "$GITHUB_OUTPUT"
printf "configlet output:\n%s\n" "$configlet_raw_output"
Comment on lines +52 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to turn off set -e via a custom shell entry. Bash under set -e can handle commands whose non-zero exit code is handled by the calling script and therefore not considered an unexpected failure that should lead to termination (which is what set -e is for). Just use some conditional statement such as if to use this. I believe here it would even increase readability, because instead of storing the raw exit code, you could save a boolean with a better name and use that below.

Suggested change
shell: bash {0}
run: |
configlet_raw_output="$(./bin/configlet sync --tests)"
exit_code=$?
printf "exit_code=%d\n" "$exit_code" >> "$GITHUB_OUTPUT"
printf "output<<EOF\n%s\nEOF\n" "$configlet_raw_output" >> "$GITHUB_OUTPUT"
printf "configlet output:\n%s\n" "$configlet_raw_output"
run: |
if configlet_raw_output="$(./bin/configlet sync --tests)"; then
printf "unsynced_tests_found=false\n" >> "$GITHUB_OUTPUT"
else
printf "unsynced_tests_found=true\n" >> "$GITHUB_OUTPUT"
printf "output<<EOF\n%s\nEOF\n" "$configlet_raw_output" >> "$GITHUB_OUTPUT"
fi
printf "configlet output:\n%s\n" "$configlet_raw_output"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implies that the string "true" or "false" is better than 0 or 1 somehow. This is when m shell code. Shell exit codes are very well understood. This also adds more code and sets up additional outputs that may or may not be set. I'm not sure this approach is necessarily better or more readable.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, you can split the handling of configlet's exit code and writing to $GITHUB_OUTPUT:

Suggested change
shell: bash {0}
run: |
configlet_raw_output="$(./bin/configlet sync --tests)"
exit_code=$?
printf "exit_code=%d\n" "$exit_code" >> "$GITHUB_OUTPUT"
printf "output<<EOF\n%s\nEOF\n" "$configlet_raw_output" >> "$GITHUB_OUTPUT"
printf "configlet output:\n%s\n" "$configlet_raw_output"
run: |
if configlet_raw_output="$(./bin/configlet sync --tests)"; then
unsynced_tests_found="false"
else
unsynced_tests_found="true"
fi
printf "unsynced_tests_found=%s\n" "$unsynced_tests_found" >> "$GITHUB_OUTPUT"
printf "output<<EOF\n%s\nEOF\n" "$configlet_raw_output" >> "$GITHUB_OUTPUT"
printf "configlet output:\n%s\n" "$configlet_raw_output"

This would add configlet's output to $GITHUB_OUTPUT even if it is not used, but for better readability would be acceptable (it's also what your current implementation does).

If you find the if ... then ... else ... fi too verbose, I think something like this instead would also count as idiomatic Bash code (the exception about set -e in conditionals holds here as well):

Suggested change
shell: bash {0}
run: |
configlet_raw_output="$(./bin/configlet sync --tests)"
exit_code=$?
printf "exit_code=%d\n" "$exit_code" >> "$GITHUB_OUTPUT"
printf "output<<EOF\n%s\nEOF\n" "$configlet_raw_output" >> "$GITHUB_OUTPUT"
printf "configlet output:\n%s\n" "$configlet_raw_output"
run: |
unsynced_tests_found="false"
configlet_raw_output="$(./bin/configlet sync --tests)" || unsynced_tests_found="true"
printf "unsynced_tests_found=%s\n" "$unsynced_tests_found" >> "$GITHUB_OUTPUT"
printf "output<<EOF\n%s\nEOF\n" "$configlet_raw_output" >> "$GITHUB_OUTPUT"
printf "configlet output:\n%s\n" "$configlet_raw_output"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using $? is also perfectly readable and idiomatic bash 🙂

Copy link

@ahans ahans Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implies that the string "true" or "false" is better than 0 or 1 somehow.

When used as a boolean in a GH actions workflow, it is better, because boolean exists as a datatype and anything else is coerced when used in a boolean expression (this is what the if:s in the subsequent steps are), see here. Directly saying true or false avoids this coercion.

Shell exit codes are very well understood.

Sure, but besides success being zero and non-success something else, it depends on the tool. Without knowing configlet, from this snippet alone I would not know that a non-zero exit code means there are unsynced tests. I would have to read the rest of the workflow file to learn that. Using a more descriptive key than exit_code does convey more information.

This also adds more code

More code is not necessarily worse if it's easy to read. Even somebody with little Bash experience would know what the if ... then ... else ... fi does. As an alternative, I suggested the option with the || shortcut that adds less code.

and sets up additional outputs that may or may not be set.

Not true. I replaced one output (exit_code) with another (unsynced_tests_found). The statement about maybe being set or not applies just as well to exit_code.

I'm not sure this approach is necessarily better or more readable.

I guess that depends on perspective. Ultimately it was just a suggestion.

My main point was that it is not necessarily to override GH's reasonable set -e default. That you can use more descriptive variable names in the process was an added benefit, IMHO at least.

(Edit: Many typos fixed.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set -e as a reasonable default is also a matter of debate. See https://mywiki.wooledge.org/BashFAQ/105


- name: Format test sync output and find existing issue
id: find_issue
if: ${{ steps.sync_test.outputs.exit_code != 0 }}
Copy link

@ahans ahans Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you go with my suggestion, this would become:

Suggested change
if: ${{ steps.sync_test.outputs.exit_code != 0 }}
if: ${{ steps.sync_test.outputs.unsynced_tests_found }}

env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
printf '```\n%s\n```\n' "${{ steps.sync_test.outputs.output }}" > /tmp/sync-test-output.txt

ISSUE_TITLE="🚨 configlet sync --test found unsynced tests"
ISSUE_DATA=$(gh issue list --search "is:issue is:open in:title \"${ISSUE_TITLE}\" repo:${{ github.repository }}" --json number,title --jq '.[0]')

if [[ -z "$ISSUE_DATA" ]]; then
printf "No open issue found with title: '%s'. A new one will be created.\n" "${ISSUE_TITLE}"
printf "issue_number=\n" >> "$GITHUB_OUTPUT"
else
ISSUE_NUMBER=$(jq -r '.number' <<< "$ISSUE_DATA")
printf "Found existing issue number: %s for title: %s\n" "$ISSUE_NUMBER" "$ISSUE_TITLE"
printf "issue_number=%s\n" "$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
fi

- name: Create or Update issue if tests are not synced
if: ${{ steps.sync_test.outputs.exit_code != 0 }}
Copy link

@ahans ahans Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dito:

Suggested change
if: ${{ steps.sync_test.outputs.exit_code != 0 }}
if: ${{ steps.sync_test.outputs.unsynced_tests_found }}

uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: "🚨 configlet sync --test found unsynced tests"
content-filepath: /tmp/sync-test-output.txt
issue-number: ${{ steps.find_issue.outputs.issue_number || '' }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will steps.find_issue.outputs.issue_number ever be unset?