Skip to content

Commit 1633c72

Browse files
Add support for fixing style as a task in another process
1 parent 70a6c96 commit 1633c72

9 files changed

Lines changed: 170 additions & 60 deletions

File tree

.env-dummy

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Go to smee.io to generate a URL here
22
SMEE_URL=https://smee.io/CHANGEME
33

4+
# No need to change this for testing
5+
REDIS_HOST=rq-server
6+
7+
# Optionally customize port redis listens on
8+
REDIS_PORT=6379
9+
410
# You don't need to change this unless you change the docker-compose volumes
511
GITHUB_PRIVATE_KEY=/app/spackbot/spack-bot-develop.private-key.pem
612

.github/workflows/build-deploy.yaml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,24 @@ on:
1212
jobs:
1313
deploy-test-containers:
1414
runs-on: ubuntu-latest
15-
name: Build Spackbot Container
15+
strategy:
16+
fail-fast: false
17+
# matrix: [tag, path to Dockerfile, label]
18+
matrix:
19+
dockerfile: [[spack-bot, ./Dockerfile, Spackbot],
20+
[spackbot-workers, ./workers/Dockerfile, "Spackbot Workers"]]
21+
name: Build ${{matrix.dockerfile[2]}} Container
1622
steps:
1723
- name: Checkout
1824
uses: actions/checkout@v2
1925

2026
- name: Build and Run Test Container
2127
run: |
22-
docker build -t ghcr.io/spack/spack-bot:latest .
23-
docker tag ghcr.io/spack/spack-bot:latest ghcr.io/spack/spack-bot:${GITHUB_SHA::8}
24-
28+
docker build -f ${{matrix.dockerfile[1]}} -t ghcr.io/spack/${{matrix.dockerfile[0]}}:latest .
29+
docker tag ghcr.io/spack/${{matrix.dockerfile[0]}}:latest ghcr.io/spack/${{matrix.dockerfile[0]}}:${GITHUB_SHA::8}
2530
- name: Login and Deploy Test Container
2631
if: (github.event_name != 'pull_request')
2732
run: |
2833
docker images
2934
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ secrets.GHCR_USERNAME }} --password-stdin
30-
docker push --all-tags ghcr.io/spack/spack-bot
35+
docker push --all-tags ghcr.io/spack/${{matrix.dockerfile[0]}}

docker-compose.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,25 @@ services:
88
context: .
99
dockerfile: smee/Dockerfile
1010

11+
rq-worker:
12+
build:
13+
context: .
14+
dockerfile: workers/Dockerfile
15+
env_file:
16+
- ./.env
17+
deploy:
18+
replicas: 1
19+
20+
rq-server:
21+
env_file:
22+
- ./.env
23+
image: redis:alpine
24+
expose:
25+
- ${REDIS_PORT}
26+
volumes:
27+
- redis-data:/data
28+
- redis-conf:/usr/local/etc/redis/redis.conf
29+
1130
spackbot:
1231
build:
1332
context: .
@@ -29,3 +48,7 @@ services:
2948
- ./.env
3049
links:
3150
- smee
51+
52+
volumes:
53+
redis-data:
54+
redis-conf:

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
aiohttp
22
gidgethub
33
python_dotenv
4+
rq
45
sh
56

67
# Add these so we don't wait for install

spackbot/handlers/style.py

Lines changed: 16 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55

66
import spackbot.comments as comments
77
import spackbot.helpers as helpers
8-
from sh.contrib import git
98
import logging
10-
import os
11-
import sh
9+
10+
from spackbot.workers import fix_style_task, work_queue
11+
12+
# If we don't provide a timeout, the default in RQ is 180 seconds
13+
WORKER_JOB_TIMEOUT = 6 * 60 * 60
1214

1315
logger = logging.getLogger(__name__)
1416

@@ -31,13 +33,6 @@ async def style_comment(event, gh):
3133
await gh.post(comments_url, {}, data={"body": comments.style_message})
3234

3335

