Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitHub workflow to build and deploy standalone plugins #686

70 changes: 70 additions & 0 deletions .github/workflows/deploy-standalone-plugins.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Deploy standalone plugins to WordPress.org

on:
# TODO The pull_request will be removed once the workflow is tested.
pull_request:
branches:
- trunk
- 'release/**'
- 'feature/**'
paths:
- '.github/workflows/deploy-standalone-plugins.yml'
types:
- opened
- reopened
- synchronize
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved
release:
types: [published]
workflow_dispatch:
inputs:
slug:
type: string
description: 'The slug of the plugin to deploy'

jobs:
release:
name: New Release
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved
- name: Checkout repository
uses: actions/checkout@v3
- name: Set matrix
id: set-matrix
# Load the JSON file and parse from "{name: {slug, version}, ...}" to "include: [{ name, slug, version }, ...]"
# for use in the matrix.
run: echo "matrix="$(jq -c '{include:[keys[] as $k | {name:$k,slug:.[$k].slug,version:.[$k].version }]}' plugins.json) >> $GITHUB_OUTPUT
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved
deploy:
needs: release
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJSON(needs.release.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Node.js (.nvmrc)
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
cache: npm
- name: Install npm dependencies
run: npm ci
- name: Building standalone plugins
run: npm run build-plugins
- name: Deploy Standalone Plugin - ${{ matrix.slug }}
# TODO Once the workflow is tested, we will remove the comment and use the 10up action to deploy the plugin.
#uses: 10up/action-wordpress-plugin-deploy@stable
felixarntz marked this conversation as resolved.
Show resolved Hide resolved
env:
# TODO Once the workflow is tested, we will remove the comment and use the secret SVN access.
#SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
#SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
# TODO Once the workflow is tested, we will remove this test credential.
SVN_PASSWORD: SVN_PASSWORD
SVN_USERNAME: SVN_USERNAME
SLUG: ${{ matrix.slug }}
VERSION: ${{ matrix.version }}
BUILD_DIR: ./build/${{ matrix.slug }}
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved
ASSETS_DIR: ./build/${{ matrix.slug }}/.wordpress-org
# TODO The script will be removed once the workflow is tested.
run: bash ./deploy.sh
170 changes: 170 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#!/bin/bash

# Note that this does not use pipefail
# because if the grep later doesn't match any deleted files,
# which is likely the majority case,
# it does not exit with a 0, and I only care about the final exit.
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved
set -eo

# Ensure SVN username and password are set
# IMPORTANT: while secrets are encrypted and not viewable in the GitHub UI,
# they are by necessity provided as plaintext in the context of the Action,
# so do not echo or use debug mode unless you want your secrets exposed!
if [[ -z "$SVN_USERNAME" ]]; then
echo "Set the SVN_USERNAME secret"
exit 1
fi

if [[ -z "$SVN_PASSWORD" ]]; then
echo "Set the SVN_PASSWORD secret"
exit 1
fi

# Allow some ENV variables to be customized
if [[ -z "$SLUG" ]]; then
SLUG=${GITHUB_REPOSITORY#*/}
fi
echo "ℹ︎ SLUG is $SLUG"

# Does it even make sense for VERSION to be editable in a workflow definition?
if [[ -z "$VERSION" ]]; then
VERSION="${GITHUB_REF#refs/tags/}"
VERSION="${VERSION#v}"
fi
echo "ℹ︎ VERSION is $VERSION"

if [[ -z "$ASSETS_DIR" ]]; then
ASSETS_DIR=".wordpress-org"
fi
echo "ℹ︎ ASSETS_DIR is $ASSETS_DIR"

if [[ -z "$BUILD_DIR" ]] || [[ $BUILD_DIR == "./" ]]; then
BUILD_DIR=false
elif [[ $BUILD_DIR == ./* ]]; then
BUILD_DIR=${BUILD_DIR:2}
fi

if [[ "$BUILD_DIR" != false ]]; then
if [[ $BUILD_DIR != /* ]]; then
BUILD_DIR="${GITHUB_WORKSPACE%/}/${BUILD_DIR%/}"
fi
echo "ℹ︎ BUILD_DIR is $BUILD_DIR"
fi

SVN_URL="https://plugins.svn.wordpress.org/${SLUG}/"
SVN_DIR="${HOME}/svn-${SLUG}"

# Checkout just trunk and assets for efficiency
# Tagging will be handled on the SVN level
echo "➤ Checking out .org repository..."
svn checkout --depth immediates "$SVN_URL" "$SVN_DIR"
cd "$SVN_DIR"
svn update --set-depth infinity assets
svn update --set-depth infinity trunk


if [[ "$BUILD_DIR" = false ]]; then
echo "➤ Copying files..."
if [[ -e "$GITHUB_WORKSPACE/.distignore" ]]; then
echo "ℹ︎ Using .distignore"
# Copy from current branch to /trunk, excluding dotorg assets
# The --delete flag will delete anything in destination that no longer exists in source
rsync -rc --exclude-from="$GITHUB_WORKSPACE/.distignore" "$GITHUB_WORKSPACE/" trunk/ --delete --delete-excluded
else
echo "ℹ︎ Using .gitattributes"

cd "$GITHUB_WORKSPACE"

# "Export" a cleaned copy to a temp directory
TMP_DIR="${HOME}/archivetmp"
mkdir "$TMP_DIR"

git config --global user.email "[email protected]"
git config --global user.name "10upbot on GitHub"

# If there's no .gitattributes file, write a default one into place
if [[ ! -e "$GITHUB_WORKSPACE/.gitattributes" ]]; then
cat > "$GITHUB_WORKSPACE/.gitattributes" <<-EOL
/$ASSETS_DIR export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.github export-ignore
EOL

# Ensure we are in the $GITHUB_WORKSPACE directory, just in case
# The .gitattributes file has to be committed to be used
# Just don't push it to the origin repo :)
git add .gitattributes && git commit -m "Add .gitattributes file"
fi

# This will exclude everything in the .gitattributes file with the export-ignore flag
git archive HEAD | tar x --directory="$TMP_DIR"

cd "$SVN_DIR"

# Copy from clean copy to /trunk, excluding dotorg assets
# The --delete flag will delete anything in destination that no longer exists in source
rsync -rc "$TMP_DIR/" trunk/ --delete --delete-excluded
fi
else
echo "ℹ︎ Copying files from build directory..."
rsync -rc "$BUILD_DIR/" trunk/ --delete --delete-excluded
fi

# Copy dotorg assets to /assets
if [[ -d "$GITHUB_WORKSPACE/$ASSETS_DIR/" ]]; then
rsync -rc "$GITHUB_WORKSPACE/$ASSETS_DIR/" assets/ --delete
else
echo "ℹ︎ No assets directory found; skipping asset copy"
fi
felixarntz marked this conversation as resolved.
Show resolved Hide resolved

# Add everything and commit to SVN
# The force flag ensures we recurse into subdirectories even if they are already added
# Suppress stdout in favor of svn status later for readability
echo "➤ Preparing files..."
svn add . --force > /dev/null

# SVN delete all deleted files
# Also suppress stdout here
svn status | grep '^\!' | sed 's/! *//' | xargs -I% svn rm %@ > /dev/null

# Copy tag locally to make this a single commit
echo "➤ Copying tag..."
svn cp "trunk" "tags/$VERSION"

# Fix screenshots getting force downloaded when clicking them
# https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/
if test -d "$SVN_DIR/assets" && test -n "$(find "$SVN_DIR/assets" -maxdepth 1 -name "*.png" -print -quit)"; then
svn propset svn:mime-type "image/png" "$SVN_DIR/assets/"*.png || true
fi
if test -d "$SVN_DIR/assets" && test -n "$(find "$SVN_DIR/assets" -maxdepth 1 -name "*.jpg" -print -quit)"; then
svn propset svn:mime-type "image/jpeg" "$SVN_DIR/assets/"*.jpg || true
fi
if test -d "$SVN_DIR/assets" && test -n "$(find "$SVN_DIR/assets" -maxdepth 1 -name "*.gif" -print -quit)"; then
svn propset svn:mime-type "image/gif" "$SVN_DIR/assets/"*.gif || true
fi
if test -d "$SVN_DIR/assets" && test -n "$(find "$SVN_DIR/assets" -maxdepth 1 -name "*.svg" -print -quit)"; then
svn propset svn:mime-type "image/svg+xml" "$SVN_DIR/assets/"*.svg || true
fi

#Resolves => SVN commit failed: Directory out of date
svn update

svn status

#echo "➤ Committing files..."
#svn commit -m "Update to version $VERSION from GitHub" --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD"
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved

#if $INPUT_GENERATE_ZIP; then
# echo "Generating zip file..."

# use a symbolic link so the directory in the zip matches the slug
# ln -s "${SVN_DIR}/trunk" "${SVN_DIR}/${SLUG}"
# zip -r "${GITHUB_WORKSPACE}/${SLUG}.zip" "$SLUG"
# unlink "${SVN_DIR}/${SLUG}"

# echo "zip-path=${GITHUB_WORKSPACE}/${SLUG}.zip" >> "${GITHUB_OUTPUT}"
# echo "✓ Zip file generated!"
#fi
mukeshpanchal27 marked this conversation as resolved.
Show resolved Hide resolved

echo "✓ Plugin deployed!"