Skip to content

Commit 9bc2519

Browse files
committed
[gha] comment ops + recreate_vm
1 parent 372b59b commit 9bc2519

File tree

5 files changed

+144
-29
lines changed

5 files changed

+144
-29
lines changed

Diff for: .github/actions/preview-create/entrypoint.sh

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ gcloud auth activate-service-account --key-file "${PREVIEW_ENV_DEV_SA_KEY_PATH}"
1616
leeway run dev/preview/previewctl:download
1717
previewctl get-credentials --gcp-service-account "${PREVIEW_ENV_DEV_SA_KEY_PATH}"
1818

19+
replace="module.preview_gce[0].google_compute_instance.default"
20+
if [[ "${INPUT_INFRASTRUCTURE_PROVIDER}" = "harvester " ]]; then
21+
replace="module.preview_harvester[0].harvester_virtualmachine.harvester"
22+
fi
23+
24+
if [[ "${INPUT_RECREATE_VM:-x}" == "true" ]]; then
25+
export TF_CLI_ARGS_plan="-replace=${replace}"
26+
fi
27+
1928
TF_VAR_preview_name="$(previewctl get-name --branch "${INPUT_NAME}")"
2029
export TF_VAR_preview_name
2130
export TF_VAR_infra_provider="${INPUT_INFRASTRUCTURE_PROVIDER}"

Diff for: .github/actions/preview-create/metadata.yml

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ inputs:
1717
previewctl_hash:
1818
description: "The Leeway hash of the dev/preview/previewctl:docker package to be used when downloading previewclt"
1919
required: false
20+
recreate_vm:
21+
description: "Whether to recreate the VM"
22+
required: false
23+
default: "false"
2024
runs:
2125
using: "docker"
2226
image: "Dockerfile"

Diff for: .github/workflows/build.yml

+30-18
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
name: Build
22
on:
33
pull_request:
4-
types: [ opened, synchronize, edited ]
4+
types: [ opened, edited ]
55
push:
6-
branches: [ main ]
76
workflow_dispatch:
7+
inputs:
8+
recreate_vm:
9+
required: true
10+
type: string
11+
description: "Whether to recreate the VM"
12+
default: "false"
813