34-
def is_up_to_date(output):
35-
"""
36-
A commit can fail if there are no changes!
37-
"""
38-
return "branch is up to date" in output
39-
40-
4136
async def fix_style(event, gh):
4237
"""
4338
Respond to a request to fix style.
@@ -58,7 +53,7 @@ async def fix_style(event, gh):
5853
return f"Sorry {sender}, I cannot do that for you. Only users with write can make this request!"
5954

6055
# Tell the user the style fix is going to take a minute or two
61-
message = "Let me see if I can fix that for you! This might take a moment..."
56+
message = "Let me see if I can fix that for you!"
6257
await gh.post(event.data["issue"]["comments_url"], {}, data={"body": message})
6358

6459
# Get the username of the original committer
@@ -72,49 +67,15 @@ async def fix_style(event, gh):
7267
full_name = pr["head"]["repo"]["full_name"]
7368
fork_url = f"git@github.com:{full_name}.git"
7469

75-
# At this point, we can clone the repository and make the change
76-
with helpers.temp_dir() as cwd:
77-
78-
# Clone a fresh spack develop to use for spack style
79-
git("clone", helpers.spack_upstream, "spack-develop")
80-
81-
spack = sh.Command(f"{cwd}/spack-develop/bin/spack")
82-
83-
# clone the develop repository to another folder for our PR
84-
git("clone", "spack-develop", "spack")
85-
86-
os.chdir("spack")
87-
git("config", "user.name", user)
88-
git("config", "user.email", email)
89-
90-
# This will authenticate the push with the added ssh credentials
91-
git("remote", "add", "upstream", helpers.spack_upstream)
92-
git("remote", "set-url", "origin", fork_url)
93-
94-
# we're on upstream/develop. Fetch and check out just the PR branch
95-
git("fetch", "origin", f"{branch}:{branch}")
96-
git("checkout", branch)
97-
98-
# Save the message for the user
99-
res, err = helpers.run_command(spack, ["--color", "never", "style", "--fix"])
100-
message = comments.get_style_message(res)
101-
102-
# Commit (allow for no changes)
103-
res, err = helpers.run_command(
104-
git,
105-
["commit", "-a", "-m", f"[spackbot] updating style on behalf of {user}"],
106-
)
107-
108-
# Continue differently if the branch is up to date or not
109-
if is_up_to_date(res):
110-
message += "\nI wasn't able to make any further changes, but please see the message above for remaining issues you can fix locally!"
111-
return message
112-
message += "\nI've updated the branch with isort fixes."
113-
114-
# Finally, try to push, update the message if permission not allowed
115-
try:
116-
git("push", "origin", branch)
117-
except Exception:
118-
message += "\n\nBut it looks like I'm not able to push to your branch. 😭️ Did you check maintainer can edit when you opened the PR?"
70+
task_q = work_queue.get_queue()
71+
fix_style_job = task_q.enqueue(
72+
fix_style_task,
73+
user,
74+
email,
75+
fork_url,
76+
branch,
77+
job_timeout=WORKER_JOB_TIMEOUT,
78+
)
79+
logger.info(f"Fix style job queued: {fix_style_job.id}")
11980

12081
return message

spackbot/workers.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import logging
2+
import os
3+
from sh.contrib import git
4+
import sh
5+
6+
from redis import Redis
7+
from rq import Queue
8+
9+
import spackbot.comments as comments
10+
import spackbot.helpers as helpers
11+
12+
logger = logging.getLogger(__name__)
13+
14+
REDIS_HOST = os.environ.get("REDIS_HOST", "localhost")
15+
REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
16+
17+
18+
class WorkQueue:
19+
def __init__(self):
20+
logger.info(f"WorkQueue creating redis connection ({REDIS_HOST}, {REDIS_PORT})")
21+
self.redis_conn = Redis(host=REDIS_HOST, port=REDIS_PORT)
22+
self.task_q = Queue(name="tasks", connection=self.redis_conn)
23+
24+
def get_queue(self):
25+
return self.task_q
26+
27+
28+
work_queue = WorkQueue()
29+
30+
31+
def is_up_to_date(output):
32+
"""
33+
A commit can fail if there are no changes!
34+
"""
35+
return "branch is up to date" in output
36+
37+
38+
async def fix_style_task(user, email, fork_url, branch):
39+
# In the worker container, the code in __main__.py will not have
40+
# run to set the logging level.
41+
logging.basicConfig(level=logging.INFO)
42+
style_logger = logging.getLogger("fix_style_task")
43+
44+
# At this point, we can clone the repository and make the change
45+
with helpers.temp_dir() as cwd:
46+
47+
# Clone a fresh spack develop to use for spack style
48+
git("clone", helpers.spack_upstream, "spack-develop")
49+
50+
spack = sh.Command(f"{cwd}/spack-develop/bin/spack")
51+
52+
# clone the develop repository to another folder for our PR
53+
git("clone", "spack-develop", "spack")
54+
55+
os.chdir("spack")
56+
git("config", "user.name", user)
57+
git("config", "user.email", email)
58+
59+
# This will authenticate the push with the added ssh credentials
60+
git("remote", "add", "upstream", helpers.spack_upstream)
61+
git("remote", "set-url", "origin", fork_url)
62+
63+
# we're on upstream/develop. Fetch and check out just the PR branch
64+
git("fetch", "origin", f"{branch}:{branch}")
65+
git("checkout", branch)
66+
67+
# Save the message for the user
68+
res, err = helpers.run_command(spack, ["--color", "never", "style", "--fix"])
69+
message = f"fix_style_task, user = {user}, email = {email}, fork = {fork_url}, branch = {branch}\n"
70+
message += comments.get_style_message(res)
71+
72+
# Commit (allow for no changes)
73+
res, err = helpers.run_command(
74+
git,
75+
["commit", "-a", "-m", f"[spackbot] updating style on behalf of {user}"],
76+
)
77+
78+
# Continue differently if the branch is up to date or not
79+
if is_up_to_date(res):
80+
message += "\nunable to make any further changes"
81+
style_logger.log(message)
82+
return
83+
84+
message += "\nupdated the branch with isort fixes."
85+
86+
# Finally, try to push, update the message if permission not allowed
87+
try:
88+
git("push", "origin", branch)
89+
except Exception:
90+
message += "\n\nunable to push to branch"
91+
92+
style_logger.log(message)

workers/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM ghcr.io/spack/ubuntu-bionic:latest
2+
3+
COPY workers/requirements.txt /source/requirements.txt
4+
COPY workers/entrypoint.sh /source/entrypoint.sh
5+
COPY spackbot /source/spackbot
6+
7+
RUN pip3 install --upgrade pip setuptools wheel && \
8+
pip3 install -r /source/requirements.txt
9+
10+
WORKDIR /source
11+
ENTRYPOINT ["/bin/bash", "/source/entrypoint.sh"]

workers/entrypoint.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
# Make sure spack can be found by worker jobs
4+
. $SPACK_ROOT/share/spack/setup-env.sh
5+
6+
# Define REDIS_HOST and REDIS_PORT in .env file or k8s deployment. Workers
7+
# always take jobs from the "copy" queue first and then the "index" queue
8+
# when passed in this order.
9+
rq worker -u redis://${REDIS_HOST}:${REDIS_PORT} --with-scheduler tasks

workers/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
aiohttp
2+
rq

0 commit comments

Comments
 (0)