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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: switch to GitHub Actions #226

Merged
merged 6 commits into from Jan 12, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 29 additions & 10 deletions .gitattributes
@@ -1,19 +1,38 @@
/.* export-ignore
.cache export-ignore
assets export-ignore
dist export-ignore
svn-assets export-ignore
#
# Exclude these files from release archives.
# This will also make them unavailable when using Composer with `--prefer-dist`.
# If you develop for this plugin using Composer, use `--prefer-source`.
# https://www.reddit.com/r/PHP/comments/2jzp6k/i_dont_need_your_tests_in_my_production
# https://blog.madewithlove.be/post/gitattributes/
#
.babelrc export-ignore
.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.phpcs.xml.dist export-ignore
CHANGELOG export-ignore
composer.* export-ignore
Gruntfile.js export-ignore
LICENSE export-ignore
package.json export-ignore
package-lock.json export-ignore
.phpcs.xml.dist export-ignore
phpunit.* export-ignore
README.md export-ignore
README.wordpress.md export-ignore
/.cache export-ignore
/.github export-ignore
assets export-ignore
dist export-ignore
svn-assets export-ignore
tests export-ignore
phpunit.xml.dist export-ignore
.babelrc export-ignore
.editorconfig export-ignore

#
# Auto detect text files and perform LF normalization
# http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/
#
* text=auto

#
# The above will handle all files NOT found below
#
*.md text
*.php text
52 changes: 52 additions & 0 deletions .github/workflows/cs.yml
@@ -0,0 +1,52 @@
name: CS

on:
# Run on all pushes (except to master) and on all pull requests.
push:
branches-ignore:
- 'master'
pull_request:
# Allow manually triggering the workflow.
workflow_dispatch:

# Cancels all previous workflow runs for the same branch that have not yet completed.
concurrency:
# The concurrency group contains the workflow name and the branch name.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
checkcs:
name: 'Check code style'
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
coverage: none
tools: cs2pr

# Validate the composer.json file.
# @link https://getcomposer.org/doc/03-cli.md#validate
- name: Validate Composer installation
run: composer validate --no-check-all

# Install dependencies and handle caching in one go.
# @link https://github.com/marketplace/actions/install-composer-dependencies
- name: Install Composer dependencies
uses: ramsey/composer-install@v2

# Check the codestyle of the files.
# The results of the CS check will be shown inline in the PR via the CS2PR tool.
# @link https://github.com/staabm/annotate-pull-request-from-checkstyle/
- name: Check PHP code style
continue-on-error: true
run: composer check-cs -- --report-full --report-checkstyle=./phpcs-report.xml

- name: Show PHPCS results in PR
run: cs2pr ./phpcs-report.xml
252 changes: 252 additions & 0 deletions .github/workflows/deploy.yml
@@ -0,0 +1,252 @@
name: Deploy

##############################################################################
# WARNING!
# The deploy workflow (re-)uses information retrieved from the original
# commit which triggered the workflow, such as the branch name, the committer,
# and the commit message.
#
# This type of data should always be regarded as **untrusted** input and when
# these `github....` variables are used directly within the `run` context,
# they can lead to script injection and unintended execution of commands.
#
# To mitigate the risk of these type of script injection attacks, untrusted
# data is first set as a step-specific interim environment variable and only
# after that the environment variable (not the github variables directly)
# is used in the `run` context.
#
# This complies with the current best practices regarding defending against
# these type of attacks as per January 2022.
# For more information, see:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions
##############################################################################

on:
push:
# Trigger the workflow on select branches.
branches:
- trunk
- 'release/**'
- 'hotfix/[0-9]+.[0-9]+*'
- 'feature/**'
# Trigger the workflow whenever a new tag is created.
tags:
- '**'
# Allow manually triggering the workflow.
workflow_dispatch:

# Cancels all previous workflow runs for the same branch that have not yet completed.
concurrency:
# The concurrency group contains the workflow name and the branch name.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
DIST_ORG: 'Yoast-dist'
DIST_DEFAULT_BRANCH: 'master'

jobs:
prepare:
name: "Prepare the artifact"
# Don't run on forks.
if: github.repository_owner == 'Yoast'

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: 5.6

# This action also handles the caching of the Yarn dependencies.
# https://github.com/actions/setup-node
- name: Set up node and enable caching of dependencies
uses: actions/setup-node@v2
with:
node-version: '14'
cache: 'yarn'

- name: "Debug info: show tooling versions"
run: |
php -v
node --version
npm --version
yarn --version
grunt --version
git --version

# Install dependencies and handle caching in one go.
# The Grunt artifact creation will run `composer install` multiple times (both no-dev as well as dev),
# however, Composer packages downloaded are not cached via Grunt.
# Running `composer install` ahead of time will ensure that the cache is warmed up
# and available across runs of the same workflow.
# @link https://github.com/marketplace/actions/install-composer-dependencies
- name: Install Composer dependencies
uses: ramsey/composer-install@v2

- name: Yarn install
run: yarn install

- name: "Grunt: set package version (tags only)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
env:
REF_NAME: ${{ github.ref_name }}
run: grunt set-version -new-version="$REF_NAME"

- name: "Grunt: update package version (tags only)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
run: grunt update-version

- name: "Grunt: create artifact"
run: grunt artifact

- name: "Debug info: show contents of artifacts directory"
run: tree -aC ./artifact

