Best Practice: Adding Gravity Forms (and other plugins)

I ended up using this installer instead: https://github.com/junaidbhura/composer-wp-pro-plugins
which also supports installing Gravity Forms Add-ons!

1 Like

https://packagist.org/packages/gotoandplay/gravityforms-composer-installer

1 Like

Folks, I’ve been experimenting with satispress https://github.com/cedaro/satispress
It turns an ordinary WordPress installation into a composer repository specifically for plugins and themes.
Nicely protected so you need an auth.json file for credentials. But is working great for me.
I manage my satispress installation in wpmanage as an ordinary WordPress site. So I use that to update almost 50 premium plugins and themes used in various projects.
It does mean using a site license for many of them so they’ll update, but if you don’t need the license for actually running the plugin in a project (or you have multi site licenses), then that’s fine.
Recommended.

3 Likes

This looks really useful, thanks…

@mikelittle I’m looking at setting this up right now. So it seems like for this to work the plugins have to be updated via the WordPress plugin update process? How are you handling authentication for things like CI/CD?

Yes. You can use whatever normal means to update the plugins. I happen to use ManageWP to remotely update a ton of sites I host. So the Satispress site is just part of the routine. But I am really considering just running a shell script to just update them every few hours.

Then the projects that use the commercial plugins can pull them in as and when I update them via composer update

As for authentication, I have set up a different account on the SatisPress site for each project. Then for each account I have generated different API keys (e.g. one for production, one for my local development, one for a remote designer, etc) Those credentials go into auth.json in each checked out copy of the project. The auth.json is git-ignored so the credentials don’t go in the repo. You can also add authentication to you CI/CD stack too. I’m not currently using this on any project with CI/CD set up.
Splitting the auth this way means I can for example revoke the api key from the remote designer when she stops working on the project.

Hope that helps.

Stay safe and healthy

Mike

This is still the best GF installation method for me, but an error has occurred on multiple websites lately, something like:
gf is not a recognised command

I solved this by using the deploy_finalize_after hooks instead, e.g.:

deploy_finalize_after:
  - "{{ playbook_dir }}/roles/deploy/hooks/finalize-after.yml"
  - "{{ playbook_dir }}/deploy-hooks/sites/{{ site }}-finalize-after.yml"

Create the file deploy-hooks/sites/mysite.com-finalize-after.yml and add the same hooks provided by runofthemill

This method works great!
I was just wondering how you guys handle the installations in your development environment, since you don’t have any deployments there?

I ended up adding the install commands in a vagrant trigger:

