Skip to content

Commit 3e81e29

Browse files
authored
Merge pull request #73 from ActivityWatch/dev/github-ci
ci: switched to GitHub Actions for CI
2 parents 0f77bf2 + 2f44d8d commit 3e81e29

17 files changed

+367
-160
lines changed

.github/workflows/build.yml

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
build:
11+
name: Test on ${{ matrix.os }}
12+
runs-on: ${{ matrix.os }}
13+
env:
14+
RELEASE: false
15+
SKIP_WEBUI: true
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
os: [ubuntu-18.04, windows-latest, macOS-latest]
20+
python_version: [3.6]
21+
steps:
22+
- uses: actions/checkout@v2
23+
with:
24+
submodules: 'recursive'
25+
- name: Set up Python
26+
uses: actions/setup-python@v1
27+
with:
28+
python-version: ${{ matrix.python_version }}
29+
- name: Create virtualenv
30+
shell: bash
31+
run: |
32+
pip install virtualenv
33+
python -m virtualenv venv
34+
- name: Install dependencies
35+
shell: bash
36+
run: |
37+
pip install poetry
38+
source venv/bin/activate || source venv/Scripts/activate
39+
make build
40+
- name: Run tests
41+
shell: bash
42+
run: |
43+
source venv/bin/activate || source venv/Scripts/activate
44+
make test
45+
make typecheck
46+
bash <(curl -s https://codecov.io/bash)
47+
- name: Package
48+
shell: bash
49+
run: |
50+
source venv/bin/activate || source venv/Scripts/activate
51+
pip install pyinstaller
52+
make package

.github/workflows/lint.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
lint:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
- uses: actions/setup-python@v2
15+
- uses: psf/black@stable

.travis.yml

-23
This file was deleted.

aw_server/__about__.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,16 @@ def detect_version_ci() -> Optional[str]:
2121

2222
def detect_version_git() -> Optional[str]:
2323
try:
24-
return basever + ".dev+" + str(subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).strip(), "utf8")
24+
return (
25+
basever
26+
+ ".dev+"
27+
+ str(
28+
subprocess.check_output(
29+
["git", "rev-parse", "--short", "HEAD"]
30+
).strip(),
31+
"utf8",
32+
)
33+
)
2534
except Exception as e:
2635
# Unable to get current commit with git
2736
return None
@@ -43,7 +52,7 @@ def detect_version():
4352
return basever + ".dev+unknown"
4453

4554

46-
__version__ = 'v0.8.dev+c6433ea'
55+
__version__ = "v0.8.dev+c6433ea"
4756

4857

4958
def assign_static_version():

aw_server/api.py

+77-29
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
def get_device_id() -> str:
2727
path = Path(get_data_dir("aw-server")) / "device_id"
2828
if path.exists():
29-
with open(path, 'r') as f:
29+
with open(path, "r") as f:
3030
return f.read()
3131
else:
3232
uuid = str(uuid4())
33-
with open(path, 'w') as f:
33+
with open(path, "w") as f:
3434
f.write(uuid)
3535
return uuid
3636

@@ -39,8 +39,11 @@ def check_bucket_exists(f):
3939
@functools.wraps(f)
4040
def g(self, bucket_id, *args, **kwargs):
4141
if bucket_id not in self.db.buckets():
42-
raise NotFound("NoSuchBucket", "There's no bucket named {}".format(bucket_id))
42+
raise NotFound(
43+
"NoSuchBucket", "There's no bucket named {}".format(bucket_id)
44+
)
4345
return f(self, bucket_id, *args, **kwargs)
46+
4447
return g
4548

4649

@@ -53,10 +56,10 @@ def __init__(self, db, testing) -> None:
5356
def get_info(self) -> Dict[str, Dict]:
5457
"""Get server info"""
5558
payload = {
56-
'hostname': gethostname(),
57-
'version': __version__,
58-
'testing': self.testing,
59-
'device_id': get_device_id(),
59+
"hostname": gethostname(),
60+
"version": __version__,
61+
"testing": self.testing,
62+
"device_id": get_device_id(),
6063
}
6164
return payload
6265

