deploy.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233
  1. #!/usr/bin/env bun
  2. // Publish the built playlist + guide to chillidonut.com/junk/iptv/ on GCS.
  3. //
  4. // SAFETY: uploads to two EXPLICIT object paths with `gsutil cp`. `cp` is additive —
  5. // it only creates/overwrites the exact objects named. It never lists, syncs, or
  6. // deletes, so NOTHING else under junk/ can be affected. (`gsutil rsync` and
  7. // `gsutil rm` — the only commands that delete — are deliberately not used.)
  8. //
  9. // `-Z` gzips on upload and sets Content-Encoding: gzip (served compressed; the
  10. // ~32 MB guide travels at ~3-4 MB). url-tvg stays …/guide.xml — do NOT pre-gzip.
  11. //
  12. // AUTH: needs a current gsutil token. If you see "Reauthentication required", run
  13. // `gcloud auth login` once. (That CLI token is separate from the ADC that
  14. // `hugo deploy` uses, which is why hugo can deploy while gsutil is stale.)
  15. import { $ } from 'bun';
  16. import { existsSync } from 'node:fs';
  17. const HERE = import.meta.dir;
  18. const uploads = [
  19. { local: `${HERE}/iptv.m3u`, remote: 'gs://chillidonut.com/junk/iptv/iptv.m3u' },
  20. { local: `${HERE}/guide.xml`, remote: 'gs://chillidonut.com/junk/iptv/guide.xml' },
  21. ];
  22. for (const u of uploads)
  23. if (!existsSync(u.local)) { console.error(`missing ${u.local} — run \`bun refresh.ts\` first`); process.exit(1); }
  24. console.log('Uploading ONLY these two objects (nothing else under junk/ is touched):');
  25. for (const u of uploads) console.log(` ${u.local}\n -> ${u.remote}`);
  26. for (const u of uploads)
  27. await $`gsutil -h ${'Cache-Control:public,max-age=3600'} cp -Z ${u.local} ${u.remote}`;
  28. console.log('done — gzipped, Content-Encoding: gzip.');