Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .build-rsync-exclude
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ package.json
package-lock.json
Gruntfile.js
README.md
scripts/
aryo-activity-log/
aryo-activity-log.*.zip
1 change: 1 addition & 0 deletions .github/workflows/php-coding-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
pull_request:
workflow_dispatch:
workflow_call:

concurrency:
cancel-in-progress: true
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: PHPUnit Tests
on:
push:
pull_request:
workflow_call:

concurrency:
cancel-in-progress: true
Expand Down
175 changes: 175 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
name: Release

on:
workflow_dispatch:
inputs:
bump:
description: Version bump
required: true
type: choice
options: [patch, minor, major]
dry_run:
description: Dry run (no git push, no WP.org commit)
required: false
type: boolean
default: false

concurrency:
group: wordpress-org-release
cancel-in-progress: false

permissions:
contents: read

jobs:
phpcs:
if: >-
github.ref == 'refs/heads/master'
&& ( github.actor == 'KingYes' || github.actor == 'bainternet' || github.actor == 'arielk' )
&& startsWith( github.repository, 'elementor/' )
uses: ./.github/workflows/php-coding-standards.yml

phpunit:
if: >-
github.ref == 'refs/heads/master'
&& ( github.actor == 'KingYes' || github.actor == 'bainternet' || github.actor == 'arielk' )
&& startsWith( github.repository, 'elementor/' )
uses: ./.github/workflows/phpunit.yml

release:
needs: [phpcs, phpunit]
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
with:
php-version: '7.4'
tools: composer:v2

- uses: actions/cache@v4
with:
path: vendor
key: composer-${{ hashFiles('composer.json') }}
restore-keys: |
composer-

- name: Install Composer dependencies
run: composer install --prefer-dist --no-progress

- name: Lint
run: composer lint

- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install npm dependencies
run: npm install

- name: Compute next version
run: |
VERSION=$(node scripts/next-version.js ${{ inputs.bump }})
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "TAG=v$VERSION" >> "$GITHUB_ENV"
echo "Next version: $VERSION"

- name: Validate readme changelog
run: node scripts/validate-readme-changelog.js "${{ env.VERSION }}"

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Bump version
run: npm version ${{ inputs.bump }} --no-git-tag-version

- name: Sync version to plugin files
run: npm run version:sync

- name: Build plugin directory
run: npm run package

- name: Validate build
env:
PLUGIN_SLUG: aryo-activity-log
PLUGIN_VERSION: ${{ env.VERSION }}
run: bash scripts/validate-build-files.sh