@@ -106,18 +109,29 @@ def import_bucket(self, bucket_data: Any):
106109
type=bucket_data["type"],
107110
client=bucket_data["client"],
108111
hostname=bucket_data["hostname"],
109-
created=(bucket_data["created"]
110-
if isinstance(bucket_data["created"], datetime)
111-
else iso8601.parse_date(bucket_data["created"])),
112+
created=(
113+
bucket_data["created"]
114+
if isinstance(bucket_data["created"], datetime)
115+
else iso8601.parse_date(bucket_data["created"])
116+
),
117+
)
118+
self.create_events(
119+
bucket_id,
120+
[Event(**e) if isinstance(e, dict) else e for e in bucket_data["events"]],
112121
)
113-
self.create_events(bucket_id, [Event(**e) if isinstance(e, dict) else e for e in bucket_data["events"]])
114122

115123
def import_all(self, buckets: Dict[str, Any]):
116124
for bid, bucket in buckets.items():
117125
self.import_bucket(bucket)
118126

119-
def create_bucket(self, bucket_id: str, event_type: str, client: str,
120-
hostname: str, created: Optional[datetime] = None)-> bool:
127+
def create_bucket(
128+
self,
129+
bucket_id: str,
130+
event_type: str,
131+
client: str,
132+
hostname: str,
133+
created: Optional[datetime] = None,
134+
) -> bool:
121135
"""
122136
Create bucket.
123137
Returns True if successful, otherwise false if a bucket with the given ID already existed.
@@ -131,7 +145,7 @@ def create_bucket(self, bucket_id: str, event_type: str, client: str,
131145
type=event_type,
132146
client=client,
133147
hostname=hostname,
134-
created=created
148+
created=created,
135149
)
136150
return True
137151

@@ -143,14 +157,20 @@ def delete_bucket(self, bucket_id: str) -> None:
143157
return None
144158

145159
@check_bucket_exists
146-
def get_events(self, bucket_id: str, limit: int = -1,
147-
start: datetime = None, end: datetime = None) -> List[Event]:
160+
def get_events(
161+
self,
162+
bucket_id: str,
163+
limit: int = -1,
164+
start: datetime = None,
165+
end: datetime = None,
166+
) -> List[Event]:
148167
"""Get events from a bucket"""
149168
logger.debug("Received get request for events in bucket '{}'".format(bucket_id))
150169
if limit is None: # Let limit = None also mean "no limit"
151170
limit = -1
152-
events = [event.to_json_dict() for event in
153-
self.db[bucket_id].get(limit, start, end)]
171+
events = [
172+
event.to_json_dict() for event in self.db[bucket_id].get(limit, start, end)
173+
]
154174
return events
155175

156176
@check_bucket_exists
@@ -161,10 +181,13 @@ def create_events(self, bucket_id: str, events: List[Event]) -> Optional[Event]:
161181
return self.db[bucket_id].insert(events[0] if len(events) == 1 else events)
162182

163183
@check_bucket_exists
164-
def get_eventcount(self, bucket_id: str,
165-
start: datetime = None, end: datetime = None) -> int:
184+
def get_eventcount(
185+
self, bucket_id: str, start: datetime = None, end: datetime = None
186+
) -> int:
166187
"""Get eventcount from a bucket"""
167-
logger.debug("Received get request for eventcount in bucket '{}'".format(bucket_id))
188+
logger.debug(
189+
"Received get request for eventcount in bucket '{}'".format(bucket_id)
190+
)
168191
return self.db[bucket_id].get_eventcount(start, end)
169192

170193
@check_bucket_exists
@@ -195,8 +218,15 @@ def heartbeat(self, bucket_id: str, heartbeat: Event, pulsetime: float) -> Event
195218
196219
Inspired by: https://wakatime.com/developers#heartbeats
197220
"""
198-
logger.debug("Received heartbeat in bucket '{}'\n\ttimestamp: {}, duration: {}, pulsetime: {}\n\tdata: {}".format(
199-
bucket_id, heartbeat.timestamp, heartbeat.duration, pulsetime, heartbeat.data))
221+
logger.debug(
222+
"Received heartbeat in bucket '{}'\n\ttimestamp: {}, duration: {}, pulsetime: {}\n\tdata: {}".format(
223+
bucket_id,
224+
heartbeat.timestamp,
225+
heartbeat.duration,
226+
pulsetime,
227+
heartbeat.data,
228+
)
229+
)
200230

