Skip to content

Commit 311f515

Browse files
committed
chore: Enable automation testing
Signed-off-by: Steve Hipwell <steve.hipwell@gmail.com>
1 parent 1af72d4 commit 311f515

10 files changed

+381
-315
lines changed

.github/workflows/dotcom-acceptance-tests.yaml

Lines changed: 116 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ name: Acceptance Tests (github.com)
22

33
on:
44
workflow_dispatch:
5-
# push:
6-
# branches:
7-
# - main
8-
# - release-v*
5+
push:
6+
branches:
7+
- main
8+
- release-v*
9+
# pull_request_target:
910
pull_request:
1011
types:
1112
- opened
@@ -23,17 +24,69 @@ concurrency:
2324
permissions: read-all
2425

2526
jobs:
27+
setup:
28+
name: Setup
29+
runs-on: ubuntu-latest
30+
defaults:
31+
run:
32+
shell: bash
33+
outputs:
34+
fork: ${{ steps.check.outputs.fork }}
35+
test: ${{ steps.check.outputs.test }}
36+
environment: ${{ steps.check.outputs.environment }}
37+
steps:
38+
- name: Check
39+
id: check
40+
env:
41+
GITHUB_HEAD_REPO: ${{ case(github.event_name == 'pull_request' || github.event_name == 'pull_request_target', github.event.pull_request.head.repo.full_name, github.repository) }}
42+
GITHUB_BASE_REPO: ${{ case(github.event_name == 'pull_request' || github.event_name == 'pull_request_target', github.event.pull_request.base.repo.full_name, github.repository) }}
43+
ACCTEST_LABEL_SET: ${{ contains(github.event.pull_request.labels.*.name, 'acctest') }}
44+
run: |
45+
set -euo pipefail
46+
47+
fork="true"
48+
test="false"
49+
environment="acctest-dotcom-untrusted"
50+
51+
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]] || [[ "${GITHUB_EVENT_NAME}" == "push" ]]; then
52+
fork="false"
53+
test="true"
54+
environment="acctest-dotcom"
55+
echo "::notice::Running in ${GITHUB_EVENT_NAME} context, proceeding with tests"
56+
else
57+
if [[ "${GITHUB_HEAD_REPO}" == "${GITHUB_BASE_REPO}" ]]; then
58+
fork="false"
59+
test="true"
60+
echo "::notice::Running in ${GITHUB_EVENT_NAME} context from the base repository, proceeding with tests"
61+
else
62+
if [[ "${ACCTEST_LABEL_SET}" == "true" ]]; then
63+
test="true"
64+
echo "::warning::Running in ${GITHUB_EVENT_NAME} context from a fork with acctest label, proceeding with tests"
65+
else
66+
echo "::warning::Running in ${GITHUB_EVENT_NAME} context from a fork, skipping tests"
67+
fi
68+
fi
69+
fi
70+
71+
{
72+
echo "test=${test}"
73+
echo "environment=${environment}"
74+
echo "fork=${fork}"
75+
} >> "${GITHUB_OUTPUT}"
76+
2677
test:
27-
name: Test ${{ matrix.mode }}
28-
if: (github.event_name != 'pull_request' && github.event_name != 'pull_request_target') || contains(github.event.pull_request.labels.*.name, 'acctest')
78+
name: Test ${{ matrix.mode || 'Skipped' }}
79+
needs:
80+
- setup
81+
if: needs.setup.outputs.test == 'true'
2982
runs-on: ubuntu-latest
3083
permissions:
3184
contents: read
3285
environment:
33-
name: acctest-dotcom
86+
name: ${{ needs.setup.outputs.environment }}
3487
strategy:
3588
matrix:
36-
mode: [anonymous, individual, organization] # team, enterprise
89+
mode: [organization] # anonymous, individual, team, enterprise
3790
fail-fast: true
3891
max-parallel: 1
3992
defaults:
@@ -44,33 +97,72 @@ jobs:
4497
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
4598

