├── .github ├── FUNDING.yml └── workflows │ ├── check.php │ ├── examples │ ├── edd.yml │ ├── events-calendar-pro.yml │ ├── facetwp.yml │ ├── gravityforms.yml │ └── gravityformsaddon.yml │ └── update.yml ├── .gitignore ├── README.md └── composer.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: sterner-stuff 4 | -------------------------------------------------------------------------------- /.github/workflows/check.php: -------------------------------------------------------------------------------- 1 | get_metadata()['version']; -------------------------------------------------------------------------------- /.github/workflows/examples/edd.yml: -------------------------------------------------------------------------------- 1 | name: Easy Digital Downloads Updater 2 | 3 | # Run this workflow twice daily 4 | on: 5 | # schedule: 6 | # - cron: '0 */12 * * *' 7 | workflow_dispatch: 8 | 9 | env: 10 | 11 | # The Easy Digital Downloads Item ID (example: searchwp's item ID is 216029) 12 | ITEM_ID: 123456 13 | 14 | # The URL of the vendor using EDD (example: https://searchwp.com) 15 | VENDOR_URL: https://example.com 16 | 17 | # A valid URL that your purchase is registered to in EDD 18 | ACTIVATION_URL: ${{github.server_url}}/${{github.repository}} 19 | 20 | ## SearchWP Example 21 | # ITEM_ID: 216029 22 | # VENDOR_URL: https://searchwp.com 23 | # ACTIVATION_URL: ${{github.server_url}}/${{github.repository}} 24 | 25 | jobs: 26 | update-plugin: 27 | name: Fetch and check versions 28 | runs-on: ubuntu-latest 29 | 30 | steps: 31 | 32 | # Checkout repo 33 | - name: Checkout repo 34 | uses: actions/checkout@v3 35 | with: 36 | fetch-depth: 0 37 | 38 | # Use EDD API to find download link for latest version, using the EDD item ID (different for every plugin) 39 | - name: Get download link from EDD 40 | id: EDDResponse 41 | uses: fjogeleit/http-request-action@master 42 | with: 43 | url: '${{ env.VENDOR_URL }}/?edd_action=get_version&item_id=${{ env.ITEM_ID }}&license=${{secrets.LICENSE_KEY}}&url=${{ env.ACTIVATION_URL }}' 44 | 45 | # Fetch latest version of SearchWP to download 46 | - name: Fetch 47 | run: wget '${{fromJson(steps.EDDResponse.outputs.response).package}}' -O package.zip 48 | 49 | # Set up PHP 50 | - name: 'Setup PHP' 51 | uses: shivammathur/setup-php@v2 52 | with: 53 | php-version: '8.0' 54 | 55 | # Install composer dependencies 56 | - name: Composer 57 | shell: bash 58 | run: 'composer install' 59 | 60 | # Get the current plugin version 61 | - name: 'Get Previous tag' 62 | id: previous_version 63 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 64 | 65 | # Get new plugin version 66 | - name: 'Get version' 67 | id: new_version 68 | shell: bash 69 | run: echo "new_version=$(php .github/workflows/check.php)" >> $GITHUB_OUTPUT 70 | 71 | # Configure git user 72 | - name: 'Git config' 73 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 74 | shell: bash 75 | run: | 76 | git config user.name "GitHub Actions" 77 | git config user.email noreply@github.com 78 | 79 | # Compare versions 80 | - name: 'Clean' 81 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 82 | shell: bash 83 | run: find . -maxdepth 1 \( -name 'package.zip' -o -name 'composer.json' -o -name 'composer.lock' -o -name '.gitignore' -o -path './.git' -o -path './.github' \) -prune -o -exec rm -rf {} \; 84 | 85 | # Unzip the package 86 | - name: Unzip 87 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 88 | uses: TonyBogdanov/zip@1.0 89 | with: 90 | args: unzip -qq ./package.zip -d . 91 | 92 | # You may not need this step depending on the contents of the zip 93 | - name: Move 94 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 95 | shell: bash 96 | run: shopt -s dotglob && sudo mv ${{ env.PACKAGE_SLUG }}/* . 97 | 98 | - name: rm 99 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 100 | shell: bash 101 | run: rm package.zip && rm -rf ${{ env.PACKAGE_SLUG }} 102 | 103 | - name: Commit 104 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 105 | id: make-commit 106 | shell: bash 107 | run: | 108 | git add . 109 | git commit -m '${{ steps.new_version.outputs.new_version }}' 110 | echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 111 | 112 | - name: Push 113 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 114 | shell: bash 115 | run: | 116 | git push 117 | git tag ${{ steps.new_version.outputs.new_version }} 118 | git push --tags 119 | -------------------------------------------------------------------------------- /.github/workflows/examples/events-calendar-pro.yml: -------------------------------------------------------------------------------- 1 | name: Updater 2 | 3 | # Run this workflow twice daily 4 | on: 5 | # schedule: 6 | # - cron: '0 */12 * * *' 7 | workflow_dispatch: 8 | 9 | env: 10 | PACKAGE_SLUG: events-calendar-pro 11 | 12 | jobs: 13 | # Set the job key. The key is displayed as the job name 14 | # when a job name is not provided 15 | update: 16 | # Name the Job 17 | name: Fetch and check versions 18 | # Set the type of machine to run on 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout repo 23 | uses: actions/checkout@v3 24 | with: 25 | fetch-depth: 0 26 | 27 | # Fetch latest version 28 | - name: Fetch 29 | run: wget 'https://pue.tri.be/api/plugins/v2/download?plugin=events-calendar-pro&key=${{secrets.TEC_KEY}}' -O package.zip 30 | 31 | # PHP 32 | - name: 'Setup PHP' 33 | uses: shivammathur/setup-php@v2 34 | with: 35 | php-version: '8.0' 36 | 37 | # Install dependencies 38 | - name: Composer 39 | run: 'composer install' 40 | 41 | # Get current tag 42 | - name: 'Get Previous tag' 43 | id: previous_version 44 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 45 | 46 | # Get new version 47 | - name: 'Get version' 48 | id: new_version 49 | run: echo "new_version=$(php .github/workflows/check.php)" >> $GITHUB_OUTPUT 50 | 51 | - name: 'Git config' 52 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 53 | run: | 54 | git config user.name "GitHub Actions" 55 | git config user.email noreply@github.com 56 | 57 | - name: 'Clean' 58 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 59 | run: find . -maxdepth 1 \( -name 'README.md' -o -name 'package.zip' -o -name 'composer.json' -o -name 'composer.lock' -o -name '.gitignore' -o -path './.git' -o -path './.github' \) -prune -o -exec rm -rf {} \; 60 | 61 | - name: Unzip 62 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 63 | uses: TonyBogdanov/zip@1.0 64 | with: 65 | args: unzip -qq ./package.zip -d . 66 | 67 | # You may not need this step depending on the contents of the zip 68 | - name: Move 69 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 70 | run: shopt -s dotglob && sudo mv ${{ env.PACKAGE_SLUG }}/* . 71 | 72 | - name: rm 73 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 74 | run: rm package.zip && rm -rf ${{ env.PACKAGE_SLUG }} 75 | 76 | - name: Commit 77 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 78 | id: make-commit 79 | run: | 80 | git add . 81 | git commit -m '${{ steps.new_version.outputs.new_version }}' 82 | echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 83 | 84 | - name: Push 85 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 86 | run: | 87 | git push 88 | git tag ${{ steps.new_version.outputs.new_version }} 89 | git push --tags 90 | -------------------------------------------------------------------------------- /.github/workflows/examples/facetwp.yml: -------------------------------------------------------------------------------- 1 | name: Updater 2 | 3 | # Run this workflow twice daily 4 | on: 5 | # schedule: 6 | # - cron: '0 */12 * * *' 7 | workflow_dispatch: 8 | 9 | env: 10 | PACKAGE_SLUG: facetwp 11 | 12 | jobs: 13 | # Set the job key. The key is displayed as the job name 14 | # when a job name is not provided 15 | update: 16 | # Name the Job 17 | name: Fetch and check versions 18 | # Set the type of machine to run on 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout repo 23 | uses: actions/checkout@v3 24 | with: 25 | fetch-depth: 0 26 | 27 | # Use FacetWP API to find download link for latest 28 | - name: Get download link from FacetWP API 29 | id: FacetWPAPIResponse 30 | uses: fjogeleit/http-request-action@master 31 | with: 32 | url: 'https://api.facetwp.com' 33 | contentType: 'application/x-www-form-urlencoded' 34 | method: 'POST' 35 | data: '{"action": "check_plugins", "slugs": "${{env.PACKAGE_SLUG}}", "license": "${{secrets.FACETWP_KEY}}"}' 36 | 37 | # uncomment to debug or see other "offerings" your license can download 38 | - name: Show Response 39 | run: echo ${{ steps.FacetWPAPIResponse.outputs.response }} 40 | 41 | # Fetch latest version of FacetWP to download 42 | - name: Fetch 43 | run: wget '${{fromJson(steps.FacetWPAPIResponse.outputs.response).slugs[env.PACKAGE_SLUG].package}}' -O package.zip 44 | 45 | # PHP 46 | - name: 'Setup PHP' 47 | uses: shivammathur/setup-php@v2 48 | with: 49 | php-version: '8.0' 50 | 51 | # Install dependencies 52 | - name: Composer 53 | run: 'composer install' 54 | 55 | # Get current tag 56 | - name: 'Get Previous tag' 57 | id: previous_version 58 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 59 | 60 | # Get new version 61 | - name: 'Get version' 62 | id: new_version 63 | run: echo "new_version=$(php .github/workflows/check.php)" >> $GITHUB_OUTPUT 64 | 65 | - name: 'Git config' 66 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 67 | run: | 68 | git config user.name "GitHub Actions" 69 | git config user.email noreply@github.com 70 | 71 | - name: 'Clean' 72 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 73 | run: find . -maxdepth 1 \( -name 'package.zip' -o -name 'composer.json' -o -name 'composer.lock' -o -name '.gitignore' -o -path './.git' -o -path './.github' \) -prune -o -exec rm -rf {} \; 74 | 75 | - name: Unzip 76 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 77 | uses: TonyBogdanov/zip@1.0 78 | with: 79 | args: unzip -qq ./package.zip -d . 80 | 81 | # You may not need this step depending on the contents of the zip 82 | - name: Move 83 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 84 | run: shopt -s dotglob && sudo mv ${{ env.PACKAGE_SLUG }}/* . 85 | 86 | - name: rm 87 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 88 | run: rm package.zip && rm -rf ${{ env.PACKAGE_SLUG }} 89 | 90 | - name: Commit 91 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 92 | id: make-commit 93 | run: | 94 | git add . 95 | git commit -m '${{ steps.new_version.outputs.new_version }}' 96 | echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 97 | 98 | - name: Push 99 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 100 | run: | 101 | git push 102 | git tag ${{ steps.new_version.outputs.new_version }} 103 | git push --tags 104 | -------------------------------------------------------------------------------- /.github/workflows/examples/gravityforms.yml: -------------------------------------------------------------------------------- 1 | name: Updater 2 | 3 | # Run this workflow twice daily 4 | on: 5 | # schedule: 6 | # - cron: '0 */12 * * *' 7 | workflow_dispatch: 8 | 9 | env: 10 | PACKAGE_SLUG: gravityforms 11 | 12 | jobs: 13 | # Set the job key. The key is displayed as the job name 14 | # when a job name is not provided 15 | update: 16 | # Name the Job 17 | name: Fetch and check versions 18 | # Set the type of machine to run on 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout repo 23 | uses: actions/checkout@v3 24 | with: 25 | fetch-depth: 0 26 | 27 | # Use GravityForms API to find download link for latest 28 | - name: Get download link from GravityForms API 29 | id: GravityFormsAPIResponse 30 | uses: fjogeleit/http-request-action@master 31 | with: 32 | url: 'https://www.gravityhelp.com/wp-content/plugins/gravitymanager/version.php?nocache=1&version=2&key=${{secrets.GRAVITYFORMS_KEY}}' 33 | 34 | # uncomment to debug or see other "offerings" your license can download 35 | #- name: Show Response 36 | # run: echo ${{ steps.GravityFormsAPIResponse.outputs.response }} 37 | 38 | # Fetch latest version of GravityForms to download 39 | # Note: to access GravityForms add-ons/extensions change `offerings.gravityforms.url_latest` 40 | # to e.g. `offerings.gravityformsmailchimp.url_latest` 41 | - name: Fetch 42 | run: wget '${{fromJson(steps.GravityFormsAPIResponse.outputs.response).offerings[env.PACKAGE_SLUG].url_latest}}' -O package.zip 43 | 44 | # PHP 45 | - name: 'Setup PHP' 46 | uses: shivammathur/setup-php@v2 47 | with: 48 | php-version: '8.0' 49 | 50 | # Install dependencies 51 | - name: Composer 52 | run: 'composer install' 53 | 54 | # Get current tag 55 | - name: 'Get Previous tag' 56 | id: previous_version 57 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 58 | 59 | # Get new version 60 | - name: 'Get version' 61 | id: new_version 62 | run: echo "new_version=$(php .github/workflows/check.php)" >> $GITHUB_OUTPUT 63 | 64 | - name: 'Git config' 65 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 66 | run: | 67 | git config user.name "GitHub Actions" 68 | git config user.email noreply@github.com 69 | 70 | - name: 'Clean' 71 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 72 | run: find . -maxdepth 1 \( -name 'package.zip' -o -name 'composer.json' -o -name 'composer.lock' -o -name '.gitignore' -o -path './.git' -o -path './.github' \) -prune -o -exec rm -rf {} \; 73 | 74 | - name: Unzip 75 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 76 | uses: TonyBogdanov/zip@1.0 77 | with: 78 | args: unzip -qq ./package.zip -d . 79 | 80 | # You may not need this step depending on the contents of the zip 81 | - name: Move 82 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 83 | run: shopt -s dotglob && sudo mv ${{ env.PACKAGE_SLUG }}/* . 84 | 85 | - name: rm 86 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 87 | run: rm package.zip && rm -rf ${{ env.PACKAGE_SLUG }} 88 | 89 | - name: Commit 90 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 91 | id: make-commit 92 | run: | 93 | git add . 94 | git commit -m '${{ steps.new_version.outputs.new_version }}' 95 | echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 96 | 97 | - name: Push 98 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 99 | run: | 100 | git push 101 | git tag ${{ steps.new_version.outputs.new_version }} 102 | git push --tags 103 | -------------------------------------------------------------------------------- /.github/workflows/examples/gravityformsaddon.yml: -------------------------------------------------------------------------------- 1 | name: Updater 2 | 3 | # Run this workflow twice daily 4 | on: 5 | # schedule: 6 | # - cron: '0 */12 * * *' 7 | workflow_dispatch: 8 | 9 | env: 10 | PACKAGE_SLUG: gravityformsrecaptcha 11 | 12 | jobs: 13 | # Set the job key. The key is displayed as the job name 14 | # when a job name is not provided 15 | update: 16 | # Name the Job 17 | name: Fetch and check versions 18 | # Set the type of machine to run on 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout repo 23 | uses: actions/checkout@v3 24 | with: 25 | fetch-depth: 0 26 | 27 | # Use GravityForms API to find download link for latest 28 | - name: Get download link from GravityForms API 29 | id: GravityFormsAPIResponse 30 | uses: fjogeleit/http-request-action@master 31 | with: 32 | url: 'https://www.gravityhelp.com/wp-content/plugins/gravitymanager/version.php?nocache=1&version=2&key=${{secrets.GRAVITYFORMS_KEY}}' 33 | 34 | # uncomment to debug or see other "offerings" your license can download 35 | #- name: Show Response 36 | # run: echo ${{ steps.GravityFormsAPIResponse.outputs.response }} 37 | 38 | # Fetch latest version of Gravity Forms add-on to download 39 | - name: Fetch 40 | run: wget '${{fromJson(steps.GravityFormsAPIResponse.outputs.response).offerings[env.PACKAGE_SLUG].url_latest}}' -O package.zip 41 | 42 | # PHP 43 | - name: 'Setup PHP' 44 | uses: shivammathur/setup-php@v2 45 | with: 46 | php-version: '8.0' 47 | 48 | # Install dependencies 49 | - name: Composer 50 | run: 'composer install' 51 | 52 | # Get current tag 53 | - name: 'Get Previous tag' 54 | id: previous_version 55 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 56 | 57 | # Get new version 58 | - name: 'Get version' 59 | id: new_version 60 | run: echo "new_version=$(php .github/workflows/check.php)" >> $GITHUB_OUTPUT 61 | 62 | - name: 'Git config' 63 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 64 | run: | 65 | git config user.name "GitHub Actions" 66 | git config user.email noreply@github.com 67 | 68 | - name: 'Clean' 69 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 70 | run: find . -maxdepth 1 \( -name 'package.zip' -o -name 'composer.json' -o -name 'composer.lock' -o -name '.gitignore' -o -path './.git' -o -path './.github' \) -prune -o -exec rm -rf {} \; 71 | 72 | - name: Unzip 73 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 74 | uses: TonyBogdanov/zip@1.0 75 | with: 76 | args: unzip -qq ./package.zip -d . 77 | 78 | # You may not need this step depending on the contents of the zip 79 | - name: Move 80 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 81 | run: shopt -s dotglob && sudo mv ${{ env.PACKAGE_SLUG }}/* . 82 | 83 | - name: rm 84 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 85 | run: rm package.zip && rm -rf ${{ env.PACKAGE_SLUG }} 86 | 87 | - name: Commit 88 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 89 | id: make-commit 90 | run: | 91 | git add . 92 | git commit -m '${{ steps.new_version.outputs.new_version }}' 93 | echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 94 | 95 | - name: Push 96 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 97 | run: | 98 | git push 99 | git tag ${{ steps.new_version.outputs.new_version }} 100 | git push --tags 101 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: Updater 2 | 3 | # Run this workflow twice daily 4 | on: 5 | # schedule: 6 | # - cron: '0 */12 * * *' 7 | workflow_dispatch: 8 | 9 | env: 10 | PACKAGE_SLUG: advanced-custom-fields-pro 11 | 12 | jobs: 13 | # Set the job key. The key is displayed as the job name 14 | # when a job name is not provided 15 | update: 16 | # Name the Job 17 | name: Fetch and check versions 18 | # Set the type of machine to run on 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout repo 23 | uses: actions/checkout@v3 24 | with: 25 | fetch-depth: 0 26 | 27 | # Fetch latest version 28 | - name: Fetch 29 | run: wget 'https://privateplugin.example&k=${{secrets.PLUGIN_KEY}}' -O package.zip 30 | 31 | # PHP 32 | - name: 'Setup PHP' 33 | uses: shivammathur/setup-php@v2 34 | with: 35 | php-version: '8.0' 36 | 37 | # Install dependencies 38 | - name: Composer 39 | run: 'composer install' 40 | 41 | # Get current tag 42 | - name: 'Get Previous tag' 43 | id: previous_version 44 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 45 | 46 | # Get new version 47 | - name: 'Get version' 48 | id: new_version 49 | run: echo "new_version=$(php .github/workflows/check.php)" >> $GITHUB_OUTPUT 50 | 51 | - name: 'Git config' 52 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 53 | run: | 54 | git config user.name "GitHub Actions" 55 | git config user.email noreply@github.com 56 | 57 | - name: 'Clean' 58 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 59 | run: find . -maxdepth 1 \( -name 'package.zip' -o -name 'composer.json' -o -name 'composer.lock' -o -name '.gitignore' -o -path './.git' -o -path './.github' \) -prune -o -exec rm -rf {} \; 60 | 61 | - name: Unzip 62 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 63 | uses: TonyBogdanov/zip@1.0 64 | with: 65 | args: unzip -qq ./package.zip -d . 66 | 67 | # You may not need this step depending on the contents of the zip 68 | - name: Move 69 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 70 | run: shopt -s dotglob && sudo mv ${{ env.PACKAGE_SLUG }}/* . 71 | 72 | - name: rm 73 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 74 | run: rm package.zip && rm -rf ${{ env.PACKAGE_SLUG }} 75 | 76 | - name: Commit 77 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 78 | id: make-commit 79 | run: | 80 | git add . 81 | git commit -m '${{ steps.new_version.outputs.new_version }}' 82 | echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 83 | 84 | - name: Push 85 | if: ${{ steps.previous_version.outputs.tag != steps.new_version.outputs.new_version }} 86 | run: | 87 | git push 88 | git tag ${{ steps.new_version.outputs.new_version }} 89 | git push --tags 90 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Private WordPress Plugin Composer Provider 2 | This library is a starter template for creating a repository that automatically mirrors a private WordPress plugin and tags releases. That repository can then be used as [a Composer VCS repository](https://getcomposer.org/doc/05-repositories.md#vcs) and the plugin can be required in your projects, just like you may already do with public plugins. See [Roots's Bedrock](https://github.com/roots/bedrock) for more information on Composer-managed WordPress. 3 | 4 | ## What problem does this solve 5 | Most existing solutions for using private plugins (without vendor Composer support) via Composer include [configuring the package data directly in your WordPress install's `composer.json`](https://getcomposer.org/doc/05-repositories.md#package-2). See: 6 | - https://roots.io/guides/acf-pro-as-a-composer-dependency-with-encrypted-license-key/ 7 | - https://github.com/PhilippBaschke/acf-pro-installer 8 | 9 | The problem with these solutions is that they require defining the plugin version in your `composer.json`'s `repositories` block. If a new release comes along, you have to bump this number manually. Fine for one site, but a massive pain for many. It also means ensuring correct env vars are set up anywhere you deploy or develop. 10 | 11 | A good Composer setup should allow you to define a version contraint for the plugin and simply run `composer update` to get the latest version compatible with your constraints. 12 | 13 | This library allows you to do that. 14 | 15 | ## How does it work 16 | This repository includes a GitHub action that, on a regular schedule, will: 17 | 1. Fetch a plugin zip from a remote URL (see the next section for how authentication works) 18 | 2. Read the plugin version from the zip 19 | 3. Compare that to the latest tag 20 | 4. If the version is the same, quits early 21 | 5. Overwrites the repository's contents with the zip's contents 22 | 6. Commits 23 | 7. Tags 24 | 8. Pushes 25 | 26 | The included `composer.json` then provides other necessary information to turn this repository into [a valid Composer VCS repository](https://getcomposer.org/doc/05-repositories.md#vcs). 27 | 28 | ## Getting started 29 | This repository is just a starting point. You'll need to configure a few things to get your plugin working. This makes the repository very flexible. 30 | 31 | ### Start from this template 32 | Get started with the "Use This Template" button on this repository. 33 | 34 | ### Consider using an example 35 | Many popular plugins have configurations ready to go in the `.github/workflows/examples` directory. Copying a workflow out of here into `update.yml` may be sufficient for your needs. Consult each file for important plugin-specific information. 36 | 37 | ### Determine the download URL for your plugin 38 | You can download the latest version of most private plugins from a fixed URL, so long as you provide authentication of some kind. For example, Events Calendar Pro can be downloaded from: 39 | 40 | ``` 41 | https://pue.tri.be/api/plugins/v2/download?plugin=events-calendar-pro&key=${{your_tec_key}} 42 | ``` 43 | 44 | ### Set up license keys as GitHub secrets 45 | You shouldn't be committing any license keys or API keys to this repository. Instead, save any sensitive information needed to authenticate and download your plugin as [GitHub Secrets](https://docs.github.com/en/actions/reference/encrypted-secrets). 46 | 47 | ### Update `.github/workflows/update.yml` 48 | Next, you need to update the GitHub action configuration in `.github/workflows/update.yml`. 49 | 50 | Find the "Fetch" step and update the URL with your plugin's endpoint, substituting in the secret you configured in the previous step for any sensitive information. For example, TEC Pro might end up looking like this: 51 | 52 | ``` 53 | # Fetch latest version 54 | - name: Fetch 55 | run: wget 'https://pue.tri.be/api/plugins/v2/download?plugin=events-calendar-pro&key=${{secrets.TEC_KEY}}' -O package.zip 56 | ``` 57 | 58 | Depending on the contents of the zip getting pulled down from the plugin's author, some moving around may be required. For example, if you download TEC Pro, the zip contains a directory that contains the plugin files. This is a common pattern, and the plugin files need to be moved up to the root directory. 59 | 60 | That particular pattern is enabled by default - simply configure the plugin slug (which should correspond to the nested directory's name) in the `env` section of the action: 61 | 62 | ``` 63 | env: 64 | PACKAGE_SLUG: events-calendar-pro 65 | ``` 66 | 67 | If this behavior _isn't_ desirable, comment out the "Move" step entirely. Tweak according to your own needs. 68 | 69 | ### Update `composer.json` 70 | Finally, update the included `composer.json` with an appropriate package name and, optionally, author credits. For example: 71 | 72 | ``` 73 | { 74 | "name": "the-events-calendar/events-calendar-pro", 75 | "type": "wordpress-plugin", 76 | "authors": [ 77 | { 78 | "name": "Ethan Clevenger", 79 | "email": "ethan@sternerstuff.dev" 80 | } 81 | ], 82 | "require": {}, 83 | "require-dev": { 84 | "tutv95/wp-package-parser": "^1.0" 85 | } 86 | } 87 | 88 | ``` 89 | 90 | The only parts you shouldn't change are the package type and the `tutv95/wp-package-parser` dependency. 91 | 92 | ### Push and test 93 | Commit and push to GitHub. You should now see a new "Actions" tab across the top of your repository. Click into it, find the "Updater" workflow, and run it (main branch, no `yml` required). The action should pull and tag the latest available version of the plugin. 94 | 95 | ### Schedule 96 | Confident that everything is in working order, you should now uncomment the schedule configuration of the `on` section in `update.yml`. By default, the package will auto-check for updates twice a day. Configure to your liking. 97 | 98 | ### Require 99 | You can now require this library in your WordPress install. Add the GitHub repo to your `composer.json` file as [a VCS repository](https://getcomposer.org/doc/05-repositories.md#vcs), and require the library according to how you named the package. Given the current example: 100 | 101 | ``` 102 | composer config repositories.events-calendar-pro vcs git@github.com:sterner-stuff/events-calendar-pro.git 103 | composer require the-events-calendar/events-calendar-pro 104 | ``` 105 | 106 | ## Etiquette 107 | The WordPress license, and how it impacts paid plugins, will probably always be a point of contention. Ignoring that, we believe that plugin authors that choose to charge for their work should get paid, considering the cost savings gained by using their work. Therefore, we strongly discourage using this workflow to: 108 | 109 | - Make self-updating public mirrors of private WordPress plugins and themes 110 | - Use a single plugin license across multiple sites when your license plan does not authorize doing so 111 | - Otherwise violate the terms of use of your purchase 112 | 113 | Please create a private repository for use according to the author's terms of use. 114 | 115 | ## Problems? 116 | You may need to make tweaks to the updater workflow unique to the plugin you're trying to make work. Feel free to open a PR for more general improvements. 117 | 118 | ## Known Incompatibilities 119 | - **Easy Digital Downloads**: EDD seem to use some kind of nonce system to create download links, so there is no fixed download link for items sold via EDD to my knowledge. Happy to be proven wrong. Impacts FacetWP, for example. 120 | 121 | ## FAQ 122 | ### [Plugin X] authenticates a different way 123 | See the `wget` documentation for a variety of options that should allow you to authenticate in whatever way required. Tinker with the "Fetch" step in `.github/workflows/update.yml` appropriately, and feel free to submit a PR with a new example workflow if you want to give back. 124 | ### Can I use this for a theme? 125 | Yes, but you'll want to update `composer.json` to be use the package type `wordpress-theme`. The existing metadata parser should support WordPress themes. 126 | ### The zip contents from my plugin download are unexpected (deeply nested, zip within a zip, etc) 127 | This will require your own tinkering with the GitHub action to move directories and files around appropriately. 128 | 129 | ## Opportunities for Improvement 130 | This starter template could probably be tweaked to act as a standalone GitHub Action, accepting args for the package name and full download URL. PRs welcome. 131 | 132 | ## See also 133 | - [Bedrock](https://github.com/roots/bedrock) for an introduction to Composer-managed WordPress 134 | - [SatisPress](https://github.com/cedaro/satispress), for using a WordPress install as a Composer repository and exposing its installed plugins/themes as packages 135 | - [Package Peak](https://packagepeak.app), a SaaS that provides all your Envato purchases as Composer-compatible packages 136 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plugin-author/plugin-name", 3 | "type": "wordpress-plugin", 4 | "authors": [ 5 | { 6 | "name": "Ethan Clevenger", 7 | "email": "ethan@sternerstuff.dev" 8 | } 9 | ], 10 | "require": {}, 11 | "require-dev": { 12 | "tutv95/wp-package-parser": "^1.0" 13 | } 14 | } 15 | --------------------------------------------------------------------------------