- name: Create zip
run: |
zip -r aryo-activity-log.${{ env.VERSION }}.zip ./aryo-activity-log/*

- name: Commit version bump
if: ${{ inputs.dry_run != true }}
run: |
git add package.json package-lock.json aryo-activity-log.php readme.txt
git commit -m "Internal: Release ${{ env.VERSION }}"

- name: Create tag
if: ${{ inputs.dry_run != true }}
run: git tag "${{ env.TAG }}"

- name: Extract changelog from readme
id: changelog
run: |
node scripts/extract-changelog-section.js "${{ env.VERSION }}" > /tmp/changelog_section.txt

{
echo "body<<EOF"
echo "## Changelog"
echo ""
cat /tmp/changelog_section.txt
echo ""
echo "EOF"
} >> "$GITHUB_OUTPUT"

- name: Push commit and tag
if: ${{ inputs.dry_run != true }}
run: |
git push origin master
git push origin "${{ env.TAG }}"

- name: Create GitHub Release
if: ${{ inputs.dry_run != true }}
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with:
tag_name: ${{ env.TAG }}
name: ${{ env.TAG }}
body: ${{ steps.changelog.outputs.body }}
files: aryo-activity-log.${{ env.VERSION }}.zip

- name: Deploy to WordPress.org
if: ${{ inputs.dry_run != true }}
uses: 10up/action-wordpress-plugin-deploy@54bd289b8525fd23a5c365ec369185f2966529c2 # stable
env:
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
SLUG: aryo-activity-log
VERSION: ${{ env.VERSION }}
BUILD_DIR: aryo-activity-log

- name: Deploy to WordPress.org (dry run)
if: ${{ inputs.dry_run == true }}
uses: 10up/action-wordpress-plugin-deploy@54bd289b8525fd23a5c365ec369185f2966529c2 # stable
with:
dry-run: true
env:
SLUG: aryo-activity-log
VERSION: ${{ env.VERSION }}
BUILD_DIR: aryo-activity-log

- name: Summary
run: |
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
echo "::notice::Dry run complete for v${{ env.VERSION }}. No commits, tags, or WP.org deploys were made."
else
echo "::notice::Released v${{ env.VERSION }} to GitHub and WordPress.org."
fi
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"scripts": {
"clean": "rimraf $npm_package_name $npm_package_name.*.zip",
"package": "npm run clean && rsync -av --exclude-from=.build-rsync-exclude . $npm_package_name",
"package:zip": "npm run package && zip -r $npm_package_name.$npm_package_version.zip ./$npm_package_name/*"
"package:zip": "npm run package && zip -r $npm_package_name.$npm_package_version.zip ./$npm_package_name/*",
"version:next": "node scripts/next-version.js",
"version:sync": "node scripts/sync-version.js",
"version:validate-changelog": "node scripts/validate-readme-changelog.js"
},
"devDependencies": {
"rimraf": "^6.0.0"
Expand Down
44 changes: 44 additions & 0 deletions scripts/extract-changelog-section.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict';

const fs = require( 'fs' );
const path = require( 'path' );

const root = path.resolve( __dirname, '..' );
const version = process.argv[ 2 ] || require( path.join( root, 'package.json' ) ).version;
const readme = fs.readFileSync( path.join( root, 'readme.txt' ), 'utf8' );

const changelogMarker = '== Changelog ==';
const changelogIndex = readme.indexOf( changelogMarker );

if ( changelogIndex === -1 ) {
console.error( 'readme.txt is missing "== Changelog ==" section.' );
process.exit( 1 );
}

const changelogBody = readme.slice( changelogIndex + changelogMarker.length );

const sectionRegex = new RegExp(
`= ${ version.replace( /\./g, '\\.' ) }(\\s+-\\s+\\d{4}-\\d{2}-\\d{2})?\\s*=`
);

const headerMatch = changelogBody.match( sectionRegex );

if ( ! headerMatch ) {
console.error( `Changelog section for version ${ version } not found.` );
process.exit( 1 );
}

const headerIndex = changelogBody.indexOf( headerMatch[ 0 ] );
const afterHeader = changelogBody.slice( headerIndex + headerMatch[ 0 ].length );
const nextSectionMatch = afterHeader.match( /\n= \d+\.\d+\.\d+/ );
const sectionContent = nextSectionMatch
? afterHeader.slice( 0, nextSectionMatch.index )
: afterHeader;

const lines = sectionContent
.trim()
.split( '\n' )
.map( ( l ) => l.trim() )
.filter( Boolean );

console.log( lines.join( '\n' ) );
30 changes: 30 additions & 0 deletions scripts/next-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

const path = require( 'path' );

const bump = process.argv[ 2 ];

if ( ! [ 'patch', 'minor', 'major' ].includes( bump ) ) {
console.error( 'Usage: node next-version.js <patch|minor|major>' );
process.exit( 1 );
}

const { version } = require( path.resolve( __dirname, '..', 'package.json' ) );
const parts = version.split( '.' ).map( Number );

switch ( bump ) {
case 'major':
parts[ 0 ]++;
parts[ 1 ] = 0;
parts[ 2 ] = 0;
break;
case 'minor':
parts[ 1 ]++;
parts[ 2 ] = 0;
break;
case 'patch':
parts[ 2 ]++;
break;
}

console.log( parts.join( '.' ) );
27 changes: 27 additions & 0 deletions scripts/sync-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict';

const fs = require( 'fs' );
const path = require( 'path' );

const root = path.resolve( __dirname, '..' );
const { version } = require( path.join( root, 'package.json' ) );

const pluginFile = path.join( root, 'aryo-activity-log.php' );
let plugin = fs.readFileSync( pluginFile, 'utf8' );

plugin = plugin.replace(
/^(Version:\s*)\d+\.\d+\.\d+/m,
`$1${ version }`
);
fs.writeFileSync( pluginFile, plugin );

const readmeFile = path.join( root, 'readme.txt' );
let readme = fs.readFileSync( readmeFile, 'utf8' );

readme = readme.replace(
/^Stable tag: \d+\.\d+\.\d+/m,
`Stable tag: ${ version }`
);
fs.writeFileSync( readmeFile, readme );

console.log( `Synced version ${ version } to aryo-activity-log.php and readme.txt` );
80 changes: 80 additions & 0 deletions scripts/validate-build-files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/bash
set -eo pipefail

if [[ -z "$PLUGIN_SLUG" ]]; then
echo "Set the PLUGIN_SLUG env var"
exit 1
fi

if [[ -z "$PLUGIN_VERSION" ]]; then
echo "Set the PLUGIN_VERSION env var"
exit 1
fi

REPO_ROOT="${GITHUB_WORKSPACE:-.}"
PLUGIN_PATH="${REPO_ROOT}/${PLUGIN_SLUG}"
EXCLUDE_FILE="${REPO_ROOT}/.build-rsync-exclude"

if [[ ! -d "$PLUGIN_PATH" ]]; then
echo "BUILD_DIR '$PLUGIN_PATH' does not exist"
exit 1
fi

cd "$PLUGIN_PATH"

PLUGIN_MAIN_FILE="${PLUGIN_SLUG}.php"

if [[ ! -f "$PLUGIN_MAIN_FILE" ]]; then
echo "${PLUGIN_MAIN_FILE} does not exist in build dir"
exit 1
fi

if [[ ! -f "readme.txt" ]]; then
echo "readme.txt does not exist in build dir"
exit 1
fi

if [[ $(grep -c "Version: $PLUGIN_VERSION" "$PLUGIN_MAIN_FILE") -eq 0 ]]; then
echo "${PLUGIN_MAIN_FILE} does not contain Version: $PLUGIN_VERSION"
EXISTING_VERSION=$(sed -n 's/.*Version: \(.*\)/\1/p' "$PLUGIN_MAIN_FILE")
echo "Found: $EXISTING_VERSION"
exit 1
fi

if [[ $(grep -c "Stable tag: $PLUGIN_VERSION" "readme.txt") -eq 0 ]]; then
echo "readme.txt does not contain Stable tag: $PLUGIN_VERSION"
EXISTING_VERSION=$(sed -n 's/.*Stable tag: \(.*\)/\1/p' "readme.txt")
echo "Found: $EXISTING_VERSION"
exit 1
fi

if [[ ! -f "$EXCLUDE_FILE" ]]; then
echo "WARNING: $EXCLUDE_FILE not found, skipping exclude-list check"
else
ERRORS=0
while IFS= read -r entry; do
# Skip empty lines, comments, and glob-only patterns (e.g. *.zip)
[[ -z "$entry" ]] && continue
[[ "$entry" == \#* ]] && continue

# Strip trailing slash for directory entries
clean="${entry%/}"

# Skip self-references and glob patterns
[[ "$clean" == "$PLUGIN_SLUG" ]] && continue
[[ "$clean" == *"*"* ]] && continue

if [[ -e "$clean" ]]; then
echo "ERROR: '$clean' from .build-rsync-exclude found in build directory"
ERRORS=1
fi
done < "$EXCLUDE_FILE"

if [[ $ERRORS -ne 0 ]]; then
exit 1
fi
fi

echo "Build validation passed for ${PLUGIN_SLUG} v${PLUGIN_VERSION}"
echo "Contents:"
ls -la
Loading
Loading