# Installing Gravity Forms plugin & Add-Ons
config.trigger.after [:up] do |trigger|
  trigger.info = "Installing Gravity Forms plugin & Add-Ons"
  trigger.run = {inline: "bash -c '
    wp @development plugin install gravityformscli --activate &&
    wp @development gf install --activate &&
    wp @development gf tool verify-checksums &&
    wp @development gf install gravityformsuserregistration --activate &&
    wp @development gf install gravityformsmailchimp --activate
  '"}
end

but that gives me errors when the plugins are already installed:

==> default: Running trigger...
==> default: Installing Gravity Forms plugin & Add-Ons
    default: Running local: Inline script
    default: bash -c '
    default:         wp @development plugin install gravityformscli --activate &&
    default:         wp @development gf install --activate &&
    default:         wp @development gf tool verify-checksums &&
    default:         wp @development gf install gravityformsuserregistration --activate &&
    default:         wp @development gf install gravityformsmailchimp --activate
    default:       '
    default: Warning: gravityformscli: Plugin already installed.
    default: 
    default: Activating 'gravityformscli'...
    default: 
    default: Success: Plugin already installed.
    default: 
    default: Warning: Plugin 'gravityformscli' is already active.
    default: 
    default: Installatiepakket downloaden van https://s3.amazonaws.com/gravityforms/releases/gravityforms_2.4.19.3.zip?AWSAccessKeyId=AKIAJC3LQNDWHBOFBQIA&Expires=1596301886&Signature=X9qH4erOHEIuAngakYpASfOda74%3D&key=ae24fe0d6c52a4bd144afdd0282db3c4...
    default: 
    default: Uitpakken van pakket...
    default: 
    default: De plugin installeren...
    default: 
    default: Warning: Doelmap bestaat al. "/srv/www/mydomain.com/current/web/app/plugins/gravityforms/"
    default: 
    default: Plugin-installatie mislukt.
    default: 
    default: Warning: The 'https://s3.amazonaws.com/gravityforms/releases/gravityforms_2.4.19.3.zip?AWSAccessKeyId=AKIAJC3LQNDWHBOFBQIA&Expires=1596301886&Signature=X9qH4erOHEIuAngakYpASfOda74%3D&key=ae24fe0d6c52a4bd144afdd0282db3c4' plugin could not be found.
    default: 
    default: Error: No plugins installed.
    default: 
==> default: Trigger run failed
==> default: A script exited with an unacceptable exit code 1.
A script exited with an unacceptable exit code 1.
1 Like

Hey, I helped create and maintain Composer.

I was sent this thread by someone looking into ways to add private Composer packages to their project. So I think I should point out that we actually have a tool called Private Packagist that gives you a private Composer repository that you can add packages to, e.g. private WordPress plugins. We have quite a few WordPress customers who happily use Private Packagist to manage plugins, and a big upside is that you’re financially supporting the maintenance of Composer itself. So certainly something worth checking out if you’re a company with some money available to spend on a professional solution!

3 Likes

ACF Pro official installation method using composer guide

Welcome @naderman! Private Packagist is a great service and I highly recommend it :heart: I used it for a couple of years at the last web agency that I worked at, and it was perfect for our needs.

Thank you for the work that y’all do on Composer! Bedrock could have never existed without it.

1 Like

Thought I’d share the setup we now use (briefly discussed off-topic in Sharing an agency fork of bedrock + sage for inspiration - #7 by oxyc

  1. We host our own satis static composer repository generator on GitHub pages (repo). We do not bundle the dist archives with satis and instead keep the repo public and offload authentication to GitHub.

    • If hosted privately you could include the version archives in satis itself (docs)
    • Or like @naderman mentioned you could use the private packagist service :heart:
  2. The repository has a workflow that rebuilds using the satis docker image.

  3. We add this as a composer repository to each project we have.

      "repositories": [
        ...
        {
          "type": "composer",
          "url": "https://generoi.github.io/packagist/"
        }
      ],
    
  4. We create a private repository for each premium plugin with a basic composer.json

    {
      "name": "generoi/<plugin-slug>",
      "type": "wordpress-plugin"
    }
    
  5. We add a cron scheduled workflow that uses generoi/github-action-update-plugins to check if there are updates available, and if there are, commit them with a scraped changelog. The README contains examples for some plugins. A public example is the kinsta-mu-plugins

  6. When an update happens there’s another job that triggers a rebuild of the satis repository.

  7. To get plugins to satis we also commit each plugins repository to satis.json

  8. We have a machine user as part of our GitHub team with a fine-grained PAT which grants Contents (read) access to their repos. The user (or actually the team) gets added as a collaborator with read access to each private plugin repo (so they don’t have access to any other organization repos).

  9. I have my own fine-grained PAT which grants write access to the packagist repository, this is used to rebuild the packagist repository. This secret is given to each plugin repository so they’re allowed to trigger the satis rebuild workflow.

Ultimately our goals of this in a prioritized order has been:

  1. Increase transparency and trust in the integrity of the downloaded packages. Satispress is scary.
  2. Maintain the past archives even if a license expires.
  3. Support automatic updates–way back before GitHub Actions existed, we used satis but manually updated the repositories.
  4. Provide changelogs to Dependabot updates
  5. Avoid self-hosting which ties with #1 and by not hosting the dist archives, it allows us to have git tags be the source of truth of all packages (probably faster to have them in satis though).
  6. Wasn’t really a priority but it’s beneficial to us that we use github ACL to grant permissions and we don’t need anything else for our developers/CI.

Todo:

Until these are solved and I’ve tagged a first release it’s probably not wise to rely on our repo for the workflows/actions since there will be breaking changes while we test more plugins and try to normalize the tasks and figure out the infinite combinations of changelog formats and zipped zip files.

6 Likes

I can’t believe my luck @oxyc. I’m having this problem right now and came across your solution within 30 min of your posting.

I’m going put together a private repo attempting to do the same thing. Thanks for posting!

2 Likes