Skip to content

wordpress.org release (SPP-91)#228

Merged
Biont merged 73 commits into
mainfrom
feature/SPP-91-wordpress-org-release
Jul 15, 2026
Merged

wordpress.org release (SPP-91)#228
Biont merged 73 commits into
mainfrom
feature/SPP-91-wordpress-org-release

Conversation

@strangerkir

@strangerkir strangerkir commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Please check if the PR fulfills these requirements

  • The commit message follows our guidelines
  • Tests for the changes have been added (for bug fixes/features)
  • Docs have been added/updated (for bug fixes/features)

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)

Feature

What is the current behavior? (You can also link to an open issue here)

There is no reusable workflow for wordpress.org release

Addresses SPP-91.

What is the new behavior (if this is a feature change)?

Implemented a reusable workflow for publishing a plugin.

Does this PR introduce a breaking change? (What changes might users need to make in their application due to this PR?)

No.

Features

  • Live mode - Publishes plugin to wordpress.org SVN repository
  • Dry run mode - Generates artifact preview of changes without committing (dry-run for reviewing what would be published)
  • Two-step publishing (optional) - Allows pausing after committing changes to the trunk for manual testing and approval before creating the tag for official release
  • Automatic file filtering - Excludes sensitive files (auth.json, .npmrc, .env)
  • .distignore support - Honors .distignore file for custom exclusions beyond the default filter list
  • Efficient sync - Uses rsync with checksums for fast, accurate file synchronization
  • Intelligent SVN sync - Automatically adds new files and removes deleted files from the WordPress.org repository
  • Version validation (MAJOR.MINOR.PATCH format enforcement) - Makes sure that the version in the main plugin file, readme.txt, and the version from input are the same
  • Duplicate publish protection - Verifies version doesn't already exist in SVN before proceeding
  • Atomic tagging via remote SVN copy - Tag is created server-side in a single operation

Out of scope

  • Building process - this workflow assumes that either the calling action does building, or provided GIT_REF points to a pre-built tag, branch, or commit.
  • Assets directory sync - it is rarely updated, and we don't keep wordpress.org assets in the git repository. Only trunk is synced; the new tag is then created via a remote server-side SVN copy of trunk.

Note: proper documentation is missing so far. I'm going to add it as soon as the general concept is approved.

Example calling action

name: Test WordPress.org Release

on:
  workflow_dispatch:
    inputs:
      SVN_PLUGIN_SLUG:
        description: "WordPress.org plugin slug (e.g., 'woocommerce' from https://wordpress.org/plugins/woocommerce)"
        type: string
        required: true

      PLUGIN_VERSION:
        description: "Plugin version to publish at WordPress.org (note: it must not exist in SVN)"
        type: string
        required: true

      GIT_REF:
        description: "Git ref to publish at WordPress.org (tag, branch or commit)"
        type: string
        required: true

      DRY_RUN:
        description: "In dry-run mode no commit to the SVN repository happens. Instead, files from trunk are provided as an artifact."
        type: boolean
        default: false
        required: false

    secrets:
      SVN_USERNAME:
        required: true

      SVN_PASSWORD:
        required: true

      GITHUB_USER_SSH_KEY:
        required: true

jobs:
  test-release:
    name: Test Release Process
    uses: inpsyde/reusable-workflows/.github/workflows/wordpress-org-release.yml@main
    with:
      SVN_PLUGIN_SLUG: ${{ inputs.SVN_PLUGIN_SLUG }}
      PLUGIN_VERSION: ${{ inputs.PLUGIN_VERSION }}
      GIT_REF: ${{ inputs.GIT_REF }}
      DRY_RUN: ${{ inputs.DRY_RUN == 'true' }}
    secrets:
      SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
      SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
      GITHUB_USER_SSH_KEY: ${{ secrets.GITHUB_USER_SSH_KEY }}

Comment thread .github/workflows/wordpress-org-release.yml Outdated
Comment thread .github/workflows/wordpress-org-release.yml
Comment thread .github/workflows/wordpress-org-release.yml
Comment thread .github/workflows/wordpress-org-release.yml Outdated
@strangerkir
strangerkir marked this pull request as ready for review May 7, 2026 08:41
@strangerkir
strangerkir requested a review from a team May 7, 2026 08:41

@Biont Biont left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The two-job structure with an environment gate is a genuinely good solution to the staged release problem, and the version cross-validation across PLUGIN_VERSION, the plugin file, and readme.txt is a solid safety net. The overall approach is sound and most of the earlier review feedback has been addressed well.

One concern worth discussing before this lands: environment: wordpress-org-release introduces a dependency on a project-side GitHub environment, and this is a concept with no precedent in this repository's existing workflows.

On first run, every calling repository will have that environment auto-created regardless of whether they intend to use an approval gate, which quietly pollutes project settings and nudges teams toward a naming convention that has never been established or discussed. Making the environment name an optional input — defaulting to 'wordpress-org-release' — would remove the naming coupling and let projects use their own conventions.
But even that is a band-aid on a broader question: should this workflow reach into project-level deployment configuration at all before we've had a cross-team conversation about how environments should be used across repositories?

A second gap is the trunk-only flow. The current design only supports a full release: sync trunk, then create a tag. DRY_RUN: true produces an artifact rather than a real SVN commit, so there is no way in live mode to push to SVN trunk and stop cleanly without a tag following.

The only current escape is cancelling a pending approval, which leaves trunk committed and the run in a failed state. I raised trunk-only as a meaningful use case on April 22nd — it enables testing the published artifact before tagging — and a TRUNK_ONLY input (or my earlier OPERATION: choice that cleanly unifies new-release, trunk-only, and amend-tag) would close this without much added complexity.

I would also like to stress that the current design includes a failure mode that we must address. It falls out of the decision to leverage deployment environments - combined with Github's default behaviour:

  1. Developers set up the workflow not reading docs carefully, not expecting any harm to be done
  2. Thus, they do not setup and configure 'wordpress-org-release' on the project
  3. Github therefore auto-creates the environment on first run
  4. Workflow sync trunk and proceeds to the tag creation step
  5. The newly created env now contains no checks & approvals whatsoever
  6. Because of that, it will auto-approve and create a new release without approval

Again: I support the idea of environments in principle. But I would really like to see a harmless test-run in an isolated project before we make this a quasi-standard via our shared reusable workflows.


Finally, the amend-tag case remains unimplemented: the "Verify version doesn't exist in SVN" check hard-exits with no bypass.
Before merging it would be worth an explicit decision: is this workflow intentionally scoped to new releases only? If so, that should be documented clearly so teams know in advance what to do when they need one of the other flows.

@strangerkir

strangerkir commented May 12, 2026

Copy link
Copy Markdown
Contributor Author

@Biont As we agreed in the call, I replaced the environment usage with the UPDATE_TRUNK_ONLY flag. It is optional, and by default, only trunk will be updated. No new version will be created unless it is explicitly requested.

I also added documentation with three example calling actions: minimal, invoked on tag creation, and using environments for manual approval.

@strangerkir
strangerkir requested a review from Biont May 12, 2026 16:58
@strangerkir strangerkir changed the title [DRAFT] wordpress.org release (SPP-91) wordpress.org release (SPP-91) Jul 7, 2026
@Biont
Biont requested a review from a team as a code owner July 14, 2026 13:16
@Biont
Biont merged commit de88773 into main Jul 15, 2026
4 checks passed
@Biont
Biont deleted the feature/SPP-91-wordpress-org-release branch July 15, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants