Publishing a WordPress plug-in to the official directory with Subversion

My WordPress plug-in for HEIC images was finally approved! So it's time to add it to WordPress's repository so that users can find my plug-in right from their blogs admin interface, yay!

But... I've realised that I forgot everything about Subversion as I haven't used it in more than 10 years (give or take!)

Not only that, but my computer also knows nothing about Subversion either:

svn co svn
-bash: svn: command not found

OOOOOK...! Time for a trip down memory lane.

There is a documentation page from WordPress which I am finding a bit obtuse (although maybe it's just me) and I'll probably have forgotten where it is next time I want to do something like this in about 15 years (or in a couple of months if I update the plug-in).

So here's what I've done, for reference.

First to install the svn tool itself:

brew install svn

(in macOS using brew, in other systems it might be apt-get install svn or something like that)

Then we start by checking out the plug-in folder locally:

svn co svn

Which returns this, showing it created three folders inside my svn local dir:

A    svn/assets
A    svn/tags
A    svn/trunk
Checked out revision 3003755

Three million revisions! Phew! That's a lot!

But let's not get distracted by a number...!

This is what each folder is for, in the most relevant order:

  • trunk: for the latest version of the plug-in code (caveats discussed later).
  • tags: to tag each release, using the same version number as described in readme.txt.
  • assets: to put screenshots and other rarely changed images which are mentioned in the plug-in's readme.txt file and are then used for WordPress listings. According to their documentation, it is heavily CDN-cached.

The recommended flow is:

  1. Do your work elsewhere (likely using git) and push there as many changes as you want until you're satisfied with the state of things.
  2. Once you're ready to release, copy the stuff to your local trunk.
  3. Check that into the WordPress plug-ins repository.
  4. Possibly update any assets in assets and check those in as well (since they have to CDN-replicate you might as well get started sooner).
  5. Make a release SVN style (using the tags folder).
  6. Profit??? 🤭

You might or not have noticed the implied caveat above. Which is that you're not meant to use WordPress's SVN repository for development. They explicitly advise you against that. If you want to work in the usual way we've got used to, this repo is not for you. Go somewhere you can push to main as much as you want without incurring on cache rebuilds and other things that hit someone else's servers hard, in other words.

This is roughly fine, except that I had initially placed the asset images referred to in readme.txt in the same assets folder that I used for things the plug-in required, like a test.heic image. So it was not just a matter of copying and pasting between folders for me. I could have manually copied things to separate folders but I automated the process because I won't remember these subtle details in a week.

So I did some work on my "upstream" git repository to prepare things before the actual release in svn:

First I split the contents of the assets folder in my "upstream" git repository, into two folders. One for the internal plugin assets and another for the WP plugins-directory:

mkdir assets/internal assets/plugins-dir

Then moved the corresponding files to each place:

git mv assets/test.heic assets/internal/
git mv assets/screenshot-*.png assets/plugins-dir/

In the code I edited the path to the test.heic file:

diff --git a/RHEIC_HEIC2JPG.php b/RHEIC_HEIC2JPG.php
index 0731a02..841c585 100644
--- a/RHEIC_HEIC2JPG.php
+++ b/RHEIC_HEIC2JPG.php
@@ -58,7 +58,7 @@ class RHEIC_HEIC2JPG {
                        $im = new Imagick();
                        $v = Imagick::getVersion();
                        $test_image = 'test.heic';
-                       $test_image_path = dirname(__FILE__) . '/assets/' . $test_image;
+                       $test_image_path = dirname(__FILE__) . '/assets/internal/' . $test_image;

In this case it's just a one line change, but if I had more internal assets I would move that /assets/internal/ string to a constant.

Then I tested it works and the plug-in is not crashing... great! (sadly this testing is not automated, but... file under the overkill department).

Now, the intention is that the git repository is the source of truth for all the changes, and when we create a plugin SVN release, some files are copied from the git repository to the top assets folder in the svn repository, and some are copied to the assets/internal folder in the trunk folder. That way we don't ship all the screenshots to people who download the plug-in.

Again I could make the plugin figure out if it's in development or release mode and use different paths but I think it's another candidate for the overkill department!

What I actually did was a bash script called to do all this creating of directories and copying of files.

I could have used something more readable as far as scripts go, but I don't want to impose node or python on other people, so I just went for the in theory more available syntax.

So then you can just do:


and it will do all the file copying that we need, placing things in the right folders, etc.

Then what you do is:

svn add assets/*
svn add trunk/*
svn ci -m 'Your commit message' --username USERNAME

which checks in the code—effectively sending it to the repository.

But we still have to tag it:

svn cp trunk tags/(PLUGIN_VERSION)
svn ci -m 'Tagging version PLUGIN_VERSION'

And this in turn causes a 'release' to be created, which I think makes WordPress aware that there's a new version of a plug-in, and eventually it pings blogs about it so they update their installation with the latest version.

My script does not automate the Subversion part because that would require knowing the plug-in version for the tagging... and I did not want to parse more arguments in the script. I also don't want to deal with handling svn errors. The script is sufficiently arcane with the simple things it's doing; I don't want to make it even more obscure.

Though: I added the bare minimum input validation (i.e. are there sufficient parameters?) and it prints the commands to actually check-in and tag the files in Subversion. But mostly for my own sanity, because I know I will totally have forgotten that next time I have to update the plug-in!

And finally, assuming you managed to check-in the plug-in into the Subversion repository for the first time, you will not find the plug-in when searching in the wp-admin plugins section. You will also not find it in the plug-in page that was provided to you in the approval email. At least, not immediately. The changes need propagating and etc, etc. So you might need to wait for a few days until it shows up in the searches.

When mine is ready, it should be at - let's see!