4699
- name: Check secrets
47-
if: github.event_name == 'pull_request_target'
100+
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
48101
env:
49-
INPUT_ALLOWED_SECRETS: ${{ vars.DOTCOM_ACCEPTANCE_TESTS_ALLOWED_SECRETS || 'GH_TEST_TOKEN' }}
50102
INPUT_SECRETS: ${{ toJSON(secrets) }}
103+
INPUT_ALLOWED_SECRETS: ${{ vars.GH_TEST_ALLOWED_SECRETS }}
51104
run: |
52105
set -eou pipefail
53106
54-
secret_keys="$(jq --raw-output --compact-output '[. | keys[] | select(test("^(?:(?:ACTIONS)|(?:actions)|(?:GITHUB)|(?:github)|(?:TEST)|(?:test))_") | not)] | sort | join(",")' <<<"${INPUT_SECRETS}")"
55-
if [[ "${secret_keys}" != "${INPUT_ALLOWED_SECRETS}" ]]; then
56-
echo "::error::Too many or too few secrets configured: ${secret_keys}"
107+
allowed_secrets="$(jq --raw-input --raw-output --compact-output 'split(",")' <<<"${INPUT_ALLOWED_SECRETS}")"
108+
109+
secret_keys="$(jq --raw-output --compact-output --argjson allowed "${allowed_secrets}" '[[. | to_entries[] | select(.value != "" and .value != "!NOSECRET!")] | from_entries | keys[] | ascii_upcase | select(test("^(?:(?:ACTIONS)|(?:GITHUB)|(?:TEST)|(?:GH_TEST))_") | not) | select((IN($allowed[]) | not))] | sort | join(",")' <<<"${INPUT_SECRETS}")"
110+
if [[ -n "${secret_keys}" ]]; then
111+
echo "::error::Unexpected secrets: ${secret_keys}"
57112
exit 1
58113
fi
59114
60115
- name: Check credentials
61116
id: credentials
62117
if: matrix.mode != 'anonymous'
63118
env:
119+
MATRIX_MODE: ${{ matrix.mode }}
120+
GH_TEST_APP_ID: ${{ vars.GH_TEST_APP_ID }}
121+
GH_TEST_APP_INSTALLATION_ID: ${{ vars.GH_TEST_APP_INSTALLATION_ID }}
122+
GH_TEST_APP_PEM: ${{ secrets.GH_TEST_APP_PEM }}
64123
GH_TEST_TOKEN: ${{ secrets.GH_TEST_TOKEN }}
65124
run: |
66125
set -eou pipefail
67126
68-
if [[ -z "${GH_TEST_TOKEN}" ]]; then
69-
echo "::error::Missing credentials"
70-
exit 1
127+
app_id=""
128+
app_installation_id=""
129+
app_pem=""
130+
token=""
131+
132+
if [[ "${MATRIX_MODE}" == "individual" ]]; then
133+
if [[ -z "${GH_TEST_TOKEN}" ]]; then
134+
echo "::error::Missing token"
135+
exit 1
136+
fi
137+
138+
token="${GH_TEST_TOKEN}"
139+
else
140+
if [[ -z "${GH_TEST_APP_ID}" ]]; then
141+
echo "::error::Missing app id"
142+
exit 1
143+
fi
144+
145+
if [[ -z "${GH_TEST_APP_INSTALLATION_ID}" ]]; then
146+
echo "::error::Missing app installation id"
147+
exit 1
148+
fi
149+
150+
if [[ -z "${GH_TEST_APP_PEM}" ]]; then
151+
echo "::error::Missing app pem"
152+
exit 1
153+
fi
154+
155+
app_id="${GH_TEST_APP_ID}"
156+
app_installation_id="${GH_TEST_APP_INSTALLATION_ID}"
157+
app_pem="${GH_TEST_APP_PEM}"
71158
fi
72159
73-
echo "token=${GH_TEST_TOKEN}" >> "${GITHUB_OUTPUT}"
160+
{
161+
echo "app_id=${app_id}"
162+
echo "app_installation_id=${app_installation_id}"
163+
echo "app_pem=${app_pem}"
164+
echo "token=${token}"
165+
} >> "${GITHUB_OUTPUT}"
74166
75167
- name: Set-up Go
76168
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
@@ -101,11 +193,14 @@ jobs:
101193
TF_ACC_TERRAFORM_PATH: ${{ steps.tf.outputs.path }}
102194
TF_ACC: "1"
103195
TF_LOG: WARN
196+
GITHUB_APP_ID: ${{ steps.credentials.outputs.app_id }}
197+
GITHUB_APP_INSTALLATION_ID: ${{ steps.credentials.outputs.app_installation_id }}
198+
GITHUB_APP_PEM_FILE: ${{ steps.credentials.outputs.app_pem }}
104199
GITHUB_TOKEN: ${{ steps.credentials.outputs.token }}
105200
GITHUB_BASE_URL: https://api.github.com/
106-
GITHUB_OWNER: ${{ (matrix.mode == 'individual' && vars.GH_TEST_LOGIN) || (matrix.mode == 'organization' && vars.GH_TEST_ORG_NAME) || '' }}
107-
GITHUB_USERNAME: ${{ vars.GH_TEST_LOGIN }}
108-
GITHUB_ENTERPRISE_SLUG: ${{ vars.GH_TEST_ENTERPRISE_SLUG }}
201+
GITHUB_OWNER: ${{ case(matrix.mode == 'anonymous', '', matrix.mode == 'individual', vars.GH_TEST_LOGIN, vars.GH_TEST_ORG_NAME) }}
202+
GITHUB_USERNAME: ${{ case(matrix.mode == 'individual', vars.GH_TEST_LOGIN, '') }}
203+
GITHUB_ENTERPRISE_SLUG: ${{ case(matrix.mode == 'enterprise', vars.GH_TEST_ENTERPRISE_SLUG, '') }}
109204
GH_TEST_AUTH_MODE: ${{ matrix.mode }}
110205
GH_TEST_USER_REPOSITORY: ${{ vars.GH_TEST_USER_REPOSITORY }}
111206
GH_TEST_ORG_USER: ${{ vars.GH_TEST_ORG_USER }}
@@ -128,7 +223,7 @@ jobs:
128223
129224
check:
130225
name: Check DotCom Acceptance Tests
131-
if: always() && github.event_name == 'pull_request'
226+
if: always() && (github.event_name == 'pull_request' || github.event_name == 'pull_request_target')
132227
needs:
133228
- test
134229
runs-on: ubuntu-latest