914
jobs:
1015
configuration:
@@ -16,42 +21,48 @@ jobs:
1621
outputs:
1722
is_main_branch: ${{ (github.head_ref || github.ref) == 'refs/heads/main' }}
1823
version: ${{ steps.branches.outputs.sanitized-branch-name }}-gha.${{github.run_number}}
19-
with_github_actions: ${{ contains(github.event.pull_request.body, '[x] /werft with-github-actions') }}
20-
preview_enable: ${{ contains(github.event.pull_request.body, '[x] /werft with-preview') }}
21-
preview_infra_provider: ${{ contains(github.event.pull_request.body, '[X] /werft with-gce-vm') && 'gce' || 'harvester' }}
22-
build_no_cache: ${{ contains(github.event.pull_request.body, '[x] leeway-no-cache') }}
23-
build_no_test: ${{ contains(github.event.pull_request.body, '[x] /werft no-test') }}
24+
with_github_actions: ${{ contains( steps.pr-details.outputs.pr_body, '[x] /werft with-github-actions') }}
25+
preview_enable: ${{ contains( steps.pr-details.outputs.pr_body, '[x] /werft with-preview') }}
26+
preview_infra_provider: ${{ contains( steps.pr-details.outputs.pr_body, '[X] /werft with-gce-vm') && 'gce' || 'harvester' }}
27+
build_no_cache: ${{ contains( steps.pr-details.outputs.pr_body, '[x] leeway-no-cache') }}
28+
build_no_test: ${{ contains( steps.pr-details.outputs.pr_body, '[x] /werft no-test') }}
2429
build_leeway_target: ${{ steps.output.outputs.build_leeway_target }}
25-
with_large_vm: ${{ contains(github.event.pull_request.body, '[X] /werft with-large-vm') }}
26-
publish_to_npm: ${{ contains(github.event.pull_request.body, '[X] /werft publish-to-npm') }}
27-
publish_to_jbmp: ${{ contains(github.event.pull_request.body, '[X] /werft publish-to-jb-marketplace') }}
28-
with_ws_manager_mk2: ${{ contains(github.event.pull_request.body, '[X] with-ws-manager-mk2') }}
29-
with_dedicated_emulation: ${{ contains(github.event.pull_request.body, '[X] with-dedicated-emulation') }}
30-
with_ee_license: ${{ contains(github.event.pull_request.body, '[X] with-ee-license') }}
31-
with_slow_database: ${{ contains(github.event.pull_request.body, '[X] with-slow-database') }}
32-
analytics: ${{ contains(github.event.pull_request.body, '[X] analytics') }}
30+
with_large_vm: ${{ contains( steps.pr-details.outputs.pr_body, '[X] /werft with-large-vm') }}
31+
publish_to_npm: ${{ contains( steps.pr-details.outputs.pr_body, '[X] /werft publish-to-npm') }}
32+
publish_to_jbmp: ${{ contains( steps.pr-details.outputs.pr_body, '[X] /werft publish-to-jb-marketplace') }}
33+
with_ws_manager_mk2: ${{ contains( steps.pr-details.outputs.pr_body, '[X] with-ws-manager-mk2') }}
34+
with_dedicated_emulation: ${{ contains( steps.pr-details.outputs.pr_body, '[X] with-dedicated-emulation') }}
35+
with_ee_license: ${{ contains( steps.pr-details.outputs.pr_body, '[X] with-ee-license') }}
36+
with_slow_database: ${{ contains( steps.pr-details.outputs.pr_body, '[X] with-slow-database') }}
37+
analytics: ${{ contains( steps.pr-details.outputs.pr_body, '[X] analytics') }}
3338
workspace_feature_flags: ${{ steps.output.outputs.workspace_feature_flags }}
3439
pr_no_diff_skip: ${{ steps.pr-diff.outputs.pr_no_diff_skip }}
3540
steps:
3641
- name: "Determine Branch"
3742
id: branches
3843
uses: transferwise/sanitize-branch-name@v1
44+
# Since we trigger this worklow on other event types, besides pull_request
45+
# We use this action to help us get the pr body, as it's not included in push/workflow_dispatch events
46+
- uses: 8BitJonny/[email protected]
47+
id: pr-details
48+
with:
49+
sha: ${{ github.event.pull_request.head.sha }}
3950
# If the PR got edited, but no checkbox changes occurred, we don't want to run the whole build
4051
# Therefore we set a flag and use it to skip the next jobs
4152
- name: "Check PR diff"
4253
id: pr-diff
54+
if: (github.event_name == 'pull_request' && github.event.action == 'edited')
4355
env:
44-
PR_DESC: '${{ github.event.pull_request.body }}'
56+
PR_DESC: '${{ steps.pr-details.outputs.pr_body }}'
4557
OLD_BODY: '${{ github.event.changes.body.from }}'
46-
if: (github.event_name == 'pull_request' && github.event.action == 'edited')
4758
run: |
4859
if ! diff <(echo "$OLD_BODY") <(echo "$PR_DESC") | grep -e '\[x\]' -e '\[X\]'; then
4960
echo "pr_no_diff_skip=true" >> $GITHUB_OUTPUT
5061
fi
5162
- name: "Set outputs"
5263
id: output
5364
env:
54-
PR_DESC: '${{ github.event.pull_request.body }}'
65+
PR_DESC: '${{ steps.pr-details.outputs.pr_body }}'
5566
shell: bash
5667
run: |
5768
{
@@ -116,6 +127,7 @@ jobs:
116127
infrastructure_provider: ${{ needs.configuration.outputs.preview_infra_provider }}
117128
previewctl_hash: ${{ needs.build-previewctl.outputs.previewctl_hash }}
118129
large_vm: ${{ needs.configuration.outputs.with_large_vm }}
130+
recreate_vm: ${{ inputs.recreate_vm }}
119131

120132
build-gitpod:
121133
name: Build Gitpod

Diff for: .github/workflows/comment-action.yaml

-11
This file was deleted.

Diff for: .github/workflows/comment-ops.yaml

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: comment-ops
2+
3+
on:
4+
issue_comment:
5+
types: [ created ]
6+
7+
# This action *ALWAYS* runs on main.
8+
# Any changes done to it, will not have an effect, until said changes have landed on the main branch
9+
# This has a side effect that always `head_ref == main` and `head_sha == main_head_sha`
10+
# Therefore we can't find out easily which PR the comment that triggered the action belongs to
11+
12+
jobs:
13+
configure:
14+
# We *MUST* always check the author_association, which tells us if the person is an owner of the repo, or member of the org (i.e. has permissions)
15+
# Otherwise they can execute arbitrary code if the triggered workflow (i.e. the build) is modified, as it's being run by the github-actions bot, and it always has permissions
16+
if: |
17+
(github.event.issue.author_association == 'OWNER' || github.event.issue.author_association == 'MEMBER') &&
18+
(github.event.issue.pull_request && contains(github.event.comment.body, '/gh run'))
19+
runs-on: [ self-hosted ]
20+
# Technically we don't need these here, as we don't reuse them between jobs, but it's good to have them in a single place
21+
outputs:
22+
branch: ${{ steps.comment-branch.outputs.head_ref }}
23+
run_url: ${{ steps.run_outputs.outputs.run_url }}
24+
run_id: ${{ steps.run_outputs.outputs.run_id }}
25+
recreate_vm: ${{ steps.configure.outputs.recreate-vm }}
26+
steps:
27+
# In order for us to find out from which PR the comment originates, we use the `xt0rted/pull-request-comment-branch@v1` action
28+
- uses: xt0rted/pull-request-comment-branch@v1
29+
id: comment-branch
30+
# Set outputs we can reuse in the steps
31+
- name: Set outputs
32+
id: outputs
33+
run: |
34+
{
35+
echo "recreate-vm=${{ contains(github.event.comment.body, 'recreate-vm') }}"
36+
} >> $GITHUB_OUTPUT
37+
# Trigger the build workflow with the input we got from the comment
38+
# In the triggered job (build), we'll combine the information from the PR description, with the input we pass here
39+
# Also we use workflow_dispatch, instead of a workflow_call ( uses: ./build.yaml with: ...)
40+
# Because with the latter it's not possible to trigger a dynamic one (i.e. based on a branch) - the name has to be hardcoded
41+
- name: Trigger Workflow
42+
uses: actions/github-script@v6
43+
with:
44+
script: |
45+
await github.rest.actions.createWorkflowDispatch({
46+
owner: context.repo.owner,
47+
repo: context.repo.repo,
48+
workflow_id: 'build.yaml',
49+
ref: '${{ steps.comment-branch.outputs.head_ref }}',
50+
inputs: {
51+
"recreate_vm": '${{ steps.configure.outputs.recreate-vm }}'
52+
}
53+
})
54+
# Getting the ID of the workflow we triggered above is a bit tricky, as it's async :(
55+
# There is a trick we can do - add an input with a unique id, get the list of worklow runs, and check for that input in them until we can find it
56+
# But it's an overkill for now
57+
# Instead, we wait a little, and grab the last job that was triggered by a `workflow_dispatch` event, AND is not completed, and we hope for the best 🤞
58+
- name: Get run URL
59+
id: run_outputs
60+
env:
61+
GH_TOKEN: ${{ github.token }}
62+
run: |
63+
sleep 5
64+
url=$(gh run list --repo '${{ github.repository }}' --workflow build.yaml -b ${{ steps.comment-branch.outputs.head_ref }} --json event,url,status -q '[.[] | select(.event=="workflow_dispatch") | select(.status!="completed").url][0]')
65+
{
66+
echo "run_url=${url}"
67+
echo "run_id=${url##*/}"
68+
} >> $GITHUB_OUTPUT
69+
# Comment with a link to the job that got triggered
70+
- uses: actions/github-script@v6
71+
with:
72+
github-token: ${{ github.token }}
73+
script: |
74+
github.rest.issues.createComment({
75+
issue_number: ${{ github.event.issue.number }},
76+
owner: context.repo.owner,
77+
repo: context.repo.repo,
78+
body: `#### Comment triggered a workflow run
79+
80+
Started workflow run: [${{ needs.configure.outputs.run_id }}](${{ needs.configure.outputs.run_url }})
81+
* \`recreate_vm: ${{ steps.configure.outputs.recreate-vm }}\``
82+
})
83+
84+
# Comment if this job failed, so there's some feedback
85+
comment-fail:
86+
if: failure()
87+
runs-on: [ self-hosted ]
88+
steps:
89+
- uses: actions/github-script@v6
90+
with:
91+
github-token: ${{ github.token }}
92+
script: |
93+
let commentBody = '${{ github.event.comment.body }}'
94+
commentBody += "\n\n Chat ops job failed. See [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details"
95+
github.rest.issues.updateComment({
96+
issue_number: ${{ github.event.issue.number }},
97+
owner: context.repo.owner,
98+
repo: context.repo.repo,
99+
comment_id: ${{ github.event.comment.id }},
100+
body: commentBody
101+
})

0 commit comments

Comments
 (0)