newspack-scripts 5.8.0 → 5.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,4 +27,4 @@ jobs:
27
27
  command: npm install --legacy-peer-deps
28
28
  - run:
29
29
  name: release
30
- command: npm run semantic-release || true
30
+ command: npm run semantic-release || true
@@ -0,0 +1,43 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - trunk
7
+ - alpha
8
+ - 'hotfix/**'
9
+ - 'epic/**'
10
+
11
+ jobs:
12
+ release:
13
+ name: Build and Release
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ contents: write
17
+ issues: write
18
+ pull-requests: write
19
+ steps:
20
+ - name: Checkout
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+ persist-credentials: false
25
+
26
+ - name: Setup Node.js
27
+ uses: actions/setup-node@v4
28
+ with:
29
+ node-version-file: '.nvmrc'
30
+ cache: 'npm'
31
+
32
+ - name: Verify Node version
33
+ run: node --version
34
+
35
+ - name: Install dependencies
36
+ run: npm ci --legacy-peer-deps
37
+
38
+ - name: Release
39
+ env:
40
+ GITHUB_REPOSITORY: ${{ github.repository }}
41
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
43
+ run: npm run semantic-release
@@ -0,0 +1,50 @@
1
+ name: Build Distributable
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ archive-name:
7
+ description: 'Name of the ZIP archive distributable'
8
+ required: true
9
+ type: string
10
+
11
+ jobs:
12
+ build-distributable:
13
+ name: Build distributable files
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v4
18
+
19
+ - name: Setup Node.js
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version-file: '.nvmrc'
23
+ cache: 'npm'
24
+
25
+ - name: Verify Node version
26
+ run: node --version
27
+
28
+ - name: Setup PHP
29
+ uses: shivammathur/setup-php@v2
30
+ with:
31
+ php-version: '8.3'
32
+ tools: composer
33
+
34
+ - name: Install dependencies
35
+ run: npm ci --legacy-peer-deps
36
+
37
+ - name: Install rsync
38
+ run: sudo apt-get update && sudo apt-get install -y rsync
39
+
40
+ - name: Install PHP packages
41
+ run: composer install --no-dev --no-scripts
42
+
43
+ - name: Build plugin files
44
+ run: npm run build && npm run release:archive
45
+
46
+ - name: Upload artifact
47
+ uses: actions/upload-artifact@v4
48
+ with:
49
+ name: ${{ inputs.archive-name }}
50
+ path: release/${{ inputs.archive-name }}.zip
@@ -0,0 +1,24 @@
1
+ name: Build
2
+
3
+ on:
4
+ workflow_call:
5
+
6
+ jobs:
7
+ build:
8
+ name: Install node dependencies
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v4
13
+
14
+ - name: Setup Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version-file: '.nvmrc'
18
+ cache: 'npm'
19
+
20
+ - name: Verify Node version
21
+ run: node --version
22
+
23
+ - name: Install dependencies
24
+ run: npm ci --legacy-peer-deps
@@ -0,0 +1,27 @@
1
+ name: Check TypeScript
2
+
3
+ on:
4
+ workflow_call:
5
+
6
+ jobs:
7
+ check-typescript:
8
+ name: Validate TypeScript
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v4
13
+
14
+ - name: Setup Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version-file: '.nvmrc'
18
+ cache: 'npm'
19
+
20
+ - name: Verify Node version
21
+ run: node --version
22
+
23
+ - name: Install dependencies
24
+ run: npm ci --legacy-peer-deps
25
+
26
+ - name: Validate TypeScript
27
+ run: npm run typescript:check
@@ -0,0 +1,39 @@
1
+ name: Generate Docs
2
+
3
+ permissions:
4
+ contents: write
5
+
6
+ on:
7
+ workflow_call:
8
+
9
+ jobs:
10
+ generate-docs:
11
+ name: Generate documentation
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout
15
+ uses: actions/checkout@v4
16
+
17
+ - name: Install dependencies
18
+ run: sudo apt-get update && sudo apt-get install -y graphviz plantuml
19
+
20
+ - name: Download PHPDocumentor
21
+ run: |
22
+ curl -L -o ./phpdocumentor https://phpdoc.org/phpDocumentor.phar
23
+ chmod +x ./phpdocumentor
24
+
25
+ - name: Generate documentation
26
+ run: ./phpdocumentor run -d . -t ./docs
27
+
28
+ - name: Switch to docs branch, commit, and push
29
+ env:
30
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31
+ GIT_COMMITTER_NAME: ${{ vars.GIT_COMMITTER_NAME || 'github-actions[bot]' }}
32
+ GIT_COMMITTER_EMAIL: ${{ vars.GIT_COMMITTER_EMAIL || 'github-actions[bot]@users.noreply.github.com' }}
33
+ run: |
34
+ git config user.name "$GIT_COMMITTER_NAME"
35
+ git config user.email "$GIT_COMMITTER_EMAIL"
36
+ git checkout -b docs
37
+ git add -f docs
38
+ git commit -m "Update the docs"
39
+ git push "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git" docs --force
@@ -0,0 +1,139 @@
1
+ name: i18n
2
+
3
+ on:
4
+ workflow_call:
5
+ secrets:
6
+ GIT_COMMITTER_TOKEN:
7
+ required: true
8
+
9
+ permissions:
10
+ contents: write
11
+
12
+ jobs:
13
+ i18n:
14
+ name: Create translation files
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0
21
+ token: ${{ secrets.GIT_COMMITTER_TOKEN }}
22
+
23
+ - name: Configure Git
24
+ env:
25
+ GIT_COMMITTER_NAME: ${{ vars.GIT_COMMITTER_NAME || 'github-actions[bot]' }}
26
+ GIT_COMMITTER_EMAIL: ${{ vars.GIT_COMMITTER_EMAIL || 'github-actions[bot]@users.noreply.github.com' }}
27
+ run: |
28
+ git config user.name "$GIT_COMMITTER_NAME"
29
+ git config user.email "$GIT_COMMITTER_EMAIL"
30
+
31
+ - name: Setup Node.js
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version-file: '.nvmrc'
35
+ cache: 'npm'
36
+
37
+ - name: Check if commit author is bot
38
+ id: check-bot
39
+ env:
40
+ GIT_COMMITTER_EMAIL: ${{ vars.GIT_COMMITTER_EMAIL || 'github-actions[bot]@users.noreply.github.com' }}
41
+ run: |
42
+ COMMIT_AUTHOR=$(git log -1 --pretty=format:'%ae')
43
+ if [ "$COMMIT_AUTHOR" = "$GIT_COMMITTER_EMAIL" ]; then
44
+ echo "Commit was made by bot ($(git rev-parse --short HEAD)), skipping translation update"
45
+ echo "skip=true" >> $GITHUB_OUTPUT
46
+ else
47
+ echo "skip=false" >> $GITHUB_OUTPUT
48
+ fi
49
+
50
+ - name: Install dependencies
51
+ if: steps.check-bot.outputs.skip != 'true'
52
+ run: npm ci --legacy-peer-deps
53
+
54
+ - name: Configure PHP for deep nesting
55
+ if: steps.check-bot.outputs.skip != 'true'
56
+ run: |
57
+ # Increase xdebug max_nesting_level to handle deeply nested JS files
58
+ echo "xdebug.max_nesting_level=512" | sudo tee -a $(php -i | grep "Scan this dir for additional .ini files" | cut -d' ' -f9)/99-custom.ini
59
+
60
+ - name: Install WP CLI
61
+ if: steps.check-bot.outputs.skip != 'true'
62
+ run: |
63
+ curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
64
+ chmod +x wp-cli.phar
65
+ sudo mv wp-cli.phar /usr/local/bin/wp
66
+
67
+ - name: Build plugin files
68
+ if: steps.check-bot.outputs.skip != 'true'
69
+ run: npm run build || true
70
+
71
+ - name: Create POT translation files
72
+ if: steps.check-bot.outputs.skip != 'true'
73
+ env:
74
+ REPO_NAME: ${{ github.event.repository.name }}
75
+ run: |
76
+ # Theme is excluded, more in https://github.com/Automattic/newspack-theme/pull/2458
77
+ if [ "$REPO_NAME" = "newspack-theme" ]; then
78
+ cd ./newspack-theme
79
+ wp i18n make-pot . languages/${REPO_NAME}.pot --exclude='src' --domain=${REPO_NAME}
80
+ cd -
81
+ else
82
+ wp i18n make-pot . languages/${REPO_NAME}.pot --domain=${REPO_NAME}
83
+ fi
84
+
85
+ - name: Create JSON translation files
86
+ if: steps.check-bot.outputs.skip != 'true'
87
+ env:
88
+ REPO_NAME: ${{ github.event.repository.name }}
89
+ run: |
90
+ if [ "$REPO_NAME" = "newspack-theme" ]; then
91
+ cd ./newspack-theme
92
+ fi
93
+
94
+ sudo apt-get update && sudo apt-get install -y gettext
95
+
96
+ cd languages
97
+
98
+ # Create PO files from POT if they don't exist
99
+ if [ ! -f "${REPO_NAME}-en_US.po" ]; then
100
+ echo "Creating ${REPO_NAME}-en_US.po from POT file"
101
+ wp i18n update-po ${REPO_NAME}.pot .
102
+ else
103
+ echo "${REPO_NAME}-en_US.po file already exists, skipping creation"
104
+ fi
105
+
106
+ for po in *.po; do
107
+ if [ -f "$po" ]; then
108
+ echo "Processing file $po …"
109
+ # Update translations according to the new POT file
110
+ msgmerge $po $REPO_NAME.pot -o $po.out
111
+ mv $po.out $po
112
+ msgfmt $po -o $(basename $po .po).mo
113
+ # no-purge since we need the JS translations for the next run
114
+ wp i18n make-json --no-purge $po .
115
+ fi
116
+ done
117
+
118
+ - name: Commit translation files
119
+ if: steps.check-bot.outputs.skip != 'true'
120
+ run: |
121
+ if [ "$REPO_NAME" = "newspack-theme" ]; then
122
+ cd ./newspack-theme
123
+ fi
124
+ if [ -d "languages" ]; then
125
+ LINES_CHANGED=$(git diff --numstat languages/ | awk '{sum += $1 + $2} END {print sum}')
126
+ # If no existing files were changed, check for new files
127
+ if [ -z "$LINES_CHANGED" ] || [ "$LINES_CHANGED" -eq 0 ]; then
128
+ LINES_CHANGED=$(git ls-files --others --exclude-standard languages/ | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}')
129
+ fi
130
+ else
131
+ LINES_CHANGED=0
132
+ fi
133
+ LINES_CHANGED=${LINES_CHANGED:-0}
134
+ echo "Lines changed in languages/: $LINES_CHANGED"
135
+ if [ "$LINES_CHANGED" -gt 3 ]; then
136
+ git add languages/
137
+ git commit -m "chore: update translation files [skip ci]"
138
+ git push
139
+ fi
@@ -0,0 +1,28 @@
1
+ name: Lint JS & SCSS
2
+
3
+ on:
4
+ workflow_call:
5
+
6
+ jobs:
7
+ lint-js-scss:
8
+ name: Lint JS & SCSS files
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v4
13
+
14
+ - name: Setup Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version-file: '.nvmrc'
18
+ cache: 'npm'
19
+
20
+ - name: Verify Node version
21
+ run: node --version
22
+
23
+ - name: Install dependencies
24
+ run: npm ci --legacy-peer-deps
25
+
26
+ - name: Run Linter
27
+ # Temporarily skip linting SCSS due to stylelint config updates. Remove :js when ready to re-enable linting of SCSS.
28
+ run: npm run lint:js
@@ -0,0 +1,30 @@
1
+ name: Lint PHP
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ php-version:
7
+ description: 'PHP version to use'
8
+ required: false
9
+ type: string
10
+ default: '8.3'
11
+
12
+ jobs:
13
+ lint-php:
14
+ name: Lint PHP files
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup PHP
21
+ uses: shivammathur/setup-php@v2
22
+ with:
23
+ php-version: ${{ inputs.php-version }}
24
+ tools: composer
25
+
26
+ - name: Install Composer dependencies
27
+ run: composer install
28
+
29
+ - name: Lint PHP files
30
+ run: ./vendor/bin/phpcs
@@ -0,0 +1,48 @@
1
+ name: Post Release
2
+
3
+ permissions:
4
+ contents: write
5
+
6
+ on:
7
+ workflow_call:
8
+ secrets:
9
+ GIT_COMMITTER_TOKEN:
10
+ required: true
11
+ SLACK_CHANNEL_ID:
12
+ required: false
13
+ SLACK_AUTH_TOKEN:
14
+ required: false
15
+
16
+ jobs:
17
+ post-release:
18
+ name: Perform post-release tasks
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v4
23
+ with:
24
+ fetch-depth: 0
25
+ token: ${{ secrets.GIT_COMMITTER_TOKEN }}
26
+
27
+ - name: Configure Git
28
+ env:
29
+ GIT_COMMITTER_NAME: ${{ vars.GIT_COMMITTER_NAME || 'github-actions[bot]' }}
30
+ GIT_COMMITTER_EMAIL: ${{ vars.GIT_COMMITTER_EMAIL || 'github-actions[bot]@users.noreply.github.com' }}
31
+ run: |
32
+ git config user.name "$GIT_COMMITTER_NAME"
33
+ git config user.email "$GIT_COMMITTER_EMAIL"
34
+
35
+ - name: Setup Node.js
36
+ uses: actions/setup-node@v4
37
+ with:
38
+ node-version-file: '.nvmrc'
39
+ cache: 'npm'
40
+
41
+ - name: Install dependencies
42
+ run: npm ci --legacy-peer-deps
43
+
44
+ - name: Perform post-release chores
45
+ env:
46
+ SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }}
47
+ SLACK_AUTH_TOKEN: ${{ secrets.SLACK_AUTH_TOKEN }}
48
+ run: ./node_modules/newspack-scripts/scripts/github/post-release.sh
@@ -0,0 +1,58 @@
1
+ # Release to WordPress.org.
2
+ # Requires the calling workflow to run reusable-release.yml first (which uploads release artifacts).
3
+ name: Release to WordPress.org
4
+
5
+ on:
6
+ workflow_call:
7
+ inputs:
8
+ plugin-name:
9
+ description: 'WordPress.org plugin slug. Defaults to the repository name.'
10
+ required: false
11
+ type: string
12
+ default: ''
13
+ secrets:
14
+ WP_ORG_USERNAME:
15
+ required: true
16
+ WP_ORG_PASSWORD:
17
+ required: true
18
+
19
+ jobs:
20
+ release-wporg:
21
+ name: Release to WordPress.org
22
+ runs-on: ubuntu-latest
23
+ env:
24
+ PLUGIN_NAME: ${{ inputs.plugin-name || github.event.repository.name }}
25
+ steps:
26
+ - name: Checkout
27
+ uses: actions/checkout@v4
28
+ with:
29
+ fetch-depth: 0
30
+
31
+ - name: Setup Node.js
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version-file: '.nvmrc'
35
+ cache: 'npm'
36
+
37
+ - name: Install dependencies
38
+ run: npm ci --legacy-peer-deps
39
+
40
+ - name: Download release artifacts
41
+ uses: actions/download-artifact@v4
42
+ with:
43
+ name: release-artifacts
44
+ path: release/
45
+
46
+ - name: Verify release artifacts
47
+ run: |
48
+ if [ ! -d "release/$PLUGIN_NAME" ]; then
49
+ echo "::error::release/$PLUGIN_NAME not found. The release job must produce this directory via release:archive."
50
+ exit 1
51
+ fi
52
+
53
+ - name: Release to WordPress.org
54
+ env:
55
+ WP_ORG_USERNAME: ${{ secrets.WP_ORG_USERNAME }}
56
+ WP_ORG_PASSWORD: ${{ secrets.WP_ORG_PASSWORD }}
57
+ WP_ORG_PLUGIN_NAME: ${{ env.PLUGIN_NAME }}
58
+ run: ./node_modules/newspack-scripts/scripts/github/release-wporg.sh
@@ -0,0 +1,61 @@
1
+ name: Release
2
+
3
+ on:
4
+ workflow_call:
5
+ secrets:
6
+ NPM_TOKEN:
7
+ required: false
8
+
9
+ jobs:
10
+ release:
11
+ name: Release new version
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ contents: write
15
+ issues: write
16
+ pull-requests: write
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0
22
+ persist-credentials: false
23
+
24
+ - name: Setup Node.js
25
+ uses: actions/setup-node@v4
26
+ with:
27
+ node-version-file: '.nvmrc'
28
+ cache: 'npm'
29
+
30
+ - name: Setup PHP
31
+ uses: shivammathur/setup-php@v2
32
+ with:
33
+ php-version: '8.3'
34
+ tools: composer
35
+
36
+ - name: Verify Node version
37
+ run: node --version
38
+
39
+ - name: Install dependencies
40
+ run: npm ci --legacy-peer-deps
41
+
42
+ - name: Install rsync
43
+ run: sudo apt-get update && sudo apt-get install -y rsync
44
+
45
+ - name: Install PHP packages
46
+ run: composer install --no-dev --no-scripts
47
+
48
+ - name: Release new version
49
+ env:
50
+ GITHUB_REPOSITORY: ${{ github.repository }}
51
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
53
+ run: npm run release
54
+
55
+ - name: Upload release artifacts
56
+ uses: actions/upload-artifact@v4
57
+ with:
58
+ name: release-artifacts
59
+ path: release/
60
+ if-no-files-found: ignore
61
+ retention-days: 1
@@ -0,0 +1,27 @@
1
+ name: Test JS
2
+
3
+ on:
4
+ workflow_call:
5
+
6
+ jobs:
7
+ test-js:
8
+ name: Run JS tests
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v4
13
+
14
+ - name: Setup Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version-file: '.nvmrc'
18
+ cache: 'npm'
19
+
20
+ - name: Verify Node version
21
+ run: node --version
22
+
23
+ - name: Install dependencies
24
+ run: npm ci --legacy-peer-deps
25
+
26
+ - name: Run JS Tests
27
+ run: npm run test
@@ -0,0 +1,72 @@
1
+ name: Test PHP
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ php-version:
7
+ description: 'PHP version to use'
8
+ required: false
9
+ type: string
10
+ default: '8.3'
11
+ wp-version:
12
+ description: 'WordPress version to test against'
13
+ required: false
14
+ type: string
15
+ default: 'latest'
16
+ secrets:
17
+ CODECOV_TOKEN:
18
+ required: false
19
+
20
+ jobs:
21
+ test-php:
22
+ name: Run PHP tests
23
+ runs-on: ubuntu-latest
24
+ services:
25
+ mysql:
26
+ image: mysql:5.7
27
+ env:
28
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
29
+ ports:
30
+ - 3306:3306
31
+ options: >-
32
+ --health-cmd="mysqladmin ping"
33
+ --health-interval=10s
34
+ --health-timeout=5s
35
+ --health-retries=3
36
+ env:
37
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
38
+ WP_TESTS_DIR: /tmp/wordpress-tests-lib
39
+ WP_CORE_DIR: /tmp/wordpress/
40
+ steps:
41
+ - name: Checkout
42
+ uses: actions/checkout@v4
43
+
44
+ - name: Setup PHP
45
+ uses: shivammathur/setup-php@v2
46
+ with:
47
+ php-version: ${{ inputs.php-version }}
48
+ tools: composer
49
+ extensions: mysqli
50
+ coverage: pcov
51
+
52
+ - name: Install system dependencies
53
+ run: sudo apt-get update && sudo apt-get install -y subversion default-mysql-client
54
+
55
+ - name: Install Composer dependencies
56
+ run: composer update
57
+
58
+ - name: Setup WordPress test environment
59
+ run: |
60
+ rm -rf $WP_TESTS_DIR $WP_CORE_DIR
61
+ bash bin/install-wp-tests.sh wordpress_test root '' 127.0.0.1 ${{ inputs.wp-version }}
62
+
63
+ - name: Run tests with coverage
64
+ run: vendor/bin/phpunit --coverage-clover coverage.xml
65
+
66
+ - name: Upload coverage to Codecov
67
+ if: ${{ env.CODECOV_TOKEN != '' }}
68
+ uses: codecov/codecov-action@v4
69
+ with:
70
+ token: ${{ secrets.CODECOV_TOKEN }}
71
+ files: coverage.xml
72
+ fail_ci_if_error: false
@@ -1,10 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ const fs = require( 'fs' );
4
+ const path = require( 'path' );
3
5
  const spawn = require( 'cross-spawn' );
