Auto Create PR on Main Push workflow (bowenliang123/markdown-exporter)
The Auto Create PR on Main Push workflow from bowenliang123/markdown-exporter, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Auto Create PR on Main Push workflow from the bowenliang123/markdown-exporter repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
# .github/workflows/auto-pr.yml
name: Auto Create PR on Main Push
on:
push:
branches: [ main ] # Trigger on push to main
jobs:
create_pr: # Renamed job for clarity
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Print working directory # Kept for debugging
run: |
pwd
ls -la
- name: Download CLI tool
run: |
# Create bin directory in runner temp
mkdir -p $RUNNER_TEMP/bin
cd $RUNNER_TEMP/bin
# Download CLI tool
wget https://github.com/langgenius/dify-plugin-daemon/releases/latest/download/dify-plugin-linux-amd64
chmod +x dify-plugin-linux-amd64
# Show download location and file
echo "CLI tool location:"
pwd
ls -la dify-plugin-linux-amd64
- name: Get basic info from manifest # Changed step name and content
id: get_basic_info
run: |
PLUGIN_NAME=$(grep "^name:" manifest.yaml | cut -d' ' -f2)
echo "Plugin name: $PLUGIN_NAME"
echo "plugin_name=$PLUGIN_NAME" >> $GITHUB_OUTPUT
VERSION=$(grep "^version:" manifest.yaml | cut -d' ' -f2)
echo "Plugin version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
# If the author's name is not your github username, you can change the author here
AUTHOR=$(grep "^author:" manifest.yaml | cut -d' ' -f2)
echo "Plugin author: $AUTHOR"
echo "author=$AUTHOR" >> $GITHUB_OUTPUT
- name: Package Plugin
id: package
run: |
# Use the downloaded CLI tool to package
cd $GITHUB_WORKSPACE
# Use variables for package name
PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg"
# Use CLI from runner temp
$RUNNER_TEMP/bin/dify-plugin-linux-amd64 plugin package . -o "$PACKAGE_NAME"
# Show packaging result
echo "Package result:"
ls -la "$PACKAGE_NAME"
echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
# Show full file path and directory structure (kept for debugging)
echo "\\nFull file path:"
pwd
echo "\\nDirectory structure:"
tree || ls -R
- name: Checkout target repo
uses: actions/checkout@v3
with:
# Use author variable for repository
repository: ${{steps.get_basic_info.outputs.author}}/dify-plugins
path: dify-plugins
token: ${{ secrets.PLUGIN_ACTION }}
fetch-depth: 1 # Fetch only the last commit to speed up checkout
persist-credentials: true # Persist credentials for subsequent git operations
- name: Prepare and create PR
run: |
# Debug info (kept)
echo "Debug: Current directory $(pwd)"
# Use variable for package name
PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg"
echo "Debug: Package name: $PACKAGE_NAME"
ls -la
# Move the packaged file to the target directory using variables
mkdir -p dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }}
mv "$PACKAGE_NAME" dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }}/
# Enter the target repository directory
cd dify-plugins
# Configure git
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
# Ensure we are on the latest main branch
git fetch origin main
git checkout main
git pull origin main
# Create and switch to a new branch using variables and new naming convention
BRANCH_NAME="bump-${{ steps.get_basic_info.outputs.plugin_name }}-plugin-${{ steps.get_basic_info.outputs.version }}"
git checkout -b "$BRANCH_NAME"
# Add and commit changes (using git add .)
git add .
git status # for debugging
# Use variables in commit message
git commit -m "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}"
# Push to remote (use force just in case the branch existed before from a failed run)
git push -u origin "$BRANCH_NAME" --force
# Confirm branch has been pushed and wait for sync (GitHub API might need a moment)
git branch -a
echo "Waiting for branch to sync..."
sleep 10 # Wait 10 seconds for branch sync
- name: Create PR via GitHub API
env:
GH_TOKEN: ${{ secrets.PLUGIN_ACTION }} # Use the provided token for authentication
run: |
gh pr create \
--repo langgenius/dify-plugins \
--head "${{ steps.get_basic_info.outputs.author }}:${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}" \
--base main \
--title "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}" \
--body "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin package to version ${{ steps.get_basic_info.outputs.version }}
Changes:
- Updated plugin package file" || echo "PR already exists or creation skipped." # Handle cases where PR already exists
- name: Print environment info # Kept for debugging
run: |
echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE"
echo "Current directory contents:"
ls -RThe same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
# .github/workflows/auto-pr.yml name: Auto Create PR on Main Push on: push: branches: [ main ] # Trigger on push to main concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: create_pr: # Renamed job for clarity timeout-minutes: 30 runs-on: latchkey-small steps: - name: Checkout code uses: actions/checkout@v3 - name: Print working directory # Kept for debugging run: | pwd ls -la - name: Download CLI tool run: | # Create bin directory in runner temp mkdir -p $RUNNER_TEMP/bin cd $RUNNER_TEMP/bin # Download CLI tool wget https://github.com/langgenius/dify-plugin-daemon/releases/latest/download/dify-plugin-linux-amd64 chmod +x dify-plugin-linux-amd64 # Show download location and file echo "CLI tool location:" pwd ls -la dify-plugin-linux-amd64 - name: Get basic info from manifest # Changed step name and content id: get_basic_info run: | PLUGIN_NAME=$(grep "^name:" manifest.yaml | cut -d' ' -f2) echo "Plugin name: $PLUGIN_NAME" echo "plugin_name=$PLUGIN_NAME" >> $GITHUB_OUTPUT VERSION=$(grep "^version:" manifest.yaml | cut -d' ' -f2) echo "Plugin version: $VERSION" echo "version=$VERSION" >> $GITHUB_OUTPUT # If the author's name is not your github username, you can change the author here AUTHOR=$(grep "^author:" manifest.yaml | cut -d' ' -f2) echo "Plugin author: $AUTHOR" echo "author=$AUTHOR" >> $GITHUB_OUTPUT - name: Package Plugin id: package run: | # Use the downloaded CLI tool to package cd $GITHUB_WORKSPACE # Use variables for package name PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg" # Use CLI from runner temp $RUNNER_TEMP/bin/dify-plugin-linux-amd64 plugin package . -o "$PACKAGE_NAME" # Show packaging result echo "Package result:" ls -la "$PACKAGE_NAME" echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT # Show full file path and directory structure (kept for debugging) echo "\\nFull file path:" pwd echo "\\nDirectory structure:" tree || ls -R - name: Checkout target repo uses: actions/checkout@v3 with: # Use author variable for repository repository: ${{steps.get_basic_info.outputs.author}}/dify-plugins path: dify-plugins token: ${{ secrets.PLUGIN_ACTION }} fetch-depth: 1 # Fetch only the last commit to speed up checkout persist-credentials: true # Persist credentials for subsequent git operations - name: Prepare and create PR run: | # Debug info (kept) echo "Debug: Current directory $(pwd)" # Use variable for package name PACKAGE_NAME="${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}.difypkg" echo "Debug: Package name: $PACKAGE_NAME" ls -la # Move the packaged file to the target directory using variables mkdir -p dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }} mv "$PACKAGE_NAME" dify-plugins/${{ steps.get_basic_info.outputs.author }}/${{ steps.get_basic_info.outputs.plugin_name }}/ # Enter the target repository directory cd dify-plugins # Configure git git config user.name "GitHub Actions" git config user.email "actions@github.com" # Ensure we are on the latest main branch git fetch origin main git checkout main git pull origin main # Create and switch to a new branch using variables and new naming convention BRANCH_NAME="bump-${{ steps.get_basic_info.outputs.plugin_name }}-plugin-${{ steps.get_basic_info.outputs.version }}" git checkout -b "$BRANCH_NAME" # Add and commit changes (using git add .) git add . git status # for debugging # Use variables in commit message git commit -m "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}" # Push to remote (use force just in case the branch existed before from a failed run) git push -u origin "$BRANCH_NAME" --force # Confirm branch has been pushed and wait for sync (GitHub API might need a moment) git branch -a echo "Waiting for branch to sync..." sleep 10 # Wait 10 seconds for branch sync - name: Create PR via GitHub API env: GH_TOKEN: ${{ secrets.PLUGIN_ACTION }} # Use the provided token for authentication run: | gh pr create \ --repo langgenius/dify-plugins \ --head "${{ steps.get_basic_info.outputs.author }}:${{ steps.get_basic_info.outputs.plugin_name }}-${{ steps.get_basic_info.outputs.version }}" \ --base main \ --title "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin to version ${{ steps.get_basic_info.outputs.version }}" \ --body "bump ${{ steps.get_basic_info.outputs.plugin_name }} plugin package to version ${{ steps.get_basic_info.outputs.version }} Changes: - Updated plugin package file" || echo "PR already exists or creation skipped." # Handle cases where PR already exists - name: Print environment info # Kept for debugging run: | echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE" echo "Current directory contents:" ls -R
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Add a job timeout so a hung step cannot burn hours of runner time.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Network fetches
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.