1
name: Ephemeral env workflow
9
runs-on: "ubuntu-22.04"
10
if: github.event.issue.pull_request
12
has-secrets: ${{ steps.check.outputs.has-secrets }}
14
- name: "Check for secrets"
18
if [ -n "${{ (secrets.AWS_ACCESS_KEY_ID != '' && secrets.AWS_SECRET_ACCESS_KEY != '') || '' }}" ]; then
19
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
22
ephemeral-env-comment:
24
group: ${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}-comment
25
cancel-in-progress: true
27
if: needs.config.outputs.has-secrets
28
name: Evaluate ephemeral env comment trigger (/testenv)
33
slash-command: ${{ steps.eval-body.outputs.result }}
34
feature-flags: ${{ steps.eval-feature-flags.outputs.result }}
39
echo "Comment on PR #${{ github.event.issue.number }} by ${{ github.event.issue.user.login }}, ${{ github.event.comment.author_association }}"
41
- name: Eval comment body for /testenv slash command
42
uses: actions/github-script@v7
45
result-encoding: string
47
const pattern = /^\/testenv (up|down)/
48
const result = pattern.exec(context.payload.comment.body)
49
return result === null ? 'noop' : result[1]
51
- name: Eval comment body for feature flags
52
uses: actions/github-script@v7
53
id: eval-feature-flags
56
const pattern = /FEATURE_(\w+)=(\w+)/g;
58
[...context.payload.comment.body.matchAll(pattern)].forEach(match => {
60
name: `SUPERSET_FEATURE_${match[1]}`,
67
- name: Limit to committers
69
steps.eval-body.outputs.result != 'noop' &&
70
github.event.comment.author_association != 'MEMBER' &&
71
github.event.comment.author_association != 'OWNER'
72
uses: actions/github-script@v7
74
github-token: ${{github.token}}
76
const errMsg = '@${{ github.event.comment.user.login }} Ephemeral environment creation is currently limited to committers.'
77
github.rest.issues.createComment({
78
issue_number: ${{ github.event.issue.number }},
79
owner: context.repo.owner,
80
repo: context.repo.repo,
83
core.setFailed(errMsg)
85
ephemeral-docker-build:
87
group: ${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}-build
88
cancel-in-progress: true
89
needs: ephemeral-env-comment
90
name: ephemeral-docker-build
93
- name: Get Info from comment
94
uses: actions/github-script@v7
99
owner: context.repo.owner,
100
repo: context.repo.repo,
101
pull_number: ${{ github.event.issue.number }},
103
core.info(`Getting PR #${request.pull_number} from ${request.owner}/${request.repo}`)
104
const pr = await github.rest.pulls.get(request);
110
echo "sha=${{ fromJSON(steps.get-pr-info.outputs.result).head.sha }}" >> $GITHUB_OUTPUT
112
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} : ${{steps.get-sha.outputs.sha}} )"
113
uses: actions/checkout@v4
115
ref: ${{ steps.get-sha.outputs.sha }}
116
persist-credentials: false
119
uses: docker/setup-qemu-action@v3
121
- name: Set up Docker Buildx
122
uses: docker/setup-buildx-action@v3
124
- name: Build ephemeral env image
126
./scripts/build_docker.py \
129
--build_context_ref ${{ github.event.issue.number }}
131
- name: Configure AWS credentials
132
uses: aws-actions/configure-aws-credentials@v4
134
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
135
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
136
aws-region: us-west-2
138
- name: Login to Amazon ECR
140
uses: aws-actions/amazon-ecr-login@v2
142
- name: Load, tag and push image to ECR
145
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
146
ECR_REPOSITORY: superset-ci
147
IMAGE_TAG: apache/superset:${{ steps.get-sha.outputs.sha }}-ci
149
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-${{ github.event.issue.number }}-ci
150
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
153
needs: [ephemeral-env-comment, ephemeral-docker-build]
154
if: needs.ephemeral-env-comment.outputs.slash-command == 'up'
155
name: Spin up an ephemeral environment
156
runs-on: ubuntu-22.04
162
- uses: actions/checkout@v4
164
persist-credentials: false
166
- name: Configure AWS credentials
167
uses: aws-actions/configure-aws-credentials@v4
169
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
170
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
171
aws-region: us-west-2
173
- name: Login to Amazon ECR
175
uses: aws-actions/amazon-ecr-login@v2
177
- name: Check target image exists in ECR
179
continue-on-error: true
181
aws ecr describe-images \
182
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
183
--repository-name superset-ci \
184
--image-ids imageTag=pr-${{ github.event.issue.number }}-ci
186
- name: Fail on missing container image
187
if: steps.check-image.outcome == 'failure'
188
uses: actions/github-script@v7
190
github-token: ${{github.token}}
192
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.'
193
github.rest.issues.createComment({
194
issue_number: ${{ github.event.issue.number }},
195
owner: context.repo.owner,
196
repo: context.repo.repo,
199
core.setFailed(errMsg)
201
- name: Fill in the new image ID in the Amazon ECS task definition
203
uses: aws-actions/amazon-ecs-render-task-definition@v1
205
task-definition: .github/workflows/ecs-task-definition.json
206
container-name: superset-ci
207
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.issue.number }}-ci
209
- name: Update env vars in the Amazon ECS task definition
211
cat <<< "$(jq '.containerDefinitions[0].environment += ${{ needs.ephemeral-env-comment.outputs.feature-flags }}' < ${{ steps.task-def.outputs.task-definition }})" > ${{ steps.task-def.outputs.task-definition }}
213
- name: Describe ECS service
214
id: describe-services
216
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.issue.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
217
- name: Create ECS service
218
if: steps.describe-services.outputs.active != 'true'
221
ECR_SUBNETS: subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
222
ECR_SECURITY_GROUP: sg-092ff3a6ae0574d91
224
aws ecs create-service \
225
--cluster superset-ci \
226
--service-name pr-${{ github.event.issue.number }}-service \
227
--task-definition superset-ci \
228
--launch-type FARGATE \
230
--platform-version LATEST \
231
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
232
--tags key=pr,value=${{ github.event.issue.number }} key=github_user,value=${{ github.actor }}
234
- name: Deploy Amazon ECS task definition
236
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
238
task-definition: ${{ steps.task-def.outputs.task-definition }}
239
service: pr-${{ github.event.issue.number }}-service
241
wait-for-service-stability: true
247
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.issue.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
249
- name: Get network interface
252
echo "eni=$(aws ecs describe-tasks --cluster superset-ci --tasks ${{ steps.list-tasks.outputs.task }} | jq '.tasks | .[0] | .attachments | .[0] | .details | map(select(.name=="networkInterfaceId")) | .[0] | .value')" >> $GITHUB_OUTPUT
254
- name: Get public IP
257
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
259
- name: Comment (success)
261
uses: actions/github-script@v7
263
github-token: ${{github.token}}
265
github.rest.issues.createComment({
266
issue_number: ${{ github.event.issue.number }},
267
owner: context.repo.owner,
268
repo: context.repo.repo,
269
body: '@${{ github.event.comment.user.login }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are `admin`/`admin`. Please allow several minutes for bootstrapping and startup.'
272
- name: Comment (failure)
274
uses: actions/github-script@v7
276
github-token: ${{github.token}}
278
github.rest.issues.createComment({
279
issue_number: ${{ github.event.issue.number }},
280
owner: context.repo.owner,
281
repo: context.repo.repo,
282
body: '@${{ github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'