@wells-nelson/build-tools 1.0.3 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/package.json +1 -1
- package/templates/ci.yml +18 -0
- package/templates/database.yml +22 -0
- package/templates/deploy-pages.yml +23 -40
- package/templates/published-packages.yml +21 -0
- package/templates/supabase-ops/client-errors.sql +9 -0
- package/templates/supabase-ops/row-counts.sql +10 -0
- package/templates/supabase-ops/scratch-stub.sql +20 -0
- package/templates/supabase-ops/security-lint.sql +40 -0
package/README.md
CHANGED
|
@@ -70,6 +70,17 @@ on an origin its own `cachePrefix`: GitHub Pages project sites of one user all s
|
|
|
70
70
|
|
|
71
71
|
## Templates
|
|
72
72
|
|
|
73
|
-
`
|
|
73
|
+
Copy them from `node_modules/@wells-nelson/build-tools/templates/` into a new site (see ONBOARDING.md in
|
|
74
|
+
the repository). The workflow templates are a few lines each: triggers, permissions and a call to one of
|
|
75
|
+
the library's reusable workflows (see "Reusable workflows" in the repository README), where the steps live.
|
|
76
|
+
|
|
77
|
+
- `deploy-pages.yml` → `.github/workflows/deploy.yml` (replace `__REPO__`): type-check, test, build, deploy to
|
|
78
|
+
Pages, with a version tag reserved before the build and a GitHub release after the deploy.
|
|
79
|
+
- `ci.yml` and `published-packages.yml` → `.github/workflows/` as they are: the pull request check, and the
|
|
80
|
+
swap from local package tarballs to published versions.
|
|
81
|
+
- `database.yml` → `.github/workflows/` and `supabase-ops/*.sql` → `supabase/ops/` (replace `__SCHEMA__`):
|
|
82
|
+
nightly encrypted backup with a test restore, keep-alive, security lint and client error digest. The SQL
|
|
83
|
+
stays in the site, so it can also be pasted into the Supabase SQL editor.
|
|
84
|
+
- `manifest.webmanifest`: for PWAs.
|
|
74
85
|
|
|
75
86
|
Try the icons, manifest, `basePath` and `postbuild` in the sandbox's Build tools page.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wells-nelson/build-tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Build and deployment tooling for Wells Nelson SvelteKit PWAs: postbuild, PWA icon generator, Vite config pieces, service worker, and templates.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/templates/ci.yml
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Template (@wells-nelson/build-tools): copy to .github/workflows/ci.yml as is.
|
|
2
|
+
|
|
3
|
+
name: CI
|
|
4
|
+
|
|
5
|
+
# Type-check, unit tests and a production build on every pull request (the shared site-ci.yml).
|
|
6
|
+
# Branch protection requires the check "ci / Check, test and build".
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
ci:
|
|
18
|
+
uses: bnelson729/wells-nelson-components/.github/workflows/site-ci.yml@main
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Template (@wells-nelson/build-tools): copy to .github/workflows/database.yml and replace __SCHEMA__ with the
|
|
2
|
+
# site's Postgres schema; copy supabase-ops/ to supabase/ops/ too.
|
|
3
|
+
|
|
4
|
+
name: Database
|
|
5
|
+
|
|
6
|
+
# Nightly: encrypted backup with a test restore, keep-alive, security lint and client error digest
|
|
7
|
+
# for the __SCHEMA__ schema (the shared site-database.yml, running supabase/ops/). Uses the
|
|
8
|
+
# `database` environment; see CONTRIBUTING.md > Nightly Database workflow.
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
schedule:
|
|
12
|
+
- cron: '17 6 * * *'
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
database:
|
|
20
|
+
uses: bnelson729/wells-nelson-components/.github/workflows/site-database.yml@main
|
|
21
|
+
with:
|
|
22
|
+
schema: __SCHEMA__
|
|
@@ -1,52 +1,35 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
1
|
+
# Template (@wells-nelson/build-tools): copy to .github/workflows/deploy.yml and replace __REPO__ with the
|
|
2
|
+
# repository name (the GitHub Pages project path).
|
|
3
|
+
|
|
3
4
|
name: Deploy to GitHub Pages
|
|
4
5
|
|
|
6
|
+
# Every merge to main deploys and releases a new version (the shared site-deploy.yml). Run it by
|
|
7
|
+
# hand to bump the minor or major version. Reads the repository variables SUPABASE_URL,
|
|
8
|
+
# SUPABASE_ANON_KEY and, for a custom domain, BASE_PATH.
|
|
9
|
+
|
|
5
10
|
on:
|
|
6
11
|
push:
|
|
7
12
|
branches: [main]
|
|
8
13
|
workflow_dispatch:
|
|
14
|
+
inputs:
|
|
15
|
+
increment:
|
|
16
|
+
description: Which part of the version to bump
|
|
17
|
+
type: choice
|
|
18
|
+
options: [patch, minor, major]
|
|
19
|
+
default: patch
|
|
9
20
|
|
|
10
|
-
|
|
11
|
-
contents: read
|
|
12
|
-
pages: write
|
|
13
|
-
id-token: write
|
|
14
|
-
|
|
21
|
+
# One deploy at a time; a newer push waits for the running one instead of cancelling it halfway.
|
|
15
22
|
concurrency:
|
|
16
23
|
group: pages
|
|
17
|
-
cancel-in-progress:
|
|
24
|
+
cancel-in-progress: false
|
|
18
25
|
|
|
19
26
|
jobs:
|
|
20
|
-
build:
|
|
21
|
-
runs-on: ubuntu-latest
|
|
22
|
-
steps:
|
|
23
|
-
- uses: actions/checkout@v4
|
|
24
|
-
- uses: actions/setup-node@v4
|
|
25
|
-
with:
|
|
26
|
-
node-version: 24
|
|
27
|
-
cache: npm
|
|
28
|
-
- run: npm ci
|
|
29
|
-
# Nothing ships unless it type-checks and its tests pass.
|
|
30
|
-
- run: npm run check --if-present
|
|
31
|
-
- run: npm test --if-present
|
|
32
|
-
- run: npm run build
|
|
33
|
-
env:
|
|
34
|
-
# Repository variables (Settings > Secrets and variables > Actions > Variables).
|
|
35
|
-
# Leave the Supabase ones unset to deploy a local-only build.
|
|
36
|
-
VITE_SUPABASE_URL: ${{ vars.SUPABASE_URL }}
|
|
37
|
-
VITE_SUPABASE_ANON_KEY: ${{ vars.SUPABASE_ANON_KEY }}
|
|
38
|
-
# "/__REPO__" for <user>.github.io/__REPO__; set BASE_PATH to "/" for a custom domain.
|
|
39
|
-
BASE_PATH: ${{ vars.BASE_PATH || '/__REPO__' }}
|
|
40
|
-
- uses: actions/upload-pages-artifact@v3
|
|
41
|
-
with:
|
|
42
|
-
path: build
|
|
43
|
-
|
|
44
27
|
deploy:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
|
|
28
|
+
uses: bnelson729/wells-nelson-components/.github/workflows/site-deploy.yml@main
|
|
29
|
+
permissions:
|
|
30
|
+
contents: write
|
|
31
|
+
pages: write
|
|
32
|
+
id-token: write
|
|
33
|
+
with:
|
|
34
|
+
base-path: /__REPO__
|
|
35
|
+
increment: ${{ inputs.increment || 'patch' }}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Template (@wells-nelson/build-tools): copy to .github/workflows/published-packages.yml as is.
|
|
2
|
+
|
|
3
|
+
name: Use published packages
|
|
4
|
+
|
|
5
|
+
# While a shared @wells-nelson package is tried out, package.json points at a local tarball. On a
|
|
6
|
+
# pull request this swaps them for the published versions, commits the result to the branch and
|
|
7
|
+
# runs CI again (the shared site-published-packages.yml).
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [main]
|
|
12
|
+
paths:
|
|
13
|
+
- package.json
|
|
14
|
+
- package-lock.json
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
packages:
|
|
18
|
+
uses: bnelson729/wells-nelson-components/.github/workflows/site-published-packages.yml@main
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
actions: write
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- Template (@wells-nelson/build-tools): copy to supabase/ops/client-errors.sql and replace __SCHEMA__ with the app's schema.
|
|
2
|
+
-- What the app reported in the last 24 hours, most frequent first:
|
|
3
|
+
-- count, kind, newest version, message.
|
|
4
|
+
select count(*), kind, max(version), left(replace(message, '|', '/'), 200)
|
|
5
|
+
from __SCHEMA__.client_errors
|
|
6
|
+
where created_at > now() - interval '24 hours'
|
|
7
|
+
group by kind, message
|
|
8
|
+
order by count(*) desc
|
|
9
|
+
limit 25;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Template (@wells-nelson/build-tools): copy to supabase/ops/row-counts.sql and replace __SCHEMA__ with the app's schema.
|
|
2
|
+
-- One line per table of the __SCHEMA__ schema: "<table> <rows>". The Database
|
|
3
|
+
-- workflow compares these before and after a test restore. client_errors is left out: it's a
|
|
4
|
+
-- log that changes while the backup runs. psql only (\gexec); the Supabase SQL editor can't run it.
|
|
5
|
+
select format('select %L || '' '' || count(*) from %I.%I', c.relname, n.nspname, c.relname)
|
|
6
|
+
from pg_class c
|
|
7
|
+
join pg_namespace n on n.oid = c.relnamespace
|
|
8
|
+
where n.nspname = '__SCHEMA__' and c.relkind in ('r', 'p') and c.relname <> 'client_errors'
|
|
9
|
+
order by c.relname
|
|
10
|
+
\gexec
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Template (@wells-nelson/build-tools): copy to supabase/ops/scratch-stub.sql and replace __SCHEMA__ with the app's schema.
|
|
2
|
+
-- The parts of a Supabase database that the app's schema refers to, so its backup can be
|
|
3
|
+
-- restored into a plain Postgres (the Database workflow's restore test, or a local check).
|
|
4
|
+
-- Not for a Supabase project: those have all of this already.
|
|
5
|
+
create role anon nologin;
|
|
6
|
+
create role authenticated nologin;
|
|
7
|
+
create role service_role nologin;
|
|
8
|
+
create role supabase_admin nologin;
|
|
9
|
+
|
|
10
|
+
create schema auth;
|
|
11
|
+
create table auth.users (
|
|
12
|
+
id uuid primary key,
|
|
13
|
+
email text,
|
|
14
|
+
email_confirmed_at timestamptz,
|
|
15
|
+
last_sign_in_at timestamptz
|
|
16
|
+
);
|
|
17
|
+
create function auth.uid() returns uuid language sql stable as $$ select null::uuid $$;
|
|
18
|
+
create function auth.jwt() returns jsonb language sql stable as $$ select '{}'::jsonb $$;
|
|
19
|
+
|
|
20
|
+
create publication supabase_realtime;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
-- Template (@wells-nelson/build-tools): copy to supabase/ops/security-lint.sql and replace __SCHEMA__ with the app's schema.
|
|
2
|
+
-- Prints one line per problem in the __SCHEMA__ schema; no output means it passed. Runs in the
|
|
3
|
+
-- Supabase SQL editor or with psql -f.
|
|
4
|
+
-- Run by the Database workflow every night, and worth running after applying a migration.
|
|
5
|
+
|
|
6
|
+
-- Every table has row level security.
|
|
7
|
+
select format('Table %I.%I has no row level security', n.nspname, c.relname)
|
|
8
|
+
from pg_class c
|
|
9
|
+
join pg_namespace n on n.oid = c.relnamespace
|
|
10
|
+
where n.nspname = '__SCHEMA__' and c.relkind in ('r', 'p') and not c.relrowsecurity
|
|
11
|
+
|
|
12
|
+
union all
|
|
13
|
+
|
|
14
|
+
-- Signed-out callers (anon) can't touch any table.
|
|
15
|
+
select format('anon has %s on table %I.%I', p.privilege, n.nspname, c.relname)
|
|
16
|
+
from pg_class c
|
|
17
|
+
join pg_namespace n on n.oid = c.relnamespace
|
|
18
|
+
cross join unnest(array['SELECT', 'INSERT', 'UPDATE', 'DELETE']) as p(privilege)
|
|
19
|
+
where n.nspname = '__SCHEMA__' and c.relkind in ('r', 'p', 'v') and has_table_privilege('anon', c.oid, p.privilege)
|
|
20
|
+
|
|
21
|
+
union all
|
|
22
|
+
|
|
23
|
+
-- ... nor call any function but report_client_error (trigger functions can't be called).
|
|
24
|
+
select format('anon can execute %s', p.oid::regprocedure)
|
|
25
|
+
from pg_proc p
|
|
26
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
27
|
+
where n.nspname = '__SCHEMA__'
|
|
28
|
+
and p.prorettype <> 'trigger'::regtype
|
|
29
|
+
and p.proname <> 'report_client_error'
|
|
30
|
+
and has_function_privilege('anon', p.oid, 'EXECUTE')
|
|
31
|
+
|
|
32
|
+
union all
|
|
33
|
+
|
|
34
|
+
-- Security definer functions pin their search_path.
|
|
35
|
+
select format('Security definer function %s has no search_path', p.oid::regprocedure)
|
|
36
|
+
from pg_proc p
|
|
37
|
+
join pg_namespace n on n.oid = p.pronamespace
|
|
38
|
+
where n.nspname = '__SCHEMA__'
|
|
39
|
+
and p.prosecdef
|
|
40
|
+
and not exists (select 1 from unnest(coalesce(p.proconfig, '{}')) as c(setting) where c.setting like 'search_path=%');
|