201231
# The endtime here is set such that in the event that the heartbeat is older than an
202232
# existing event we should try to merge it with the last event before the heartbeat instead.
@@ -220,16 +250,32 @@ def heartbeat(self, bucket_id: str, heartbeat: Event, pulsetime: float) -> Event
220250
merged = heartbeat_merge(last_event, heartbeat, pulsetime)
221251
if merged is not None:
222252
# Heartbeat was merged into last_event
223-
logger.debug("Received valid heartbeat, merging. (bucket: {})".format(bucket_id))
253+
logger.debug(
254+
"Received valid heartbeat, merging. (bucket: {})".format(
255+
bucket_id
256+
)
257+
)
224258
self.last_event[bucket_id] = merged
225259
self.db[bucket_id].replace_last(merged)
226260
return merged
227261
else:
228-
logger.info("Received heartbeat after pulse window, inserting as new event. (bucket: {})".format(bucket_id))
262+
logger.info(
263+
"Received heartbeat after pulse window, inserting as new event. (bucket: {})".format(
264+
bucket_id
265+
)
266+
)
229267
else:
230-
logger.debug("Received heartbeat with differing data, inserting as new event. (bucket: {})".format(bucket_id))
268+
logger.debug(
269+
"Received heartbeat with differing data, inserting as new event. (bucket: {})".format(
270+
bucket_id
271+
)
272+
)
231273
else:
232-
logger.info("Received heartbeat, but bucket was previously empty, inserting as new event. (bucket: {})".format(bucket_id))
274+
logger.info(
275+
"Received heartbeat, but bucket was previously empty, inserting as new event. (bucket: {})".format(
276+
bucket_id
277+
)
278+
)
233279

234280
self.db[bucket_id].insert(heartbeat)
235281
self.last_event[bucket_id] = heartbeat
@@ -238,7 +284,9 @@ def heartbeat(self, bucket_id: str, heartbeat: Event, pulsetime: float) -> Event
238284
def query2(self, name, query, timeperiods, cache):
239285
result = []
240286
for timeperiod in timeperiods:
241-
period = timeperiod.split("/")[:2] # iso8601 timeperiods are separated by a slash
287+
period = timeperiod.split("/")[
288+
:2
289+
] # iso8601 timeperiods are separated by a slash
242290
starttime = iso8601.parse_date(period[0])
243291
endtime = iso8601.parse_date(period[1])
244292
query = str().join(query)
@@ -249,7 +297,7 @@ def query2(self, name, query, timeperiods, cache):
249297
def get_log(self):
250298
"""Get the server log in json format"""
251299
payload = []
252-
with open(get_log_file_path(), 'r') as log_file:
300+
with open(get_log_file_path(), "r") as log_file:
253301
for line in log_file.readlines()[::-1]:
254302
payload.append(json.loads(line))
255303
return payload, 200

aw_server/config.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
"host": "localhost",
88
"port": "5600",
99
"storage": "peewee",
10-
"cors_origins": ""
10+
"cors_origins": "",
1111
}
1212
default_config["server-testing"] = {
1313
"host": "localhost",
1414
"port": "5666",
1515
"storage": "peewee",
16-
"cors_origins": ""
16+
"cors_origins": "",
1717
}
1818

1919
config = load_config("aw-server", default_config)

aw_server/exceptions.py

+2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ def __init__(self, type: str, message: str) -> None:
66
super().__init__(message)
77
self.type = type
88

9+
910
class NotFound(werkzeug.exceptions.NotFound):
1011
def __init__(self, type: str, message: str) -> None:
1112
super().__init__(message)
1213
self.type = type
1314

15+
1416
class Unauthorized(werkzeug.exceptions.Unauthorized):
1517
def __init__(self, type: str, message: str) -> None:
1618
super().__init__(message)

aw_server/log.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ def log(self, levelname, message, *args):
2222
levelno = logging.DEBUG
2323
else:
2424
raise Exception("Unknown level " + type)
25-
self.logger.log(levelno, '{} ({}): {}'.format(code, self.address_string(), msg))
25+
self.logger.log(levelno, "{} ({}): {}".format(code, self.address_string(), msg))

0 commit comments

Comments
 (0)