- name: "Debug info: check git status"
run: git status -b -v -u

# Retention is normally 90 days, but this artifact is only for review
# and use in the next step, so no need to keep it for more than a day.
- name: Upload the artifact folder
uses: actions/upload-artifact@v2
if: ${{ success() }}
with:
name: deploy-artifact
path: ./artifact
if-no-files-found: error
retention-days: 1

deploy:
name: "Deploy to dist"
# Don't run on forks.
if: github.repository_owner == 'Yoast'

needs: prepare

runs-on: ubuntu-latest

steps:
- name: "Set variable: short sha"
id: set_sha
env:
SHA: ${{ github.sha }}
run: |
shortsha=$(echo "$SHA" | cut -b 1-6)
echo "::set-output name=SHORTSHA::$shortsha"

- name: "Set variables: target branch, commit title"
id: set_vars
env:
REF_NAME: ${{ github.ref_name }}
run: |
if [[ "${{ github.event_name }}" == 'push' && "${{ github.ref_type }}" == 'branch' && "$REF_NAME" != "${{ env.DIST_DEFAULT_BRANCH }}" ]]; then
echo "::set-output name=BRANCH::$REF_NAME"
echo "::set-output name=TITLE::Syncing branch $REF_NAME (sha: ${{ steps.set_sha.outputs.SHORTSHA }})"
elif [[ "${{ github.event_name }}" == 'workflow_dispatch' && "$REF_NAME" != "${{ env.DIST_DEFAULT_BRANCH }}" ]]; then
echo "::set-output name=BRANCH::$REF_NAME"
echo "::set-output name=TITLE::Manual deploy for $REF_NAME (sha: ${{ steps.set_sha.outputs.SHORTSHA }})"
else # = Pushed tag.
echo "::set-output name=BRANCH::${{ env.DIST_DEFAULT_BRANCH }}"
echo "::set-output name=TITLE::Release $REF_NAME"
fi

- name: Checkout Yoast Dist repo
uses: actions/checkout@v2
with:
repository: ${{ env.DIST_ORG }}/${{ github.event.repository.name }}
ref: ${{ env.DIST_DEFAULT_BRANCH }}
# Personal Access Token for (push) access to the dist version of the repo.
token: ${{ secrets.YOASTBOT_CI_PAT_DIST }}

- name: "Create branch/Switch to branch"
if: ${{ steps.set_vars.outputs.BRANCH != env.DIST_DEFAULT_BRANCH }}
run: git checkout ${{ steps.set_vars.outputs.BRANCH }} 2>/dev/null || git checkout -b ${{ steps.set_vars.outputs.BRANCH }}

# Clean out all files to make sure that deleted files will actually
# be deleted when the artifact gets put in place.
- name: Remove all files
run: |
# Enable extended pattern matching.
shopt -s extglob
# Remove everything, except the ".git" directory and the `composer.json` file.
rm -vrf !(.git/*|composer.json)
# Disable extended pattern matching.
shopt -u extglob

# After the previous step, only the `.git` directory and its contents and the `composer.json` file should remain.
- name: "Debug info: show contents of root directory after cleaning"
run: tree -aC .

# The artifact will be unpacked into the root directory of the repository.
- name: Download and unpack the prepared artifact
uses: actions/download-artifact@v2
with:
name: deploy-artifact

# Remove the vendor directory from the artifact, composer will generate it's own autoload.
- name: Remove generated vendor directory
run: rm -vrf ./vendor

- name: "Debug info: show contents of root directory after artifact insertion"
run: tree -aC .

- name: "Debug info: check git status"
run: git status -b -v -u

- name: Set Git config
env:
ACTOR: ${{ github.actor }}
run: |
git config user.name 'GitHub Action'
git config user.email "$ACTOR@users.noreply.github.com"

- name: Stage files
run: git add -A

- name: "Commit the files (branch)"
if: ${{ github.event_name != 'push' || github.ref_type != 'tag' }}
env:
COMMITTER: ${{ github.event.head_commit.committer.username }}
COMMIT_MSG: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
COMMIT_TIME: ${{ github.event.head_commit.timestamp }}
run: |
git commit --allow-empty -m "${{ steps.set_vars.outputs.TITLE }}" \
-m "Synced up to commit hash: $COMMIT_URL" \
-m "Timestamp last commit: $COMMIT_TIME" \
-m "Committer last commit: @$COMMITTER" \
-m "" \
-m "Commit message last commit:" \
-m "---------------------------" \
-m "$COMMIT_MSG"

- name: "Commit the files (release)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
env:
COMMITTER: ${{ github.event.head_commit.committer.username }}
COMMIT_MSG: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
COMMIT_TIME: ${{ github.event.head_commit.timestamp }}
run: |
git commit -m "${{ steps.set_vars.outputs.TITLE }}" \
-m "Commit hash for tag: $COMMIT_URL" \
-m "Timestamp for tag: $COMMIT_TIME" \
-m "Committer for tag: @$COMMITTER" \
-m "" \
-m "Commit message last commit:" \
-m "---------------------------" \
-m "$COMMIT_MSG"

- name: "Tag the commit (releases only)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
env:
REF_NAME: ${{ github.ref_name }}
run: git tag "$REF_NAME" $(git rev-parse HEAD)

- name: Push to target branch
run: git push -u origin ${{ steps.set_vars.outputs.BRANCH }} --tags -v