4
6
  const utils = require( '../scripts/utils/index.js' );
5
7
 
6
8
  const [ scriptName, ...nodeArgs ] = process.argv.slice( 2 );
7
9
 
10
+ /**
11
+ * Resolve script path. If running in GitHub Actions, try to find the script
12
+ * in `scripts/github/` first, otherwise fall back to `scripts/`.
13
+ *
14
+ * @param {string} name Script name.
15
+ * @return {string} Resolved script path.
16
+ */
17
+ const resolveScript = ( name ) => {
18
+ if ( process.env.GITHUB_ACTIONS ) {
19
+ const githubScriptPath = path.resolve(
20
+ __dirname,
21
+ '../scripts/github/',
22
+ name + '.js'
23
+ );
24
+ if ( fs.existsSync( githubScriptPath ) ) {
25
+ return githubScriptPath;
26
+ }
27
+ }
28
+ return require.resolve( '../scripts/' + name );
29
+ };
30
+
8
31
  if (
9
32
  [
10
33
  'test',
@@ -18,7 +41,7 @@ if (
18
41
  ) {
19
42
  const result = spawn.sync(
20
43
  process.execPath,
21
- [ require.resolve( '../scripts/' + scriptName ), ...nodeArgs ],
44
+ [ resolveScript( scriptName ), ...nodeArgs ],
22
45
  { stdio: 'inherit' }
23
46
  );
24
47
  if ( result.signal ) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newspack-scripts",
3
- "version": "5.8.0",
3
+ "version": "5.9.1",
4
4
  "description": "",
5
5
  "bin": {
6
6
  "newspack-scripts": "./bin/newspack-scripts.js"
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This script should be ran on CI after a new regular (not pre-release) version is released.
4
+
5
+ # The last commit message at this point is the automated release commit. The second-to-last
6
+ # commit message should contain data about the merge.
7
+ SECOND_TO_LAST_COMMIT_MSG=$(git log -n 1 --skip 1 --pretty=format:"%s")
8
+
9
+ LATEST_VERSION_TAG=$(git describe --tags --abbrev=0)
10
+
11
+ git pull origin release
12
+ git checkout alpha
13
+
14
+ # If the merge was from alpha branch (the basic flow), alpha branch should be reset.
15
+ if [[ $(echo $SECOND_TO_LAST_COMMIT_MSG | grep '^Merge .*alpha') ]]; then
16
+ echo '[newspack-scripts] Release was created from the alpha branch. Alpha branch will now be reset.'
17
+
18
+ # Reset the tip of alpha branch to the release branch.
19
+ # The alpha branch is single-serving, just for alpha releases. After a release,
20
+ # we don't care about any alpha changes.
21
+ git reset --hard release --
22
+ # Force-push the alpha branch.
23
+ git push --force
24
+ else
25
+ echo '[newspack-scripts] Release was created from a different branch than the alpha branch (e.g. a hotfix branch).'
26
+ echo '[newspack-scripts] Alpha branch will now be updated with the lastest changes from release.'
27
+ git merge --no-ff release -m "chore(release): merge in release $LATEST_VERSION_TAG"
28
+ if [[ $? == 0 ]]; then
29
+ git push
30
+ else
31
+ git merge --abort
32
+ echo '[newspack-scripts] Post-release merge to alpha failed.'
33
+ if [ -z "$SLACK_CHANNEL_ID" ] || [ -z "$SLACK_AUTH_TOKEN" ]; then
34
+ echo '[newspack-scripts] Missing Slack channel ID and/or token. Cannot notify.'
35
+ else
36
+ echo '[newspack-scripts] Notifying the team on Slack.'
37
+ curl \
38
+ --data "{\"channel\":\"$SLACK_CHANNEL_ID\",\"blocks\":[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"⚠️ Post-release merge to alpha failed for: \`$CIRCLE_PROJECT_REPONAME\`. Check <$CIRCLE_BUILD_URL|the build> for details.\"}}]}" \
39
+ -H "Content-type: application/json" \
40
+ -H "Authorization: Bearer $SLACK_AUTH_TOKEN" \
41
+ -X POST https://slack.com/api/chat.postMessage \
42
+ -s > /dev/null
43
+ fi
44
+ fi
45
+ fi
46
+
47
+ # Update trunk branch with latest changes from the release branch, so they are in sync.
48
+ echo '[newspack-scripts] Merging the release branch into trunk.'
49
+ git checkout trunk
50
+
51
+ # Merge release branch into trunk branch, and notify the team if any conflicts arise.
52
+ git merge --no-ff release -m "chore(release): merge in release $LATEST_VERSION_TAG"
53
+ if [[ $? == 0 ]]; then
54
+ echo '[newspack-scripts] Pushing updated trunk to origin.'
55
+ git push
56
+ else
57
+ git merge --abort
58
+ echo '[newspack-scripts] Post-release merge to trunk failed.'
59
+ if [ -z "$SLACK_CHANNEL_ID" ] || [ -z "$SLACK_AUTH_TOKEN" ]; then
60
+ echo '[newspack-scripts] Missing Slack channel ID and/or token. Cannot notify.'
61
+ else
62
+ echo '[newspack-scripts] Notifying the team on Slack.'
63
+ curl \
64
+ --data "{\"channel\":\"$SLACK_CHANNEL_ID\",\"blocks\":[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"⚠️ Post-release merge to \`trunk\` failed for: \`$CIRCLE_PROJECT_REPONAME\`. Check <$CIRCLE_BUILD_URL|the build> for details.\"}}]}" \
65
+ -H "Content-type: application/json" \
66
+ -H "Authorization: Bearer $SLACK_AUTH_TOKEN" \
67
+ -X POST https://slack.com/api/chat.postMessage \
68
+ -s > /dev/null
69
+ fi
70
+ fi
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Release the latest version on wordpress.org plugin repository.
4
+ # To be run as part of CI workflow.
5
+ # Assumptions:
6
+ # - repository name matches the wordpress.org plugin name or WP_ORG_PLUGIN_NAME is set,
7
+ # - there is a `release` directory with the folder containing the files and named as the plugin in it
8
+ # Partially adapted from https://carlalexander.ca/continuous-deployment-wordpress-directory-circleci/
9
+
10
+ SVN_PLUGINS_URL="https://plugins.svn.wordpress.org"
11
+ SVN_REPO_LOCAL_PATH="release/svn"
12
+ SVN_REPO_URL="$SVN_PLUGINS_URL/$WP_ORG_PLUGIN_NAME"
13
+
14
+ LATEST_GIT_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)
15
+ # Remove the "v" at the beginning of the git tag
16
+ LATEST_SVN_TAG=${LATEST_GIT_TAG:1}
17
+
18
+ mkdir -p $SVN_REPO_LOCAL_PATH && cd $SVN_REPO_LOCAL_PATH
19
+ sudo apt-get update
20
+ sudo apt-get install subversion
21
+
22
+ # Check if the latest SVN tag exists already
23
+ TAG=$(svn ls "$SVN_REPO_URL/tags/$LATEST_SVN_TAG")
24
+ error=$?
25
+ if [ $error == 0 ]; then
26
+ # Tag exists, don't deploy
27
+ echo "Latest tag ($LATEST_SVN_TAG) already exists on the WordPress directory. No deployment needed!"
28
+ exit 0
29
+ fi
30
+
31
+ # Wait a moment to avoid a 429 by WPORG's server.
32
+ sleep 3
33
+
34
+ svn checkout -q "$SVN_REPO_URL" .
35
+
36
+ rm -rf trunk
37
+
38
+ cp -r "../$WP_ORG_PLUGIN_NAME" ./trunk
39
+ cp -r ./trunk "./tags/$LATEST_SVN_TAG"
40
+
41
+ # Add new files to SVN
42
+ svn stat | grep '^?' | awk '{print $2}' | xargs -I x svn add x@
43
+
44
+ # Remove deleted files from SVN
45
+ svn stat | grep '^!' | awk '{print $2}' | xargs -I x svn rm --force x@
46
+
47
+ # Commit to SVN
48
+ svn ci --no-auth-cache --username $WP_ORG_USERNAME --password $WP_ORG_PASSWORD -m "Deploy version $LATEST_SVN_TAG"
@@ -0,0 +1,165 @@
1
+ 'use strict';
2
+
3
+ const utils = require( './utils/index.js' );
4
+
5
+ const semanticRelease = require( 'semantic-release' );
6
+
7
+ const { files, ...otherArgs } = require( 'yargs/yargs' )(
8
+ process.argv.slice( 2 )
9
+ ).parse();
10
+
11
+ const filesList = files.split( ',' );
12
+
13
+ // Get repository name from GitHub Actions environment variable (format: owner/repo).
14
+ const repoName = process.env.GITHUB_REPOSITORY?.split( '/' )[ 1 ] || 'unknown';
15
+
16
+ utils.log( `Releasing ${ repoName }…` );
17
+
18
+ const getConfig = ({ gitBranchName }) => {
19
+ const branchType = gitBranchName.split("/")[0];
20
+ const githubConfig = {
21
+ assets: [
22
+ {
23
+ path: `./release/${ repoName }.zip`,
24
+ label: `${ repoName }.zip`,
25
+ },
26
+ ],
27
+ releasedLabels: false,
28
+ };
29
+
30
+ // Only post GH PR comments for alpha, hotfix/*, and release branches.
31
+ if ( ! ["alpha", "hotfix", "release"].includes(branchType) ) {
32
+ githubConfig.successComment = false;
33
+ githubConfig.failComment = false;
34
+ }
35
+
36
+ // Only publish alpha and release branches to NPM.
37
+ const shouldPublishOnNPM = Boolean( process.env.NPM_TOKEN ) && ["alpha", "release"].includes(branchType);
38
+ if ( shouldPublishOnNPM ) {
39
+ utils.log( `Will publish to npm.` );
40
+ }
41
+
42
+ const config = {
43
+ dryRun: otherArgs.dryRun,
44
+ ci: otherArgs.ci,
45
+ debug: otherArgs.debug,
46
+
47
+ branches: [
48
+ // `release` branch is published on the main distribution channel (a new version on GH).
49
+ "release",
50
+ // `alpha` branch – for regular pre-releases.
51
+ {
52
+ name: "alpha",
53
+ prerelease: true,
54
+ },
55
+ // `hotfix/*` branches – for releases outside of the release schedule.
56
+ {
57
+ name: "hotfix/*",
58
+ // With `prerelease: true`, the `name` would be used for the pre-release tag. A name with a `/`
59
+ // is not valid, though. See https://semver.org/#spec-item-9.
60
+ prerelease: '${name.replace(/\\//g, "-")}',
61
+ },
62
+ // `epic/*` branches – for beta testing/QA pre-release builds.
63
+ {
64
+ name: "epic/*",
65
+ // With `prerelease: true`, the `name` would be used for the pre-release tag. A name with a `/`
66
+ // is not valid, though. See https://semver.org/#spec-item-9.
67
+ prerelease: '${name.replace(/\\//g, "-")}',
68
+ },
69
+ ],
70
+ prepare: ["@semantic-release/changelog", "@semantic-release/npm"],
71
+ plugins: [
72
+ "@semantic-release/commit-analyzer",
73
+ "@semantic-release/release-notes-generator",
74
+ [
75
+ // Whether to publish on npm.
76
+ "@semantic-release/npm",
77
+ {
78
+ npmPublish: shouldPublishOnNPM,
79
+ },
80
+ ],
81
+ "semantic-release-version-bump",
82
+ // Add the built ZIP archive to GH release.
83
+ [
84
+ "@semantic-release/github",
85
+ githubConfig,
86
+ ],
87
+ ],
88
+ };
89
+
90
+ // Bump the semver and prepare a build package.
91
+ config.prepare.push( [
92
+ // Increment the version in additional files, and the create the release archive.
93
+ 'semantic-release-version-bump',
94
+ {
95
+ files: filesList,
96
+ callback: 'npm run release:archive',
97
+ },
98
+ ] );
99
+
100
+ // Unless on a hotfix or epic branch, add a commit that updates the files.
101
+ if ( [ 'hotfix', 'epic' ].indexOf( branchType ) === -1 ) {
102
+ let assets = filesList;
103
+ // These assets should be added to source control after a release.
104
+ if ( branchType === 'release' ) {
105
+ assets = [
106
+ ...filesList,
107
+ 'package.json',
108
+ 'package-lock.json',
109
+ 'CHANGELOG.md',
110
+ ];
111
+ }
112
+ utils.log(
113
+ `On ${ branchType } branch, following files will be updated: ${ assets.join(
114
+ ', '
115
+ ) }`
116
+ );
117
+ config.prepare.push( {
118
+ path: '@semantic-release/git',
119
+ assets,
120
+ message:
121
+ 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}',
122
+ } );
123
+ } else {
124
+ utils.log(
125
+ `This branch is ${ branchType }, plugin files and the changelog will *not* be updated.`
126
+ );
127
+ }
128
+
129
+ return config;
130
+ };
131
+
132
+ const run = async () => {
133
+ try {
134
+ const gitBranch = await utils.getGitBranch();
135
+
136
+ const result = await semanticRelease.default(
137
+ getConfig( { gitBranchName: gitBranch } )
138
+ );
139
+
140
+ if ( result ) {
141
+ const { lastRelease, commits, nextRelease, releases } = result;
142
+
143
+ utils.log(
144
+ `Published ${ nextRelease.type } release version ${ nextRelease.version } containing ${ commits.length } commits.`
145
+ );
146
+
147
+ if ( lastRelease.version ) {
148
+ utils.log( `The last release was "${ lastRelease.version }".` );
149
+ }
150
+
151
+ for ( const release of releases ) {
152
+ utils.log(
153
+ `The release was published with plugin "${ release.pluginName }".`
154
+ );
155
+ }
156
+ } else {
157
+ utils.log( 'No release published.' );
158
+ }
159
+ } catch ( err ) {
160
+ console.error( 'The automated release failed with %O', err );
161
+ process.exit( 1 );
162
+ }
163
+ };
164
+
165
+ run();