From 9d2d8c428c4175fb1d9f1f76367e8b8cfa7fc15d Mon Sep 17 00:00:00 2001 From: Hisam Mehboob Date: Tue, 18 Aug 2026 20:53:14 +0500 Subject: [PATCH 1/2] Add cron workflow to update driverless printer list (#229) --- .github/workflows/update-driverless.yml | 63 +++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/update-driverless.yml diff --git a/.github/workflows/update-driverless.yml b/.github/workflows/update-driverless.yml new file mode 100644 index 00000000..f0dab686 --- /dev/null +++ b/.github/workflows/update-driverless.yml @@ -0,0 +1,63 @@ +name: Update driverless printer list + +on: + schedule: + # Monthly, 1st of the month at 06:00 UTC + - cron: '0 6 1 * *' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +# A manual run must not overlap a scheduled one mid-PR. +concurrency: + group: "update-driverless" + cancel-in-progress: false + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + # The script must run from driverless/: it reads ./convert-airprint.py and + # ./add-ippeve-only.py and writes ../public/assets/json/driverless.json. + - name: Update printer list + working-directory: driverless + run: ./update-printer-list.sh + + # Guard against an empty/garbled list slipping through (#223). The script + # has no `set -e`, so a failed upstream fetch can still exit 0 with a + # truncated file; fail the run before any PR is opened. + - name: Validate updated list + run: | + python3 - <<'PY' + import json, sys + try: + with open('public/assets/json/driverless.json') as f: + data = json.load(f) + except Exception as e: + print(f'::error::driverless.json is not valid JSON ({e}). Aborting.') + sys.exit(1) + count = sum(1 for p in data if p.get('model') != '_dummy_') + print(f'Driverless printers: {count}') + if count < 5000: + print(f'::error::driverless.json has only {count} printers; expected thousands. Aborting.') + sys.exit(1) + PY + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v8 + with: + token: ${{ secrets.GITHUB_TOKEN }} + add-paths: public/assets/json/driverless.json + branch: update-driverless-list + delete-branch: true + commit-message: "Update driverless printer list" + title: "Update driverless printer list" + body: | + Automated monthly update of the driverless (AirPrint + IPP Everywhere) + printer list, generated by `driverless/update-printer-list.sh`. From 143ea8661dfbb3a74f3292d75a612256d9132f3c Mon Sep 17 00:00:00 2001 From: Hisam Mehboob Date: Tue, 18 Aug 2026 21:13:12 +0500 Subject: [PATCH 2/2] Harden driverless list validation with shape checks --- .github/workflows/update-driverless.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/update-driverless.yml b/.github/workflows/update-driverless.yml index f0dab686..f0a9b53f 100644 --- a/.github/workflows/update-driverless.yml +++ b/.github/workflows/update-driverless.yml @@ -42,7 +42,16 @@ jobs: except Exception as e: print(f'::error::driverless.json is not valid JSON ({e}). Aborting.') sys.exit(1) - count = sum(1 for p in data if p.get('model') != '_dummy_') + if not isinstance(data, list): + print(f'::error::driverless.json must be a JSON array, got {type(data).__name__}. Aborting.') + sys.exit(1) + count = 0 + for p in data: + if not isinstance(p, dict) or 'model' not in p: + print(f'::error::driverless.json contains a malformed entry: {p!r}. Aborting.') + sys.exit(1) + if p['model'] != '_dummy_': + count += 1 print(f'Driverless printers: {count}') if count < 5000: print(f'::error::driverless.json has only {count} printers; expected thousands. Aborting.')