From b17b54fa36a585619cab915961244abbd7a59488 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Tue, 31 May 2022 12:39:46 +1200 Subject: [PATCH 1/2] NEW Create action --- README.md | 5 +- action.yml | 235 +++++++++++++++++++++++++++++++++++++++++++++ behat.php | 16 +++ behat_headless.yml | 33 +++++++ 4 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 action.yml create mode 100644 behat.php create mode 100644 behat_headless.yml diff --git a/README.md b/README.md index c967bff..943058c 100644 --- a/README.md +++ b/README.md @@ -1 +1,4 @@ -# gha-run-tests \ No newline at end of file +# GitHub Action - Run tests +Run Silverstripe CI matrix tests + +See [gha-ci](https://github.com/silverstripe/gha-ci) diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..c17a636 --- /dev/null +++ b/action.yml @@ -0,0 +1,235 @@ +name: Run tests +description: Run tests for a single matrix entry + +inputs: + endtoend: + type: boolean + default: false + # if endtoend_suite is blank or "root" it will run suites defined in root behat.yml + # passing this input is intended for extra_jobs running non-root suites + # e.g. running "asset-admin" behat from silverstripe-installer + endtoend_suite: + type: string + required: false + default: '' + endtoend_config: + type: string + required: false + default: '' + phpcoverage: + type: boolean + default: false + phplinting: + type: boolean + default: false + phpunit: + type: boolean + default: false + phpunit_suite: + type: string + required: false + default: '' + phpunit_fail_on_warning: + type: boolean + default: false + js: + type: boolean + default: false + +runs: + using: composite + steps: + + - name: Validate inputs + shell: bash + env: + PHPUNIT_SUITE: ${{ inputs.phpunit_suite }} + ENDTOEND_SUITE: ${{ inputs.endtoend_suite }} + ENDTOEND_CONFIG: ${{ inputs.endtoend_config }} + run: | + if ! [[ "$PHPUNIT_SUITE" =~ ^[a-zA-Z0-9_\-]*$ ]]; then + echo "Invalid input for phpunit_suite" + exit 1 + fi + if ! [[ "$ENDTOEND_SUITE" =~ ^[a-zA-Z0-9_\-]*$ ]]; then + echo "Invalid input for endtoend_suite" + exit 1 + fi + if ! [[ "$ENDTOEND_CONFIG" =~ ^[a-zA-Z0-9_\./\-]*$ ]]; then + echo "Invalid input for endtoend_config" + exit 1 + fi + + - name: Run PHPUnit + # input booleans are converted to strings + # https://docs.github.com/en/actions/learn-github-actions/expressions#functions + if: ${{ inputs.phpunit == 'true' }} + shell: bash + env: + PHPUNIT_SUITE: ${{ inputs.phpunit_suite }} + run: | + FAIL_ON_WARNING= + if [ "${{ inputs.phpunit_fail_on_warning }}" == "true" ]; then + FAIL_ON_WARNING='--fail-on-warning' + fi + echo "Running PHPUnit with options: $FAIL_ON_WARNING" + if [ "$PHPUNIT_SUITE" == "all" ]; then + vendor/bin/phpunit --verbose --colors=always $FAIL_ON_WARNING + else + vendor/bin/phpunit --verbose --colors=always --testsuite "$PHPUNIT_SUITE" $FAIL_ON_WARNING + fi + echo "Passed" + + - name: Setup chrome and chromedriver + if: ${{ inputs.endtoend == 'true' }} + shell: bash + run: | + echo "Default versions of google-chrome and chromedriver" + GCVR=$(google-chrome --version) + CDVR=$(chromedriver --version) + echo "$GCVR" + echo "$CDVR" + # Example version number is 101.0.4951.64 + [[ "$GCVR" =~ ([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+ ]] + GCV="${BASH_REMATCH[1]}" + [[ "$CDVR" =~ ([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+ ]] + CDV="${BASH_REMATCH[1]}" + # Reinstall if a.b.c versions do not match, though allow a different .d version + if [ "$GCV" != "$CDV" ]; then + WGC=$(which google-chrome) + echo "google-chrome and chromedriver versions do not match, reinstalling" + sudo apt remove -y --purge google-chrome-stable || true + # Note that on ubuntu 20.04 and later, these will be installed via a snap and there seems + # too be a permission error with using snap on github actions, but it does not seem to matter + # mkdir: cannot create directory '/run/user/1001': Permission denied + sudo apt install -y chromium-browser chromium-chromedriver + echo "Updated versions of chromium-browser and chromedriver" + sudo ln -s $(which chromium-browser) "$WGC" + google-chrome --version + chromedriver --version + else + echo "Default versions match, continuing" + fi + + - name: Run end-to-end tests + if: ${{ inputs.endtoend == 'true' }} + shell: bash + env: + ENDTOEND_SUITE: ${{ inputs.endtoend_suite }} + ENDTOEND_CONFIG: ${{ inputs.endtoend_config }} + run: | + echo "Running behat" + BEHAT_CONFIG="behat.yml" + if [ "$ENDTOEND_CONFIG" != "" ]; then + BEHAT_CONFIG="$ENDTOEND_CONFIG" + fi + if [ ! -f "$BEHAT_CONFIG" ]; then + echo "behat.yml config missing" + exit 1 + fi + # Remove any sneaky attempts to put __* files into pull-requests + if [ -f __behat.yml ]; then + rm __behat.yml + fi + if [ -f __behat.php ]; then + rm __behat.php + fi + if [ -f __behat_headless.yml ]; then + rm __behat_headless.yml + fi + cp "$BEHAT_CONFIG" __behat.yml + cp ${{ github.action_path }}/behat.php __behat.php + cp ${{ github.action_path }}/behat_headless.yml __behat_headless.yml + php __behat.php + rm __behat.php + rm __behat_headless.yml + # start chromedriver as a background process + nohup sh -c "chromedriver" > /dev/null 2>&1 & + if [ "$ENDTOEND_SUITE" != "root" ]; then + vendor/bin/behat --colors --strict --config __behat.yml "$ENDTOEND_SUITE" + else + vendor/bin/behat --colors --strict --config __behat.yml + fi + echo "Passed" + + - name: Run JS tests + if: ${{ inputs.js == 'true' }} + shell: bash + run: | + echo "Running JS tests" + if [ ! -f package.json ]; then + echo "package.json missing" + exit 1 + fi + wget https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh + php -r "if (hash_file('sha384', 'install.sh') === 'dd4b116a7452fc3bb8c0e410ceac27e19b0ba0f900fe2f91818a95c12e92130fdfb8170fec170b9fb006d316f6386f2b') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('install.sh'); } echo PHP_EOL;" + if [ ! -f install.sh ]; then + echo "Cannot install nvm" + exit 1 + fi + . install.sh + rm install.sh + export NVM_DIR="$HOME/.nvm" + # this loads nvm into the current terminal + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + if [ ! -f .nvmrc ]; then + echo "Missing .nvmrc" + exit 1 + fi + nvm install + nvm use + rm -rf client/dist + npm install -g yarn + yarn install --network-concurrency 1 + if [ -d vendor/silverstripe/admin ]; then + cd vendor/silverstripe/admin + yarn install --network-concurrency 1 + cd ../../.. + fi + yarn run build + echo "Running git diff" + git diff-files --quiet -w --relative=client + git diff --name-status --relative=client + echo "Running yarn test" + yarn run test + echo "Running yarn lint" + yarn run lint + echo "Passed" + + - name: "Run PHP linting" + if: ${{ inputs.phplinting == 'true' }} + shell: bash + run: | + echo "Running PHPCS" + if [ ! -f phpcs.xml.dist ]; then + echo "Missing phpcs.xml.dist" + exit 1 + fi + vendor/bin/phpcs + # phpstan is optional + if [ -f phpstan.neon.dist ]; then + echo "Running PHPStan" + vendor/bin/phpstan analyse + fi + # cow validation is also done here due to it being a tiny piece of work not meriting its own step + if [ -f .cow.json ]; then + echo "Running cow schema validate" + vendor/bin/cow schema:validate + fi + echo "Passed" + + - name: "Run PHP coverage" + if: ${{ inputs.phpcoverage == 'true' }} + shell: bash + run: | + echo "Running codecov" + curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --import + curl -Os https://uploader.codecov.io/latest/codecov-linux + curl -Os https://uploader.codecov.io/latest/codecov-linux.SHA256SUM + curl -Os https://uploader.codecov.io/latest/codecov-linux.SHA256SUM.sig + gpg --verify codecov-linux.SHA256SUM.sig codecov-linux.SHA256SUM + shasum -a 256 -c codecov-linux.SHA256SUM + chmod +x codecov-linux + phpdbg -qrr vendor/bin/phpunit --coverage-clover=coverage.xml + ./codecov-linux -f coverage.xml; + echo "coverage.xml generated and uploaded to codecov" diff --git a/behat.php b/behat.php new file mode 100644 index 0000000..f1b0f29 --- /dev/null +++ b/behat.php @@ -0,0 +1,16 @@ + Date: Tue, 31 May 2022 16:18:33 +1200 Subject: [PATCH 2/2] MNT Add auto-tag workflow --- .github/workflows/auto-tag.yml | 12 ++++ README.md | 2 +- action.yml | 104 +++++++++++++++++---------------- behat.php | 22 ++++--- behat_headless.yml | 5 +- 5 files changed, 83 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/auto-tag.yml diff --git a/.github/workflows/auto-tag.yml b/.github/workflows/auto-tag.yml new file mode 100644 index 0000000..33446ca --- /dev/null +++ b/.github/workflows/auto-tag.yml @@ -0,0 +1,12 @@ +name: Auto-tag +on: + push: + tags: + - '*.*.*' +jobs: + auto-tag: + name: Auto-tag + runs-on: ubuntu-latest + steps: + - name: Auto-tag + uses: silverstripe/gha-auto-tag@main diff --git a/README.md b/README.md index 943058c..028cb16 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # GitHub Action - Run tests Run Silverstripe CI matrix tests -See [gha-ci](https://github.com/silverstripe/gha-ci) +Only intended to be used within [gha-ci](https://github.com/silverstripe/gha-ci). The inputs all come from the matrix generated as a part of that workflow. diff --git a/action.yml b/action.yml index c17a636..52b2898 100644 --- a/action.yml +++ b/action.yml @@ -2,12 +2,19 @@ name: Run tests description: Run tests for a single matrix entry inputs: + phpunit: + type: boolean + default: false + phpunit_suite: + type: string + required: false + default: '' + phpunit_fail_on_warning: + type: boolean + default: false endtoend: type: boolean default: false - # if endtoend_suite is blank or "root" it will run suites defined in root behat.yml - # passing this input is intended for extra_jobs running non-root suites - # e.g. running "asset-admin" behat from silverstripe-installer endtoend_suite: type: string required: false @@ -16,23 +23,13 @@ inputs: type: string required: false default: '' - phpcoverage: - type: boolean - default: false - phplinting: - type: boolean - default: false - phpunit: + js: type: boolean default: false - phpunit_suite: - type: string - required: false - default: '' - phpunit_fail_on_warning: + phpcoverage: type: boolean default: false - js: + phplinting: type: boolean default: false @@ -62,22 +59,19 @@ runs: - name: Run PHPUnit # input booleans are converted to strings - # https://docs.github.com/en/actions/learn-github-actions/expressions#functions if: ${{ inputs.phpunit == 'true' }} shell: bash env: PHPUNIT_SUITE: ${{ inputs.phpunit_suite }} run: | - FAIL_ON_WARNING= - if [ "${{ inputs.phpunit_fail_on_warning }}" == "true" ]; then - FAIL_ON_WARNING='--fail-on-warning' + PHPUNIT_OPTIONS="--verbose --colors=always" + if [[ "$PHPUNIT_SUITE" != "all" ]] && [[ "$PHPUNIT_SUITE" != "" ]]; then + PHPUNIT_OPTIONS="$PHPUNIT_OPTIONS --testsuite "$PHPUNIT_SUITE"" fi - echo "Running PHPUnit with options: $FAIL_ON_WARNING" - if [ "$PHPUNIT_SUITE" == "all" ]; then - vendor/bin/phpunit --verbose --colors=always $FAIL_ON_WARNING - else - vendor/bin/phpunit --verbose --colors=always --testsuite "$PHPUNIT_SUITE" $FAIL_ON_WARNING + if [[ "${{ inputs.phpunit_fail_on_warning }}" == "true" ]]; then + PHPUNIT_OPTIONS="$PHPUNIT_OPTIONS --fail-on-warning" fi + vendor/bin/phpunit $PHPUNIT_OPTIONS echo "Passed" - name: Setup chrome and chromedriver @@ -95,12 +89,12 @@ runs: [[ "$CDVR" =~ ([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+ ]] CDV="${BASH_REMATCH[1]}" # Reinstall if a.b.c versions do not match, though allow a different .d version - if [ "$GCV" != "$CDV" ]; then + if [[ "$GCV" != "$CDV" ]]; then WGC=$(which google-chrome) echo "google-chrome and chromedriver versions do not match, reinstalling" - sudo apt remove -y --purge google-chrome-stable || true - # Note that on ubuntu 20.04 and later, these will be installed via a snap and there seems - # too be a permission error with using snap on github actions, but it does not seem to matter + sudo apt remove -y --purge google-chrome-stable + # Note that on ubuntu 20.04 and later, these will be installed via a snap. When trying to install + # chromium (or any other snaps), we get a permission error, but it doesn't seem to cause problem. The error looks like this: # mkdir: cannot create directory '/run/user/1001': Permission denied sudo apt install -y chromium-browser chromium-chromedriver echo "Updated versions of chromium-browser and chromedriver" @@ -120,23 +114,24 @@ runs: run: | echo "Running behat" BEHAT_CONFIG="behat.yml" - if [ "$ENDTOEND_CONFIG" != "" ]; then + if [[ "$ENDTOEND_CONFIG" != "" ]]; then BEHAT_CONFIG="$ENDTOEND_CONFIG" fi - if [ ! -f "$BEHAT_CONFIG" ]; then - echo "behat.yml config missing" + if ! [[ -f "$BEHAT_CONFIG" ]]; then + echo "$BEHAT_CONFIG config file missing" exit 1 fi - # Remove any sneaky attempts to put __* files into pull-requests - if [ -f __behat.yml ]; then + # Remove any sneaky attempts to put __behat* files into pull-requests + if [[ -f __behat.yml ]]; then rm __behat.yml fi - if [ -f __behat.php ]; then + if [[ -f __behat.php ]]; then rm __behat.php fi - if [ -f __behat_headless.yml ]; then + if [[ -f __behat_headless.yml ]]; then rm __behat_headless.yml fi + # Copy files from the action to temporary locations to generate the new headless behat config cp "$BEHAT_CONFIG" __behat.yml cp ${{ github.action_path }}/behat.php __behat.php cp ${{ github.action_path }}/behat_headless.yml __behat_headless.yml @@ -145,7 +140,7 @@ runs: rm __behat_headless.yml # start chromedriver as a background process nohup sh -c "chromedriver" > /dev/null 2>&1 & - if [ "$ENDTOEND_SUITE" != "root" ]; then + if [[ "$ENDTOEND_SUITE" != "root" ]]; then vendor/bin/behat --colors --strict --config __behat.yml "$ENDTOEND_SUITE" else vendor/bin/behat --colors --strict --config __behat.yml @@ -157,13 +152,26 @@ runs: shell: bash run: | echo "Running JS tests" - if [ ! -f package.json ]; then + if [[ ! -f package.json ]]; then echo "package.json missing" exit 1 fi + if [[ ! -f .nvmrc ]]; then + echo "Missing .nvmrc" + exit 1 + fi wget https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh - php -r "if (hash_file('sha384', 'install.sh') === 'dd4b116a7452fc3bb8c0e410ceac27e19b0ba0f900fe2f91818a95c12e92130fdfb8170fec170b9fb006d316f6386f2b') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('install.sh'); } echo PHP_EOL;" - if [ ! -f install.sh ]; then + php -r ' + $hash = "dd4b116a7452fc3bb8c0e410ceac27e19b0ba0f900fe2f91818a95c12e92130fdfb8170fec170b9fb006d316f6386f2b"; + if (hash_file("sha384", "install.sh") === $hash) { + echo "Installer verified"; + } else { + echo "Installer corrupt"; + unlink('install.sh'); + } + echo PHP_EOL; + ' + if [[ ! -f install.sh ]]; then echo "Cannot install nvm" exit 1 fi @@ -171,17 +179,13 @@ runs: rm install.sh export NVM_DIR="$HOME/.nvm" # this loads nvm into the current terminal - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - if [ ! -f .nvmrc ]; then - echo "Missing .nvmrc" - exit 1 - fi + [[ -s "$NVM_DIR/nvm.sh" ]] && \. "$NVM_DIR/nvm.sh" nvm install nvm use rm -rf client/dist npm install -g yarn yarn install --network-concurrency 1 - if [ -d vendor/silverstripe/admin ]; then + if [[ -d vendor/silverstripe/admin ]]; then cd vendor/silverstripe/admin yarn install --network-concurrency 1 cd ../../.. @@ -201,18 +205,18 @@ runs: shell: bash run: | echo "Running PHPCS" - if [ ! -f phpcs.xml.dist ]; then - echo "Missing phpcs.xml.dist" + if ! [[ -f phpcs.xml ]] && ! [[ -f phpcs.xml.dist ]]; then + echo "Missing phpcs.xml or phpcs.xml.dist" exit 1 fi vendor/bin/phpcs # phpstan is optional - if [ -f phpstan.neon.dist ]; then + if [[ -f phpstan.neon.dist ]]; then echo "Running PHPStan" vendor/bin/phpstan analyse fi # cow validation is also done here due to it being a tiny piece of work not meriting its own step - if [ -f .cow.json ]; then + if [[ -f .cow.json ]]; then echo "Running cow schema validate" vendor/bin/cow schema:validate fi diff --git a/behat.php b/behat.php index f1b0f29..540a43c 100644 --- a/behat.php +++ b/behat.php @@ -2,15 +2,19 @@ // this script will update the modules behat.yml to work with headless chrome // uses behat_headless.yml as the main behat.yml file, // and adds in the 'suites' from the module behat.yml -$a = trim(file_get_contents('__behat_headless.yml')); -$b = file_get_contents('__behat.yml'); -preg_match("#(?s) suites:(.+?)\n [a-z]#", $b, $m); -if (!$m) { - preg_match("#(?s) suites: (.+?)$#", $b, $m); +$behatHeadless = trim(file_get_contents('__behat_headless.yml')); +$behat = file_get_contents('__behat.yml'); +// Match where suites are defined with additional configuration. +// Matches everything after "suites" before the next property starts. +preg_match("# suites:(.+?)\n [a-z]#s", $behat, $matches); +if (!$matches) { + // Match where a suite name is given as a string or array inline with the suites key + // e.g. "suites: some-suite" or "suites: []" + preg_match("# suites: (.+?)$#s", $behat, $matches); } -if (!$m) { +if (!$matches) { echo "Could not match suites in behat.yml, cannot run behat\n\n"; - die; + exit(1); } -$c = str_replace('suites: []', 'suites: ' . $m[1], $a); -file_put_contents('__behat.yml', $c); +$combinedBehat = str_replace('suites: []', 'suites: ' . $matches[1], $behatHeadless); +file_put_contents('__behat.yml', $combinedBehat); diff --git a/behat_headless.yml b/behat_headless.yml index dd15637..ad44c78 100644 --- a/behat_headless.yml +++ b/behat_headless.yml @@ -18,8 +18,9 @@ default: # disable gpu is often mentioned as fix after headless chrome suddenly breaks after an update # leaving it in just in case to prevent hard to diagnose errors later - "--disable-gpu" - # this following have been used by other to things working not sure which ones - # not sure where are actually required. these may fix future problems + # the following options have been used in dev to fix various issues. + # not sure which ones# are actually required, but it works with thi + # configuration and these may fix future problems #https://stackoverflow.com/a/43840128/1689770 - "--disable-infobars" # https://stackoverflow.com/a/50725918/1689770