Integration Tests #263
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Integration Tests | |
on: | |
workflow_dispatch: | |
workflow_run: | |
workflows: ['CI'] | |
branches: | |
- main | |
- 'releases/*' | |
types: | |
- completed | |
schedule: | |
- cron: '0 22 * * 3' | |
jobs: | |
integration-tests: | |
name: Integration Test | |
runs-on: ubuntu-latest | |
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }} | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- auth: PAT | |
owner: dsanders11 | |
project_number: 11 | |
- auth: PAT | |
owner: dsanders11-playground-org | |
project_number: 2 | |
- auth: GHA | |
owner: dsanders11-playground-org | |
project_number: 2 | |
steps: | |
- name: Checkout | |
id: checkout | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- name: Get Date | |
uses: ./github-script/ | |
id: get-date | |
with: | |
result-encoding: string | |
script: | | |
return new Date().toISOString() | |
- name: Generate GitHub App Token | |
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1 | |
id: generate-app-token | |
if: ${{ matrix.auth == 'GHA' }} | |
with: | |
creds: ${{ secrets.GH_APP_CREDS }} | |
org: ${{ matrix.owner }} | |
- name: Get Auth Token | |
id: get-auth-token | |
run: echo "token=${{ steps.generate-app-token.outputs.token || secrets.PAT }}" >> "$GITHUB_OUTPUT" | |
- name: Create Template View | |
uses: ./github-script/ | |
id: template-view | |
with: | |
script: | | |
return { | |
"type": "Favorite", | |
"foo": "bar" | |
} | |
- name: Copy Project | |
uses: ./copy-project/ | |
id: copy-project | |
with: | |
drafts: true | |
owner: ${{ matrix.owner }} | |
project-number: ${{ matrix.project_number }} | |
# public: true | |
target-owner: ${{ matrix.owner }} | |
template-view: ${{ steps.template-view.outputs.result }} | |
title: Integration Test Project | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Get Draft Issue ID | |
id: get-draft-issue-id | |
run: | | |
set -eo pipefail | |
echo "id=$(gh project item-list ${{ steps.copy-project.outputs.number }} --owner ${{ steps.copy-project.outputs.owner }} --format json | jq -r '.items[0] | .id')" >> "$GITHUB_OUTPUT" | |
env: | |
GH_TOKEN: ${{ steps.get-auth-token.outputs.token }} | |
- name: Get Draft Issue | |
uses: ./get-item/ | |
id: get-draft-issue | |
with: | |
field: Priority | |
item: ${{ steps.get-draft-issue-id.outputs.id }} | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Draft Issue | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
assert.strictEqual('${{ steps.get-draft-issue.outputs.title }}', 'My Favorite Issue'); | |
assert.strictEqual('${{ steps.get-draft-issue.outputs.field-value }}', 'Low'); | |
assert.match(`${{ steps.get-draft-issue.outputs.body }}`, /Here's another bar/); | |
- name: Run Completed By | |
uses: ./completed-by/ | |
id: completed-by | |
with: | |
field-value: Done | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Draft Issue Is Completed | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
const item = await actions.getItem( | |
'${{ steps.copy-project.outputs.owner }}', | |
'${{ steps.copy-project.outputs.number }}', | |
'${{ steps.get-draft-issue-id.outputs.id }}', | |
'Status' | |
) | |
assert.strictEqual(item.field?.value, 'Done'); | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Add Item | |
uses: ./add-item/ | |
id: add-item | |
with: | |
content-url: https://github.com/dsanders11/project-actions/pull/2 | |
field: Added | |
field-value: ${{ steps.get-date.outputs.result }} | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
# HACK - This is a workaround for a GitHub change in behavior | |
# where the item is not immediately available after creation | |
- name: Sleep (Wait for Item to be Added) | |
run: sleep 5 | |
- name: Get Added Item | |
uses: ./get-item/ | |
id: get-added-item | |
with: | |
field: Added | |
item: ${{ steps.add-item.outputs.id }} | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Added Item Field Value | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
assert.strictEqual('${{ steps.get-added-item.outputs.field-value }}', new Date('${{ steps.get-date.outputs.result }}').toISOString().split('T')[0]); | |
- name: Edit Item | |
uses: ./edit-item/ | |
id: edit-item | |
with: | |
field: Priority | |
field-value: ⛰️ High | |
item: ${{ steps.get-added-item.outputs.id }} | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Edit Item (Not Found) | |
uses: ./edit-item/ | |
id: edit-item-not-found | |
with: | |
fail-if-item-not-found: false | |
field: Priority | |
field-value: ⛰️ High | |
item: foobar | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Get Item | |
uses: ./get-item/ | |
id: get-edited-item | |
with: | |
field: Priority | |
item: ${{ steps.edit-item.outputs.id }} | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Get Item (Not Found) | |
uses: ./get-item/ | |
id: get-item-not-found | |
with: | |
fail-if-item-not-found: false | |
field: Priority | |
item: foobar | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Edited Item Field Value | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
assert.strictEqual('${{ steps.get-edited-item.outputs.field-value }}', '⛰️ High'); | |
- name: Test GitHub Script Action | |
uses: ./github-script/ | |
with: | |
token: ${{ steps.get-auth-token.outputs.token }} | |
script: | | |
const assert = require('node:assert'); | |
const item = await actions.getItem( | |
'${{ steps.copy-project.outputs.owner }}', | |
'${{ steps.copy-project.outputs.number }}', | |
'${{ steps.edit-item.outputs.id }}', | |
'Priority' | |
); | |
const items = await actions.getAllItems('${{ steps.copy-project.outputs.id }}'); | |
assert.strictEqual(item.field?.value, '⛰️ High'); | |
assert.strictEqual(items.length, 2, 'Expected 2 items'); | |
# - name: Archive Item | |
# uses: ./archive-item/ | |
# id: archive-item | |
# with: | |
# item: ${{ steps.add-item.outputs.id }} | |
# owner: ${{ steps.copy-project.outputs.owner }} | |
# project-number: ${{ steps.copy-project.outputs.number }} | |
# token: ${{ steps.get-auth-token.outputs.token }} | |
# - name: Unarchive Item | |
# uses: ./archive-item/ | |
# id: unarchive-item | |
# with: | |
# archived: false | |
# item: ${{ steps.add-item.outputs.id }} | |
# owner: ${{ steps.copy-project.outputs.owner }} | |
# project-number: ${{ steps.copy-project.outputs.number }} | |
# token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Delete Item | |
uses: ./delete-item/ | |
id: delete-item | |
with: | |
item: ${{ steps.edit-item.outputs.id }} | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Delete Item (Not Found) | |
uses: ./delete-item/ | |
id: delete-item-not-found | |
with: | |
item: foobar | |
fail-if-item-not-found: false | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Link Project to Repository | |
uses: ./link-project/ | |
id: link-project-to-repo | |
if: ${{ matrix.owner == 'dsanders11' }} | |
with: | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
repository: dsanders11/project-actions | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Project is Linked to Repository | |
uses: ./github-script/ | |
if: ${{ matrix.owner == 'dsanders11' }} | |
with: | |
token: ${{ steps.get-auth-token.outputs.token }} | |
script: | | |
const assert = require('node:assert'); | |
const { projectV2 } = await github.graphql( | |
`query getProjectLinkedRepos($projectId: ID!) { | |
projectV2: node(id: $projectId) { | |
... on ProjectV2 { | |
id | |
repositories(first: 10) { | |
nodes { | |
id | |
nameWithOwner | |
} | |
} | |
} | |
} | |
}`, | |
{ projectId: '${{ steps.copy-project.outputs.id }}' } | |
); | |
assert.strictEqual(projectV2.repositories.nodes.length, 1, 'Expected one linked repository'); | |
assert.strictEqual(projectV2.repositories.nodes[0].nameWithOwner, 'dsanders11/project-actions', 'Project not linked to repository'); | |
assert.strictEqual(projectV2.repositories.nodes[0].id, '${{ steps.link-project-to-repo.outputs.repository-id }}', `Output 'repository-id' is not as expected`); | |
- name: Link Project to Team | |
uses: ./link-project/ | |
id: link-project-to-team | |
if: ${{ matrix.owner == 'dsanders11-playground-org' }} | |
with: | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
team: dsanders11-playground-org/maintainers | |
token: ${{ steps.get-auth-token.outputs.token }} | |
# HACK - Sometimes the linking isn't immediately reflected | |
- name: Sleep (Wait for Project to be Linked) | |
run: sleep 5 | |
- name: Check Project is Linked to Team | |
uses: ./github-script/ | |
if: ${{ matrix.owner == 'dsanders11-playground-org' }} | |
with: | |
token: ${{ steps.get-auth-token.outputs.token }} | |
script: | | |
const assert = require('node:assert'); | |
const { projectV2 } = await github.graphql( | |
`query getProjectLinkedRepos($projectId: ID!) { | |
projectV2: node(id: $projectId) { | |
... on ProjectV2 { | |
id | |
teams(first: 10) { | |
nodes { | |
id | |
name | |
} | |
} | |
} | |
} | |
}`, | |
{ projectId: '${{ steps.copy-project.outputs.id }}' } | |
); | |
assert.strictEqual(projectV2.teams.nodes.length, 1, 'Expected one linked team'); | |
assert.strictEqual(projectV2.teams.nodes[0].name, 'maintainers', 'Project not linked to team'); | |
assert.strictEqual(projectV2.teams.nodes[0].id, '${{ steps.link-project-to-team.outputs.team-id }}', `Output 'team-id' is not as expected`); | |
- name: Edit Project | |
uses: ./edit-project/ | |
id: edit-project | |
with: | |
description: New Description | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
readme: This is the readme | |
title: New Title ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Find Project | |
uses: ./find-project/ | |
id: find-project | |
with: | |
owner: ${{ matrix.owner }} | |
title: New Title ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Find Project (Not Found) | |
uses: ./find-project/ | |
id: find-project-not-found | |
with: | |
fail-if-project-not-found: false | |
owner: ${{ matrix.owner }} | |
title: Foobar | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Confirm Project Found | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
assert.strictEqual('${{ steps.copy-project.outputs.number }}', '${{ steps.find-project.outputs.number }}', 'Expect to find project by title'); | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Get Project | |
uses: ./get-project/ | |
id: get-project | |
with: | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Project Values | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
assert.strictEqual('${{ steps.get-project.outputs.title }}', 'New Title ${{ steps.copy-project.outputs.number }}'); | |
assert.strictEqual('${{ steps.get-project.outputs.description }}', 'New Description'); | |
assert.strictEqual('${{ steps.get-project.outputs.readme }}', 'This is the readme'); | |
- name: Find Workflow | |
uses: ./find-workflow/ | |
id: find-workflow | |
with: | |
owner: ${{ matrix.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
name: 'Item closed' | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Workflow Values | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
assert.strictEqual('${{ steps.find-workflow.outputs.name }}', 'Item closed'); | |
assert.strictEqual(${{ steps.find-workflow.outputs.enabled }}, true); | |
assert.strictEqual('${{ steps.find-workflow.outputs.project-id }}', '${{ steps.get-project.outputs.id }}'); | |
- name: Get Workflow | |
uses: ./get-workflow/ | |
id: get-workflow | |
with: | |
owner: ${{ matrix.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
number: ${{ steps.find-workflow.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Check Workflow Values | |
uses: ./github-script/ | |
with: | |
script: | | |
const assert = require('node:assert'); | |
assert.strictEqual('${{ steps.get-workflow.outputs.id }}', '${{ steps.find-workflow.outputs.id }}'); | |
assert.strictEqual('${{ steps.get-workflow.outputs.name }}', 'Item closed'); | |
assert.strictEqual('${{ steps.get-workflow.outputs.number }}', '${{ steps.find-workflow.outputs.number }}'); | |
assert.strictEqual(${{ steps.get-workflow.outputs.enabled }}, true); | |
assert.strictEqual('${{ steps.get-workflow.outputs.project-id }}', '${{ steps.get-project.outputs.id }}'); | |
- name: Close Project | |
uses: ./close-project/ | |
id: close-project | |
with: | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Close Project (Not Found) | |
uses: ./close-project/ | |
id: close-project-not-found | |
with: | |
fail-if-project-not-found: false | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: 99999 | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Find Closed Project | |
uses: ./find-project/ | |
id: find-closed-project | |
with: | |
owner: ${{ steps.copy-project.outputs.owner }} | |
title: ${{ steps.copy-project.outputs.title }} | |
include-closed: true | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Reopen Project | |
uses: ./close-project/ | |
id: reopen-project | |
with: | |
closed: false | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Delete Project | |
uses: ./delete-project/ | |
id: delete-project | |
with: | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: ${{ steps.copy-project.outputs.number }} | |
token: ${{ steps.get-auth-token.outputs.token }} | |
- name: Delete Project (Not Found) | |
uses: ./delete-project/ | |
id: delete-project-not-found | |
with: | |
fail-if-project-not-found: false | |
owner: ${{ steps.copy-project.outputs.owner }} | |
project-number: 99999 | |
token: ${{ steps.get-auth-token.outputs.token }} |