Skip to content

Commit 59db9d0

Browse files
authored
Merge pull request #2208 from kattni/actions-status-light
Add code and README for Status Light guide.
2 parents 5d917a3 + 68bf6c2 commit 59db9d0

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# GitHub Actions Status Tower Light
2+
3+
This project allows you to see the status of your current Actions run on a repo of your choice,
4+
lit up on a tower light plugged into your computer via USB. The program is run directly from your
5+
computer.
6+
7+
This README includes the basic requirements to run the project. Check out
8+
[the guide](https://learn.adafruit.com/github-actions-status-tower-light) for details.
9+
10+
### Four requirements to run this example:
11+
#### Hardware:
12+
* [Tri-Color USB Controller Tower Light with Buzzer](https://www.adafruit.com/product/5125)
13+
#### Software:
14+
* Python
15+
#### Libraries to `pip install`:
16+
* `pyserial`
17+
* `requests`
18+
#### Create GitHub API token:
19+
* In your GitHub account, click through Settings > Developer Settings > Personal Access Tokens,
20+
and generate a new token with no scopes.
21+
* Create an environment variable on your computer and make it available for your code to use.
22+
23+
To begin, plug the tower light into a USB port on your computer.
24+
25+
This project is written in Python. To use, prepare the requirements above, copy the `.py` file t
26+
your computer, and run the file as follows, updating `filename.py` to the name you chose for the
27+
file:
28+
29+
`python filename.py`
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# SPDX-FileCopyrightText: 2022 Tim C for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
"""
4+
GitHub Actions Status Tower Light
5+
"""
6+
import json
7+
import time
8+
import os
9+
import serial
10+
import requests
11+
12+
# Customisations for this program
13+
# Update with the URL from any repo running Actions to get the status. Defaults to CircuitPython.
14+
REPO_WORKFLOW_URL = "https://api.github.com/repos/adafruit/circuitpython/actions/workflows/build.yml/runs" # pylint: disable=line-too-long
15+
# The rate at which the program will query GitHub for an updated status. You can increase or
16+
# decrease the delay time to fit the duration and frequency of Actions runs on your repo.
17+
# Defaults to 3 minutes.
18+
POLL_DELAY = 60 * 3 # 3 minutes
19+
# The length of time in seconds the LED remains on once the Actions run has completed.
20+
# Defaults to 30 seconds.
21+
COMPLETION_LIGHT_TIME = 30 # seconds
22+
# The length of time in seconds the buzzer beeps once the actions run has completed.
23+
# Set this to 0 to disable the buzzer. Defaults to 1 second.
24+
COMPLETION_BUZZER_TIME = 1 # seconds
25+
# Determines whether the code sends commands to the tower light. Set it to False to disable the
26+
# tower light code and run this example without requiring the tower light. Defaults to True.
27+
ENABLE_USB_LIGHT_MESSAGES = True
28+
29+
# Serial port. Update the serial port to match the port of the tower light on your computer.
30+
# Windows will be a COM** port. If you are on Windows, comment out the Mac/Linux line, and
31+
# uncomment the line immediately below.
32+
# serial_port = "COM57"
33+
# Mac/Linux will be a /dev/** path to the serial port. If you're having trouble finding it,
34+
# check the contents of the /dev/ directory with the tower light unplugged and plugged in.
35+
serial_port = "/dev/tty.usbserial-144430"
36+
37+
# USB Tower Light constants
38+
RED_ON = 0x11
39+
RED_OFF = 0x21
40+
RED_BLINK = 0x41
41+
42+
YELLOW_ON = 0x12
43+
YELLOW_OFF = 0x22
44+
YELLOW_BLINK = 0x42
45+
46+
GREEN_ON = 0x14
47+
GREEN_OFF = 0x24
48+
GREEN_BLINK = 0x44
49+
50+
BUZZER_ON = 0x18
51+
BUZZER_OFF = 0x28
52+
BUZZER_BLINK = 0x48
53+
54+
# Baud rate for serial communication
55+
baud_rate = 9600
56+
57+
58+
def send_command(serialport, cmd):
59+
serialport.write(bytes([cmd]))
60+
61+
62+
def reset_state():
63+
# Clean up any old state
64+
send_command(mSerial, BUZZER_OFF)
65+
send_command(mSerial, RED_OFF)
66+
send_command(mSerial, YELLOW_OFF)
67+
send_command(mSerial, GREEN_OFF)
68+
69+
70+
def buzzer_on_completion():
71+
if COMPLETION_BUZZER_TIME > 0:
72+
send_command(mSerial, BUZZER_ON)
73+
time.sleep(COMPLETION_BUZZER_TIME)
74+
send_command(mSerial, BUZZER_OFF)
75+
76+
77+
already_shown_ids = []
78+
79+
headers = {'Accept': "application/vnd.github.v3+json",
80+
'Authorization': f"token {os.getenv('GITHUB_API_TOKEN')}"}
81+
82+
83+
mSerial = None
84+
if ENABLE_USB_LIGHT_MESSAGES:
85+
print("Opening serial port.")
86+
mSerial = serial.Serial(serial_port, baud_rate)
87+
88+
print("Starting Github Actions Status Watcher")
89+
print("Press Ctrl-C to Exit")
90+
while True:
91+
print("Fetching workflow run status.")
92+
response = requests.get(f"{REPO_WORKFLOW_URL}?per_page=1", headers=headers)
93+
response_json = response.json()
94+
with open("action_status_result.json", "w") as f:
95+
f.write(json.dumps(response_json))
96+
97+
workflow_run_id = response_json['workflow_runs'][0]['id']
98+
if workflow_run_id not in already_shown_ids:
99+
status = response_json['workflow_runs'][0]['status']
100+
conclusion = response_json['workflow_runs'][0]['conclusion']
101+
print(f"Status - Conclusion: {status} - {conclusion}")
102+
103+
if status == "queued":
104+
print("Actions run status: Queued.")
105+
if ENABLE_USB_LIGHT_MESSAGES:
106+
print("Sending serial command 'YELLOW_BLINK'.")
107+
send_command(mSerial, YELLOW_BLINK)
108+
109+
if status == "in_progress":
110+
print("Actions run status: In progress.")
111+
if ENABLE_USB_LIGHT_MESSAGES:
112+
print("Sending serial command 'YELLOW_ON'.")
113+
send_command(mSerial, YELLOW_ON)
114+
115+
if status == "completed":
116+
print(f"Adding {workflow_run_id} to shown workflow IDs.")
117+
already_shown_ids.append(workflow_run_id)
118+
119+
if conclusion == "success":
120+
print("Actions run status: Completed - successful.")
121+
if ENABLE_USB_LIGHT_MESSAGES:
122+
send_command(mSerial, YELLOW_OFF)
123+
print("Sending serial command 'GREEN_ON'.")
124+
send_command(mSerial, GREEN_ON)
125+
buzzer_on_completion()
126+
time.sleep(COMPLETION_LIGHT_TIME - COMPLETION_BUZZER_TIME)
127+
if ENABLE_USB_LIGHT_MESSAGES:
128+
print("Sending serial command 'GREEN_OFF'.")
129+
send_command(mSerial, GREEN_OFF)
130+
131+
if conclusion == "failure":
132+
print("Actions run status: Completed - failed.")
133+
if ENABLE_USB_LIGHT_MESSAGES:
134+
send_command(mSerial, YELLOW_OFF)
135+
print("Sending serial command 'RED_ON'.")
136+
send_command(mSerial, RED_ON)
137+
buzzer_on_completion()
138+
time.sleep(COMPLETION_LIGHT_TIME - COMPLETION_BUZZER_TIME)
139+
if ENABLE_USB_LIGHT_MESSAGES:
140+
print("Sending serial command 'RED_OFF'.")
141+
send_command(mSerial, RED_OFF)
142+
else:
143+
print("Already followed the current run.")
144+
time.sleep(POLL_DELAY)

0 commit comments

Comments
 (0)