2021-02-24 13:50:52 -05:00
name : Ephemeral env workflow
on :
issue_comment :
types : [ created]
2024-02-01 10:08:41 -05:00
# cancel previous workflow jobs for PRs
concurrency :
group : ${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}
cancel-in-progress : true
2021-02-24 13:50:52 -05:00
jobs :
2023-04-14 11:23:00 -04:00
config :
runs-on : "ubuntu-latest"
2021-02-24 13:50:52 -05:00
if : github.event.issue.pull_request
2023-04-14 11:23:00 -04:00
outputs :
has-secrets : ${{ steps.check.outputs.has-secrets }}
steps :
- name : "Check for secrets"
id : check
shell : bash
run : |
if [ -n "${{ (secrets.AWS_ACCESS_KEY_ID != '' && secrets.AWS_SECRET_ACCESS_KEY != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
2024-01-31 08:33:45 -05:00
ephemeral-env-comment :
2023-04-14 11:23:00 -04:00
needs : config
if : needs.config.outputs.has-secrets
2021-02-24 13:50:52 -05:00
name : Evaluate ephemeral env comment trigger (/testenv)
runs-on : ubuntu-latest
2023-04-14 11:23:00 -04:00
permissions :
pull-requests : write
2021-02-24 13:50:52 -05:00
outputs :
slash-command : ${{ steps.eval-body.outputs.result }}
2021-04-08 14:05:59 -04:00
feature-flags : ${{ steps.eval-feature-flags.outputs.result }}
2021-02-24 13:50:52 -05:00
steps :
- name : Debug
run : |
echo "Comment on PR #${{ github.event.issue.number }} by ${{ github.event.issue.user.login }}, ${{ github.event.comment.author_association }}"
- name : Eval comment body for /testenv slash command
2024-02-01 10:09:10 -05:00
uses : actions/github-script@v7
2021-02-24 13:50:52 -05:00
id : eval-body
with :
result-encoding : string
script : |
const pattern = /^\/testenv (up|down)/
const result = pattern.exec(context.payload.comment.body)
return result === null ? 'noop' : result[1]
2021-04-08 14:05:59 -04:00
- name : Eval comment body for feature flags
2024-02-01 10:09:10 -05:00
uses : actions/github-script@v7
2021-04-08 14:05:59 -04:00
id : eval-feature-flags
with :
script : |
const pattern = /FEATURE_(\w+)=(\w+)/g;
let results = [];
[ ...context.payload.comment.body.matchAll(pattern)].forEach(match => {
const config = {
name : `SUPERSET_FEATURE_${match[1]}`,
value : match[2],
};
results.push(config);
});
return results;
2021-02-24 13:50:52 -05:00
- name : Limit to committers
if : >
steps.eval-body.outputs.result != 'noop' &&
github.event.comment.author_association != 'MEMBER' &&
github.event.comment.author_association != 'OWNER'
2024-02-01 10:09:10 -05:00
uses : actions/github-script@v7
2021-02-24 13:50:52 -05:00
with :
2023-04-14 11:23:00 -04:00
github-token : ${{github.token}}
2021-02-24 13:50:52 -05:00
script : |
const errMsg = '@${{ github.event.comment.user.login }} Ephemeral environment creation is currently limited to committers.'
2024-02-01 11:40:40 -05:00
github.rest.issues.createComment({
2021-02-24 13:50:52 -05:00
issue_number : ${{ github.event.issue.number }},
owner : context.repo.owner,
repo : context.repo.repo,
body : errMsg
})
core.setFailed(errMsg)
2024-01-31 07:06:06 -05:00
ephemeral-docker-build :
2024-01-31 08:33:45 -05:00
needs : ephemeral-env-comment
name : ephemeral-docker-build
2024-01-23 10:46:46 -05:00
runs-on : ubuntu-latest
steps :
2024-01-31 07:06:06 -05:00
- name : Get Info from comment
2024-02-01 10:09:10 -05:00
uses : actions/github-script@v7
2024-01-31 07:06:06 -05:00
id : get-pr-info
2024-01-23 10:46:46 -05:00
with :
script : |
2024-01-31 07:06:06 -05:00
const request = {
2024-01-23 10:46:46 -05:00
owner : context.repo.owner,
repo : context.repo.repo,
2024-01-31 07:06:06 -05:00
pull_number : ${{ github.event.issue.number }},
2024-01-23 10:46:46 -05:00
}
2024-01-31 07:06:06 -05:00
core.info(`Getting PR #${request.pull_number} from ${request.owner}/${request.repo}`)
2024-02-01 11:40:40 -05:00
const pr = await github.rest.pulls.get(request);
2024-01-31 07:06:06 -05:00
return pr.data;
2024-01-23 10:46:46 -05:00
2024-01-31 07:06:06 -05:00
- name : Debug
id : get-sha
run : |
echo "sha=${{ fromJSON(steps.get-pr-info.outputs.result).head.sha }}" >> $GITHUB_OUTPUT
2024-01-23 10:46:46 -05:00
2024-01-31 07:06:06 -05:00
- name : "Checkout ${{ github.ref }} ( ${{ github.sha }} : ${{steps.get-sha.outputs.sha}} )"
uses : actions/checkout@v4
with :
ref : ${{ steps.get-sha.outputs.sha }}
persist-credentials : false
2024-01-23 10:46:46 -05:00
2024-01-31 07:06:06 -05:00
- name : Set up QEMU
uses : docker/setup-qemu-action@v3
2024-01-23 10:46:46 -05:00
2024-01-31 07:06:06 -05:00
- name : Set up Docker Buildx
uses : docker/setup-buildx-action@v3
2024-01-23 10:46:46 -05:00
2024-01-31 07:06:06 -05:00
- name : Build ephemeral env image
run : |
docker buildx build --target ci \
--load \
-t ${{ steps.get-sha.outputs.sha }} \
-t "pr-${{ github.event.issue.number }}" \
--platform linux/amd64 \
--label "build_actor=${GITHUB_ACTOR}" \
.
2024-01-23 10:46:46 -05:00
- name : Configure AWS credentials
2024-02-01 05:19:44 -05:00
uses : aws-actions/configure-aws-credentials@v4
2024-01-23 10:46:46 -05:00
with :
aws-access-key-id : ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region : us-west-2
- name : Login to Amazon ECR
id : login-ecr
2024-02-01 05:18:00 -05:00
uses : aws-actions/amazon-ecr-login@v2
2024-01-23 10:46:46 -05:00
- name : Load, tag and push image to ECR
id : push-image
env :
ECR_REGISTRY : ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY : superset-ci
SHA : ${{ steps.get-sha.outputs.sha }}
2024-01-31 07:06:06 -05:00
IMAGE_TAG : pr-${{ github.event.issue.number }}
2024-01-23 10:46:46 -05:00
run : |
docker tag $SHA $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker tag $SHA $ECR_REGISTRY/$ECR_REPOSITORY:$SHA
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
2024-01-31 08:33:45 -05:00
ephemeral-env-up :
needs : [ ephemeral-env-comment, ephemeral-docker-build]
if : needs.ephemeral-env-comment.outputs.slash-command == 'up'
2021-02-24 13:50:52 -05:00
name : Spin up an ephemeral environment
runs-on : ubuntu-latest
2023-04-14 11:23:00 -04:00
permissions :
contents : read
pull-requests : write
2021-02-24 13:50:52 -05:00
steps :
2023-04-14 11:23:00 -04:00
- uses : actions/checkout@v3
2021-02-24 13:50:52 -05:00
with :
persist-credentials : false
- name : Configure AWS credentials
2024-02-01 05:19:44 -05:00
uses : aws-actions/configure-aws-credentials@v4
2021-02-24 13:50:52 -05:00
with :
aws-access-key-id : ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region : us-west-2
- name : Login to Amazon ECR
id : login-ecr
2024-02-01 05:18:00 -05:00
uses : aws-actions/amazon-ecr-login@v2
2021-02-24 13:50:52 -05:00
- name : Check target image exists in ECR
id : check-image
continue-on-error : true
run : |
aws ecr describe-images \
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
--repository-name superset-ci \
--image-ids imageTag=pr-${{ github.event.issue.number }}
- name : Fail on missing container image
if : steps.check-image.outcome == 'failure'
2024-02-01 10:09:10 -05:00
uses : actions/github-script@v7
2021-02-24 13:50:52 -05:00
with :
2023-04-14 11:23:00 -04:00
github-token : ${{github.token}}
2021-02-24 13:50:52 -05:00
script : |
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.'
2024-02-01 11:40:40 -05:00
github.rest.issues.createComment({
2021-02-24 13:50:52 -05:00
issue_number : ${{ github.event.issue.number }},
owner : context.repo.owner,
repo : context.repo.repo,
body : errMsg
})
core.setFailed(errMsg)
- name : Fill in the new image ID in the Amazon ECS task definition
id : task-def
uses : aws-actions/amazon-ecs-render-task-definition@v1
with :
task-definition : .github/workflows/ecs-task-definition.json
container-name : superset-ci
image : ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.issue.number }}
2021-04-08 14:05:59 -04:00
- name : Update env vars in the Amazon ECS task definition
run : |
2024-01-31 08:33:45 -05:00
cat <<< "$(jq '.containerDefinitions[0].environment += ${{ needs.ephemeral-env-comment.outputs.feature-flags }}' < ${{ steps.task-def.outputs.task-definition }})" > ${{ steps.task-def.outputs.task-definition }}
2021-04-08 14:05:59 -04:00
2021-02-24 13:50:52 -05:00
- name : Describe ECS service
id : describe-services
run : |
2024-01-31 13:40:07 -05:00
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.issue.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
2021-02-24 13:50:52 -05:00
- name : Create ECS service
if : steps.describe-services.outputs.active != 'true'
id : create-service
env :
ECR_SUBNETS : subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
ECR_SECURITY_GROUP : sg-092ff3a6ae0574d91
run : |
aws ecs create-service \
--cluster superset-ci \
--service-name pr-${{ github.event.issue.number }}-service \
--task-definition superset-ci \
--launch-type FARGATE \
--desired-count 1 \
--platform-version LATEST \
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
--tags key=pr,value=${{ github.event.issue.number }} key=github_user,value=${{ github.actor }}
- name : Deploy Amazon ECS task definition
id : deploy-task
uses : aws-actions/amazon-ecs-deploy-task-definition@v1
with :
task-definition : ${{ steps.task-def.outputs.task-definition }}
service : pr-${{ github.event.issue.number }}-service
cluster : superset-ci
wait-for-service-stability : true
wait-for-minutes : 10
- name : List tasks
id : list-tasks
run : |
2024-01-31 13:40:07 -05:00
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.issue.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
2021-02-24 13:50:52 -05:00
- name : Get network interface
id : get-eni
run : |
2024-01-31 13:40:07 -05:00
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
2021-02-24 13:50:52 -05:00
- name : Get public IP
id : get-ip
run : |
2024-01-31 13:40:07 -05:00
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
2021-02-24 13:50:52 -05:00
- name : Comment (success)
if : ${{ success() }}
2024-02-01 10:09:10 -05:00
uses : actions/github-script@v7
2021-02-24 13:50:52 -05:00
with :
2023-04-14 11:23:00 -04:00
github-token : ${{github.token}}
2021-02-24 13:50:52 -05:00
script : |
2024-02-01 12:46:31 -05:00
github.rest.issues.createComment({
2021-02-24 13:50:52 -05:00
issue_number : ${{ github.event.issue.number }},
owner : context.repo.owner,
repo : context.repo.repo,
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.'
})
- name : Comment (failure)
if : ${{ failure() }}
2024-02-01 10:09:10 -05:00
uses : actions/github-script@v7
2021-02-24 13:50:52 -05:00
with :
2023-04-14 11:23:00 -04:00
github-token : ${{github.token}}
2021-02-24 13:50:52 -05:00
script : |
github.issues.createComment({
issue_number : ${{ github.event.issue.number }},
owner : context.repo.owner,
repo : context.repo.repo,
body : '@${{ github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'
})