Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GitHub Action for Tor update check #221

Merged
merged 2 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/update-tor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Tor package updates
on:
schedule:
- cron: "0 7 * * *"
jobs:
check-for-tor-updates:
runs-on: ubuntu-latest
container: debian:bookworm
env:
# This token is used by the issue generation script to open an issue
# in the SecureDrop repository via the `gh` CLI (hence GH_TOKEN).
# It is distinct from the PUSH_TOKEN, which is used for `git`
# commands.
GH_TOKEN: ${{ secrets.ISSUES_TOKEN }}
steps:
- name: Install dependencies
run: |
apt-get update && apt-get install --yes reprepro ca-certificates dctrl-tools \
git git-lfs openssh-client python3 gh
- uses: actions/checkout@v4
with:
lfs: true
# This token is required to push to the protected `main` branch.
token: ${{ secrets.PUSH_TOKEN }}
- name: Check for and commit Tor package updates
run: |
git config --global --add safe.directory '*'
git config user.email "[email protected]"
git config user.name "sdcibot"

# Import the Tor repo signing key
gpg --import repo/conf/updates-keys/*.gpg
# Run reprepro update, skip export since we just want the debs (and we don't have
# the repo signing key anyways)
REPREPRO_BASE_DIR=repo reprepro --export=never update

# Move the new packages over, intentionally leaving the old ones around
mv repo/pool/main/t/tor/*.deb core/focal/
git add core/focal/*.deb
# If there are changes, diff-index will fail, so we commit and push
git diff-index --quiet HEAD || (git commit -m "Automatically updating Tor packages" \
&& git push origin main && ../scripts/new-tor-issue)
72 changes: 72 additions & 0 deletions scripts/new-tor-issue
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""
Creates a new issue to track Tor updates or appends a comment
to any existing issues
"""

import json
import random
import subprocess
import tempfile

REPOSITORY = "freedomofpress/securedrop"
# TODO: Add more
SALUTATIONS = ["Aloha", "Bonjour", "Ciao", "Dear human overlords"]
TEMPLATE = """\
{salutation},

A new Tor update is available.

Details should be available on the [Tor forum](https://forum.torproject.net/c/news/tor-release-announcement/28).

<details><summary>Here is the commit I just pushed to
apt-test:</summary>

```diff
{patch}
```
</details>

* [x] CI adds new packages to apt-test
* [ ] Install tor, tor-geoipdb packages from apt-test on a prod
install and let them sit overnight
* [ ] Verify that tor is still running after reboot, services
available, no errors or unexpected messages in logs
* [ ] Submit a PR to `securedrop-apt-prod` to deploy
the same packages

P.S. This issue was created by `scripts/new-tor-issue` via the GitHub workflow `update-tor.yml`.
"""
TITLE = "New Tor update available"


def main():
patch = subprocess.check_output(["git", "format-patch", "HEAD~1", "--stdout"]).decode().strip()
# Query open issues to see if there's a task already open
existing = json.loads(subprocess.check_output(
["gh", "issue", "list", "-R", REPOSITORY,
"-S", TITLE, "--json", "title,number"]
))
with tempfile.TemporaryFile("w") as message:
message.write(TEMPLATE.format(salutation=random.choice(SALUTATIONS), patch=patch))
message.seek(0)
for issue in existing:
# Looks like there's already an open issue
if issue["title"] == TITLE:
subprocess.run(
["gh", "issue", "comment", "-R", REPOSITORY,
str(issue["number"]), "-F", "-"],
stdin=message, check=True
)
return

# Create a new issue
subprocess.run(
["gh", "issue", "create", "-R", REPOSITORY,
"--title", TITLE, "-F", "-"],
stdin=message, check=True
)


if __name__ == "__main__":
main()