Skip to content

Commit 4399873

Browse files
authored
Merge pull request #213 from mozilla-services/feat/add-rs-script
[WebkitLists] P3. Add `publish2rs` script to push changes to RS
2 parents 43d118b + 540d417 commit 4399873

File tree

5 files changed

+112
-2
lines changed

5 files changed

+112
-2
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ RUN python -m pip install --no-cache-dir -r requirements.txt
2020
# Copy the rest of the application code
2121
COPY --chown=app:app . .
2222

23-
CMD ["python", "lists2safebrowsing.py"]
23+
CMD ["sh", "enrypoint.sh"]

entrypoint.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Build and publish the tracking lists for safebrowsing and webkit
2+
python lists2safebrowsing.py
3+
python lists2webkit.py

lists2webkit.py

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
import os
33
from settings import config
4+
from publish2rs import publish2rs
45
from constants import (
56
DNT_SECTIONS,
67
PRE_DNT_SECTIONS,
@@ -149,5 +150,10 @@ def main():
149150

150151
print("All content blocker rules have been generated successfully.")
151152

153+
# Push to remote settings
154+
publish2rs()
155+
156+
return os.EX_OK
157+
152158
if __name__ == "__main__":
153159
main()

publish2rs.py

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python
2+
3+
import os
4+
import kinto_http
5+
import hashlib
6+
import pathlib
7+
import uuid
8+
9+
from settings import config
10+
11+
from constants import WEBKIT_LISTS_DIR
12+
13+
def get_config_if_env(env_var, config_section, config_option, fallback=""):
14+
"""
15+
Return the config value if the environment variable exists; otherwise, return the fallback.
16+
"""
17+
if env_var in os.environ:
18+
return os.environ[env_var]
19+
return config.get(config_section, config_option, fallback=fallback)
20+
21+
def get_file_hash(list_path):
22+
with open(list_path, "rb") as f:
23+
return hashlib.sha256(f.read()).hexdigest()
24+
25+
SERVER = get_config_if_env("SERVER", "main", "remote_settings_url")
26+
BUCKET = "main-workspace"
27+
COLLECTION = "tracking-protection-lists-ios"
28+
AUTHORIZATION = get_config_if_env("AUTHORIZATION", "main", "remote_settings_authorization")
29+
ENVIRONMENT = os.getenv("ENVIRONMENT", "local").lower()
30+
DRY_RUN = os.getenv("DRY_RUN", "0") in "1yY"
31+
32+
def publish2rs():
33+
client = kinto_http.Client(
34+
server_url=SERVER,
35+
auth=AUTHORIZATION,
36+
bucket=BUCKET,
37+
collection=COLLECTION,
38+
dry_mode=DRY_RUN
39+
)
40+
41+
remote_attachments = {
42+
r["name"]: {"id": r["id"], "hash": r["attachment"]["hash"]}
43+
for r in client.get_records()
44+
}
45+
46+
local_attachments = {
47+
file.stem: get_file_hash(file)
48+
for file in pathlib.Path(WEBKIT_LISTS_DIR).iterdir()
49+
}
50+
51+
# Determine records to create, update, or delete
52+
# by comparing the attachment sha256 hashes.
53+
to_create = []
54+
to_update = []
55+
for name, hash in local_attachments.items():
56+
remote_attachment = remote_attachments.pop(name, None)
57+
if remote_attachment is None:
58+
to_create.append({"name": name})
59+
elif remote_attachment["hash"] != hash:
60+
to_update.append({"id": remote_attachment["id"], "name": name})
61+
# Remaining records in `remote_attachments` are to be deleted.
62+
to_delete = [{"id": record["id"]} for _, record in remote_attachments.items()]
63+
64+
# Print changes
65+
print("Changes to apply:")
66+
print(f"To create: {to_create}")
67+
print(f"To update: {to_update}")
68+
print(f"To delete: {to_delete}")
69+
70+
has_pending_changes = (len(to_create) + len(to_update) + len(to_delete)) > 0
71+
if not has_pending_changes:
72+
print("Records are in sync. Nothing to do ✅.")
73+
return os.EX_OK
74+
75+
# Batch delete operations.
76+
# NOTE: Attachment deletion is implicit when deleting a record.
77+
with client.batch() as batch:
78+
for record in to_delete:
79+
batch.delete_record(id=record["id"])
80+
81+
# Adding, updating attachments on client
82+
# since batch operations are not supported.
83+
for record in to_create:
84+
id = str(uuid.uuid4())
85+
filepath = f"{WEBKIT_LISTS_DIR}/{record['name']}.json"
86+
client.add_attachment(id=id, data={"name": record["name"]}, filepath=filepath)
87+
for record in to_update:
88+
filepath = f"{WEBKIT_LISTS_DIR}/{record['name']}.json"
89+
client.add_attachment(id=record["id"], filepath=filepath)
90+
91+
92+
if ENVIRONMENT == "dev":
93+
# Self approve changes on DEV.
94+
# message arg is not supported as of now.
95+
client.approve_changes()
96+
print("Changes applied to dev server ✅")
97+
else:
98+
# Request review.
99+
print("Request review...", end="")
100+
client.request_review(message="r?")
101+
print("✅")

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ publicsuffixlist==0.7.5
33
requests==2.32.0
44
trackingprotection-tools==0.6.1
55
packaging==20.4
6-
kinto-http==11.1.0
6+
kinto-http==11.7.0

0 commit comments

Comments
 (0)