.github/workflows/ghes-acceptance-tests.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ name: Acceptance Tests (GHES)
22

33
on:
44
workflow_dispatch:
5+
# push:
6+
# branches:
7+
# - main
8+
# - release-v*
59
# pull_request_target:
610
# types:
711
# - opened

github/acc_test.go

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ type testAccConfig struct {
3737
baseURL *url.URL
3838

3939
// Auth configuration
40-
authMode testMode
41-
owner string
42-
username string
43-
token string
40+
authMode testMode
41+
owner string
42+
username string
43+
token string
44+
appID string
45+
appInstallationID string
46+
appPEM string
4447

4548
// Enterprise configuration
4649
enterpriseSlug string
@@ -112,13 +115,11 @@ func TestMain(m *testing.M) {
112115
}
113116

114117
config := testAccConfig{
115-
baseURL: baseURL,
116-
authMode: authMode,
117-
testPublicRepository: "terraform-provider-github",
118-
testPublicRepositoryOwner: "integrations",
119-
testPublicReleaseId: 186531906,
120-
// The terraform-provider-github_6.4.0_manifest.json asset ID from
121-
// https://github.com/integrations/terraform-provider-github/releases/tag/v6.4.0
118+
baseURL: baseURL,
119+
authMode: authMode,
120+
testPublicRepository: "terraform-provider-github",
121+
testPublicRepositoryOwner: "integrations",
122+
testPublicReleaseId: 186531906, // The terraform-provider-github_6.4.0_manifest.json asset ID from https://github.com/integrations/terraform-provider-github/releases/tag/v6.4.0
122123
testPublicRelaseAssetId: "207956097",
123124
testPublicRelaseAssetName: "terraform-provider-github_6.4.0_manifest.json",
124125
testPublicReleaseAssetContent: "{\n \"version\": 1,\n \"metadata\": {\n \"protocol_versions\": [\n \"5.0\"\n ]\n }\n}",
@@ -135,30 +136,38 @@ func TestMain(m *testing.M) {
135136
testExternalUser2: os.Getenv("GH_TEST_EXTERNAL_USER2"),
136137
testAdvancedSecurity: os.Getenv("GH_TEST_ADVANCED_SECURITY") == "true",
137138
testRepositoryVisibility: "public",
138-
enterpriseIsEMU: authMode == enterprise && os.Getenv("GH_TEST_ENTERPRISE_IS_EMU") == "true",
139139
}
140140

141141
if config.authMode != anonymous {
142142
config.owner = os.Getenv("GITHUB_OWNER")
143143
config.username = os.Getenv("GITHUB_USERNAME")
144144
config.token = os.Getenv("GITHUB_TOKEN")
145+
config.appID = os.Getenv("GITHUB_APP_ID")
146+
config.appInstallationID = os.Getenv("GITHUB_APP_INSTALLATION_ID")
147+
config.appPEM = os.Getenv("GITHUB_APP_PEM_FILE")
145148

146149
if len(config.owner) == 0 {
147150
fmt.Println("GITHUB_OWNER environment variable not set")
148151
os.Exit(1)
149152
}
150153

151-
if len(config.username) == 0 {
154+
if config.authMode == individual && len(config.username) == 0 {
152155
fmt.Println("GITHUB_USERNAME environment variable not set")
153156
os.Exit(1)
154157
}
155158

156-
if len(config.token) == 0 {
157-
fmt.Println("GITHUB_TOKEN environment variable not set")
159+
if len(config.token) == 0 && (len(config.appID) == 0 || len(config.appInstallationID) == 0 || len(config.appPEM) == 0) {
160+
fmt.Println("authentication not configured")
158161
os.Exit(1)
159162
}
160163
}
161164

165+
if config.authMode != anonymous && config.authMode != individual {
166+
if i, err := strconv.Atoi(os.Getenv("GH_TEST_ORG_APP_INSTALLATION_ID")); err == nil {
167+
config.testOrgAppInstallationId = i
168+
}
169+
}
170+
162171
if config.authMode == enterprise {
163172
config.enterpriseSlug = os.Getenv("GITHUB_ENTERPRISE_SLUG")
164173

@@ -167,21 +176,19 @@ func TestMain(m *testing.M) {
167176
os.Exit(1)
168177
}
169178

170-
i, err := strconv.Atoi(os.Getenv("GH_TEST_ENTERPRISE_EMU_GROUP_ID"))
171-
if err == nil {
172-
config.testEnterpriseEMUGroupId = i
179+
if os.Getenv("GH_TEST_ENTERPRISE_IS_EMU") == "true" {
180+
config.enterpriseIsEMU = true
181+
182+
if i, err := strconv.Atoi(os.Getenv("GH_TEST_ENTERPRISE_EMU_GROUP_ID")); err == nil {
183+
config.testEnterpriseEMUGroupId = i
184+
}
173185
}
174186

175187
if config.enterpriseIsEMU {
176188
config.testRepositoryVisibility = "private"
177189
}
178190
}
179191

180-
i, err := strconv.Atoi(os.Getenv("GH_TEST_ORG_APP_INSTALLATION_ID"))
181-
if err == nil {
182-
config.testOrgAppInstallationId = i
183-
}
184-
185192
testAccConf = &config
186193

187194
configureSweepers()
@@ -292,6 +299,24 @@ func skipUnauthenticated(t *testing.T) {
292299
}
293300
}
294301

302+
func skipNoToken(t *testing.T) {
303+
if testAccConf.authMode == anonymous {
304+
t.Skip("Skipping as test mode not authenticated")
305+
}
306+
if testAccConf.token == "" {
307+
t.Skip("Skipping as no token provided")
308+
}
309+
}
310+
311+
func skipNoApp(t *testing.T) {
312+
if testAccConf.authMode == anonymous {
313+
t.Skip("Skipping as test mode not authenticated")
314+
}
315+
if testAccConf.appID == "" || testAccConf.appInstallationID == "" || testAccConf.appPEM == "" {
316+
t.Skip("Skipping as app not configured")
317+
}
318+
}
319+
295320
func skipUnlessHasOrgs(t *testing.T) {
296321
if !slices.Contains(orgTestModes, testAccConf.authMode) {
297322
t.Skip("Skipping as test mode doesn't have orgs")

0 commit comments

Comments
 (0)