-
Notifications
You must be signed in to change notification settings - Fork 7
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
Add actions and workflows for QIT tests #81
Changes from 7 commits
90e1a23
764e2d7
ad7a5fa
d8f0673
15d3e40
cfb8348
a8f23ba
d7e552e
38a0364
265e00f
af42247
94bd179
e93d3c6
44409f5
5bdc33d
5cf8761
f09dda3
c592289
c0a8ee1
5f318fb
d252f0e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
name: Run QIT for all extensions | ||
|
||
# **What it does**: Runs a suite of tests for all Grow extensions. | ||
# **Why we have it**: To be able to run tests for all extensions at once. For example when we want to compatibility test a new version of the platform (WP/WC). | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
# Basic params. | ||
version: | ||
description: 'Version to be tested' | ||
required: true | ||
type: choice | ||
options: | ||
- latest | ||
- dev | ||
|
||
# Configure which tests to run. | ||
test-activation: | ||
description: 'Should activation be tested?' | ||
required: true | ||
default: true | ||
type: boolean | ||
test-security: | ||
description: 'Should security be tested?' | ||
required: true | ||
default: true | ||
type: boolean | ||
test-phpstan: | ||
description: 'Should phpstan be tested?' | ||
required: true | ||
default: true | ||
type: boolean | ||
test-api: | ||
description: 'Should API be tested?' | ||
required: true | ||
default: true | ||
type: boolean | ||
test-e2e: | ||
description: 'Should E2E be tested? (takes a lot of time)' | ||
required: true | ||
default: false | ||
type: boolean | ||
|
||
# Advanced customization. | ||
options: | ||
description: 'Additional options for `qit` command, like `--optional_features=hpos`.' | ||
required: false | ||
|
||
jobs: | ||
qit-tests: | ||
name: Run QIT Tests | ||
uses: ./.github/workflows/run-qit-extension.yml | ||
secrets: inherit | ||
strategy: | ||
# Allow to test extensions even if one of them fails. | ||
fail-fast: false | ||
matrix: | ||
# List of extensions to be tested. | ||
extension: [automatewoo, automatewoo-birthdays, automatewoo-referrals, google-listings-and-ads, woocommerce-google-analytics-integration] | ||
with: | ||
# Conditional statements are here to allow testing on push triggers, without manual input. To be removed before merging. | ||
version: ${{ inputs.version }} | ||
test-activation: ${{ inputs.test-activation }} | ||
test-security: ${{ inputs.test-security }} | ||
test-phpstan: ${{ inputs.test-phpstan }} | ||
test-api: ${{ inputs.test-api }} | ||
test-e2e: ${{ inputs.test-e2e }} | ||
extension: ${{ matrix.extension }} | ||
options: ${{ inputs.options }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
name: Run QIT for a given extensions | ||
|
||
# **What it does**: Runs a set of QIT tests for a given extension. | ||
# **Why we have it**: To reuse across other repos, to make a full test of a single extension. | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
# Basic params. | ||
extension: | ||
description: Extension to test | ||
required: true | ||
type: string | ||
version: | ||
description: | | ||
Version to be tested: `latest`, `dev`, or `local`. | ||
`latest` will test latest released version, | ||
`dev` will make the action look up for an `{extension}.zip` file in the root | ||
of the repository under the `gha-dev-build` tag, | ||
`local` will look up for an `{extension}.zip` artifact in the current workflow. | ||
required: true | ||
default: 'latest' | ||
type: string | ||
|
||
# Customize which types to run. | ||
test-activation: | ||
description: 'Should activation be tested?' | ||
default: true | ||
type: boolean | ||
test-security: | ||
description: 'Should security be tested?' | ||
default: true | ||
type: boolean | ||
test-phpstan: | ||
description: 'Should PHPStan be tested?' | ||
default: true | ||
type: boolean | ||
test-api: | ||
description: 'Should API be tested?' | ||
default: true | ||
type: boolean | ||
test-e2e: | ||
description: 'Should E2E be tested?' | ||
default: true | ||
type: boolean | ||
|
||
# Advanced customization. | ||
options: | ||
description: 'Additional options for `qit` command, like `--optional_features=hpos`' | ||
type: string | ||
|
||
outputs: | ||
statuses: | ||
description: "Statuses of all tests. Array of integers." | ||
value: ${{ jobs.qit-tests.outputs.statuses }} | ||
|
||
|
||
jobs: | ||
qit-tests: | ||
name: Run QIT Tests | ||
runs-on: ubuntu-20.04 | ||
env: | ||
QIT_DISABLE_ONBOARDING: yes | ||
dev_build: ${{ inputs.version != 'latest' && format('{0}.zip', inputs.extension) || '' }} | ||
outputs: | ||
statuses: ${{ toJSON( steps.*.outputs.status ) }} | ||
steps: | ||
|
||
- name: Download `gha-dev-build` | ||
if: ${{ inputs.version == 'dev' }} | ||
uses: robinraju/release-downloader@v1.8 | ||
with: | ||
repository: "woocommerce/${{ inputs.extension }}" | ||
tag: 'gha-dev-build' | ||
fileName: ${{ env.dev_build }} | ||
token: ${{ secrets.BOT_GH_TOKEN }} | ||
|
||
- name: Download artifact | ||
if: ${{ inputs.version == 'local' }} | ||
uses: actions/download-artifact@v3 | ||
with: | ||
name: ${{ env.dev_build }} | ||
|
||
- name: Install QIT via composer | ||
run: composer require woocommerce/qit-cli | ||
- name: Add Partner | ||
run: | | ||
./vendor/bin/qit partner:add \ | ||
--user='${{ secrets.QIT_PARTNER_USER }}' \ | ||
--application_password='${{ secrets.QIT_PARTNER_SECRET }}' | ||
|
||
- name: Create results dir | ||
run: mkdir -p ./qit-results/${{ inputs.extension }} | ||
|
||
- name: Activation test | ||
id: activation-test | ||
if: ${{ inputs.test-activation == true }} | ||
uses: woocommerce/grow/run-qit-annotate@actions-v1.10.2-pre | ||
timeout-minutes: 5 | ||
with: | ||
type: activation | ||
extension: ${{ inputs.extension }} | ||
extension-file: ${{ env.dev_build }} | ||
options: ${{ inputs.options }} | ||
|
||
- name: Security test | ||
id: security-test | ||
if: ${{ inputs.test-security == true }} | ||
uses: woocommerce/grow/run-qit-annotate@actions-v1.10.2-pre | ||
timeout-minutes: 5 | ||
with: | ||
type: security | ||
extension: ${{ inputs.extension }} | ||
extension-file: ${{ env.dev_build }} | ||
options: ${{ inputs.options }} | ||
|
||
- name: PHPStan test | ||
id: phpstan-test | ||
if: ${{ inputs.test-phpstan == true }} | ||
uses: woocommerce/grow/run-qit-annotate@actions-v1.10.2-pre | ||
timeout-minutes: 5 | ||
with: | ||
type: phpstan | ||
extension: ${{ inputs.extension }} | ||
extension-file: ${{ env.dev_build }} | ||
options: ${{ inputs.options }} | ||
|
||
- name: API test | ||
id: api-test | ||
if: ${{ inputs.test-api == true }} | ||
uses: woocommerce/grow/run-qit-annotate@actions-v1.10.2-pre | ||
timeout-minutes: 5 | ||
with: | ||
type: api | ||
extension: ${{ inputs.extension }} | ||
extension-file: ${{ env.dev_build }} | ||
options: ${{ inputs.options }} | ||
|
||
- name: E2E test | ||
id: e2e-test | ||
if: ${{ inputs.test-e2e == true }} | ||
uses: woocommerce/grow/run-qit-annotate@actions-v1.10.2-pre | ||
timeout-minutes: 30 | ||
with: | ||
type: e2e | ||
extension: ${{ inputs.extension }} | ||
extension-file: ${{ env.dev_build }} | ||
options: ${{ inputs.options }} | ||
|
||
- name: Upload results | ||
uses: actions/upload-artifact@v1 | ||
with: | ||
name: "qit-results-${{ inputs.extension }}" | ||
path: ./qit-results/${{ inputs.extension }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ Custom GitHub actions that help to composite GitHub workflows across the repos m | |
- [`prepare-node`](actions/prepare-node) - Set up Node.js with a specific version, load npm cache, install Node dependencies | ||
- [`prepare-php`](actions/prepare-php) - Set up PHP with a specific version and tools, load Composer cache, install Composer dependencies | ||
- [`publish-extension-dev-build`](actions/publish-extension-dev-build) - Publish extension development build | ||
- [`run-qit-annotate`](actions/run-qit-annotate) - Runs QIT test and annotates the results | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
- [`stylelint-annotation`](actions/stylelint-annotation) - Annotate stylelint results via stylelint formatter | ||
- [`update-version-tags`](actions/update-version-tags) - Update version tags | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Run QIT test | ||
|
||
This action provides the following functionality for GitHub Actions users: | ||
|
||
- Run `qit` test of given type for a given extension | ||
- Annotate the results | ||
- Forward status code, so the consumer can decide how to conclude the results | ||
|
||
|
||
## Usage | ||
|
||
See [action.yml](action.yml) | ||
|
||
### Prerequisites | ||
|
||
- QIT needs to be [installed](https://woocommerce.github.io/qit-documentation/#/cli/getting-started?id=installing-qit) and [authenticated](https://woocommerce.github.io/qit-documentation/#/authenticating?id=cli) | ||
- To setup QIT, you need to set `QIT_DISABLE_ONBOARDING` env to `yes`. | ||
- The action assumes there is `qit-results` directory. You can change it's name using `results-folder` input. | ||
|
||
|
||
### Basic: | ||
|
||
```yaml | ||
jobs: | ||
qit-test: | ||
name: Run QIT Tests | ||
runs-on: ubuntu-20.04 | ||
env: | ||
QIT_DISABLE_ONBOARDING: yes | ||
steps: | ||
- name: Install QIT via composer | ||
run: composer require woocommerce/qit-cli | ||
|
||
- name: Add Partner | ||
run: | | ||
./vendor/bin/qit partner:add \ | ||
--user='${{ secrets.QIT_PARTNER_USER }}' \ | ||
--application_password='${{ secrets.QIT_PARTNER_SECRET }}' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noticed this deprecation message on the GL&A side. Looks like this could be changed to use |
||
|
||
- name: Create results dir | ||
run: mkdir -p ./qit-results/automatewoo | ||
|
||
- name: Security test | ||
id: security-test | ||
uses: woocommerce/grow/run-qit-annotate@actions-v1 | ||
timeout-minutes: 5 | ||
with: | ||
type: security | ||
extension: automatewoo | ||
options: '--optional_features=hpos' | ||
|
||
- name: Echo status | ||
shell: bash | ||
run: echo ${{ jobs.security-test.outputs.status }} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
name: Run QIT test | ||
description: Runs QIT test and annotates the results. | ||
|
||
# **What it does**: Runs a single QIT test and annotates the results. | ||
# **Why we have it**: To reuse across other workflows to test extensions. | ||
|
||
inputs: | ||
# Basic params. | ||
extension: | ||
description: Extension to test | ||
required: true | ||
extension-file: | ||
description: Custom build of the extension to test. If not given, the latest release will be used. | ||
required: false | ||
type: | ||
description: Type of test to run | ||
required: false | ||
default: activation | ||
# Advanced customization. | ||
options: | ||
description: Options to pass to the qit command | ||
required: false | ||
default: '' | ||
results-filename: | ||
description: Custom file name for results | ||
required: false | ||
results-folder: | ||
description: Folder to store results | ||
required: false | ||
default: qit-results | ||
|
||
outputs: | ||
status: | ||
description: "Exit code of the test. May be used, for example, to fail the workflow if the test fails." | ||
value: ${{ steps.run-test.outputs.status }} | ||
summary: | ||
description: "Short summary of the test" | ||
value: ${{ steps.read-summary.outputs.summary }} | ||
resultsURL: | ||
description: "URL to the results of the test" | ||
value: ${{ steps.read-summary.outputs.resultURL }} | ||
|
||
branding: | ||
icon: 'award' | ||
color: 'purple' | ||
|
||
runs: | ||
using: composite | ||
steps: | ||
- name: Run test | ||
id: run-test | ||
# Do not fail when the `qit` fails, so we can annotate the results. | ||
shell: bash --noprofile --norc {0} | ||
continue-on-error: true | ||
env: | ||
# If the custom build is provided, pass it to the `zip` param. | ||
zip: ${{ inputs.extension-file && format('--zip={0}', inputs.extension-file) || '' }} | ||
report_file: ${{ inputs.results-filename || format( '{0}/{1}/{2}/{3}.txt', github.workspace, inputs.results-folder, inputs.extension, inputs.type ) }} | ||
status: 0 | ||
run: | | ||
./vendor/bin/qit run:${{ inputs.type }} ${{ inputs.extension }} \ | ||
$zip \ | ||
${{ inputs.options }} \ | ||
--wait \ | ||
eason9487 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
> $report_file || status=$? | ||
echo "status=$status" >> "$GITHUB_OUTPUT" | ||
echo "report_file=$report_file" >> "$GITHUB_OUTPUT" | ||
cat $report_file | ||
|
||
# Parse the report file, to fetch the essential information. | ||
- name: Read summary | ||
id: read-summary | ||
shell: bash | ||
if: '!cancelled()' | ||
run: | | ||
summary=`grep -Po "(?<=Test Summary)\s+(.*)" ${{ steps.run-test.outputs.report_file }} --color=never` | ||
resultURL=`grep -Po "(?<=Result Url)\s+(.*)" ${{ steps.run-test.outputs.report_file }} --color=never` | ||
echo "summary=$summary" >> $GITHUB_OUTPUT | ||
echo "resultURL=$resultURL" >> $GITHUB_OUTPUT | ||
|
||
# Annotate the results according to the exit code. | ||
- name: Annotate | ||
if: '!cancelled()' | ||
shell: bash | ||
run: | | ||
summary="${{ inputs.type }}: ${{ steps.read-summary.outputs.summary }} - ${{ steps.read-summary.outputs.resultURL }}"; | ||
case ${{ steps.run-test.outputs.status }} in | ||
0) echo "::notice ::$summary" | ||
;; | ||
2) echo "::warning ::$summary" | ||
;; | ||
*) echo "::error ::$summary" | ||
;; | ||
esac |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I guess it right, this step is meant to be used in a way like this line?
A concern is the workflow files in
.github/workflows
directory of this repo won't be included in theactions-v1
releases. As a result, it would become difficult to ensure version compatibility between them.To run QIT tests with a local build, I would suggest leaving the processing of preparing a local extension zip file on the action user side. For example, GLA could either build a zip file within its workflow or run the
actions/download-artifact
step on its own, and this action only needs the local file path as input.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is the way to use it.
I completely agree with that concern. That's why in the OP I mentioned:
I would appreciate your opinion here. I'd say having separate release flows for workflows and separate for actions is too much. I would choose one of those approaches:
actions
tag actually mean "github actions & workflows", thenThe problem here is that. This is a workflow (
jobs.*.uses
), not an atomic action (jobs.*.steps.uses
). This workflow runs as a separate job, from any other workflow or action. So the only way to share a file (I'm aware of) between this workflow and another (GLA's, or other extension's) workflow is to use artifacts. Then this workflow needs to download them itself. Otherwise, how would GLA's job push a file to this job?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version compatibility concern in #81 (comment) is the same as this thread.
Sorry, I omitted a large portion of explanation. The idea is to transform the
run-qit-extension.yml
workflow into a composite action and it involves a degree of change that is not quite easily stated in words. I created a demo in the repo and one in GLA to illustrate how it works.Changes in this repo
run-qit-extension
workflow, create a compositerun-qit-extension
action.qit-partner-user
andqit-partner-secret
inputs to forward the original secret variables.timeout-minutes
as they are not supported in the composite action. Probably it would be better to let the action user specify the timeout.outputs.statuses
as it would need more time or the composite action might not support the same syntax.grow/.github/workflows/run-qit-extension.yml
Lines 52 to 55 in a8f23ba
grow/.github/workflows/run-qit-extension.yml
Lines 65 to 66 in a8f23ba
Changes in GLA
run-qit-extension
action instead.The test run: https://github.com/woocommerce/google-listings-and-ads/actions/runs/6391261008
I didn't continue to make further changes. If adopt this method, the
.github/workflows/run-qit-all.yml
workflow should be able to userun-qit-extension
action as well, and the.github/workflows/run-qit-extension.yml
workflow would be no longer in needed.In this way, the action user sides won't need to use this repo's workflow directly, and this repo doesn't need to add them to any release and versioning flow.
Another advantage is that the action user side wouldn't have to upload artifacts if their action builds a local zip file and uses this action in the same job. For example:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the detailed explanations and the new branch!
I can see it works, and I appreciate how it addresses the following:
However, I'm not sure if I see all the benefits of
The biggest difference I see is granularity. Having
qit
as an atomic action, users could compose it within their workflows.But I think it also has the downsides:
the log is less collapsible and divided.:
as a workflow:
as an action
I was actually thinking of unifying the workflow across our repos so we will not have to implement a workflow and compose actions in every repo but just use the shared entire workflow.
Especially if it comes to the build, I think it is even desirable to have it as a separate workflow that uploads an artifact. So, other workflows and actions running for the same commit could reuse that work, reducing the overall cost and time.
See woocommerce/google-listings-and-ads#2114 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the perspective of this repo, I would suppose its granularity prefers a custom action over a reusable workflow for flexibility in composition and configuration and fewer limitations.
If an automation requirement is highly repetitive or identical across several repos, then a reusable workflow, which might still composite some custom actions within this repo, would be appropriate.
From a practicable point of view, I find it rather difficult to imagine whether it would be easier to do so.
Take GLA as an example, given it has a reusable workflow for building a zip bundle, and each automation of "Bundle watch", "Publish dev build", "E2E test", and "QIT" need a build file as input.
Unless all these automations are in the same workflow, each automation will be grouped into standalone workflows with the same execution conditions, and then build a zip on its own. Because artifact access through
actions/upload-artifact
andactions/download-artifact
is limited within the same workflow run. In this case, the same commit doesn't use the "same" work result (zip bundle), only the extracted build workflow is reused.However, having all of them in the same workflow run seems to make that workflow configuration very complex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main concern is still how the release versions of these reusable workflows in the
.github/workflows
directory will proceed if go with the current solution.The unintuitive understanding of the artifact upload/download split between the use-end repo and this repo is also a concern, but if this complexity trade-off is necessary, then it won't be a blocker.
Agree with this.
GitHub docs say the syntax of
jobs.<job_id>.uses
is{owner}/{repo}/.github/workflows/{filename}@{ref}
and doesn't clarify if the.github/workflows/
part can be changed.Either yes or no, I lean toward leaving reusable workflows under the original directory and keeping custom actions the same as it's:
The main reason is that each of them conforms to the syntax described in GitHub docs respectively.
jobs.<job_id>.steps[*].uses
jobs.<job_id>.uses
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I merged your proposed changes and used action as you suggested.
We can get back to shared workflows if needed in some following PRs, exploring possibilities and flow optimizations there.