Skip to content

Commit b81af85

Browse files
committed
chore: update package versions and add versioning scripts
- Updated version numbers in package.json for functions and snapsign.com.au. - Added a script to write the version information to a file during build. - Created version.js files in both functions and snapsign.com.au to export the app version. - Updated build script in snapsign.com.au to include version writing step.
1 parent 895a021 commit b81af85

10 files changed

Lines changed: 971 additions & 926 deletions

File tree

README.md

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,71 @@ Tests cover:
104104
- Error handling scenarios
105105

106106
## Deployment
107+
108+
### Recommended: Unified Build + Deploy Script
109+
Use the root script `./build-and-deploy.sh` to build all dependent projects and deploy from one command.
110+
111+
The script runs from repo root and orchestrates:
112+
1. Optional semver bump in all project `package.json` files (`patch`, `minor`, `major`)
113+
2. `npm ci` in:
114+
- `snapsign.com.au/`
115+
- `Decodocs/web/`
116+
- `Decodocs/admin/`
117+
- `functions/`
118+
3. Build/version steps:
119+
- `snapsign.com.au`: `npm run build`
120+
- `Decodocs/web`: `npm run build`
121+
- `Decodocs/admin`: `npm run build`
122+
- `functions`: `npm run version:write`
123+
4. Output validation:
124+
- `snapsign.com.au/dist/`
125+
- `Decodocs/web/decodocs.com/`
126+
- `Decodocs/admin/dist/`
127+
5. Firebase deploy (default targets): `functions,hosting,firestore`
128+
129+
### Common Usage
107130
```bash
108-
# Deploy functions
109-
firebase deploy --only functions
131+
# Build + deploy everything
132+
./build-and-deploy.sh
110133

111-
# Deploy hosting
112-
firebase deploy --only hosting
134+
# Bump patch version across all projects, then build + deploy
135+
./build-and-deploy.sh --bump patch
136+
137+
# Build only (no deploy)
138+
./build-and-deploy.sh --skip-deploy
139+
140+
# Deploy only (skip install and build)
141+
./build-and-deploy.sh --skip-install --skip-build
142+
143+
# Override Firebase project
144+
./build-and-deploy.sh --project snapsign-au
113145

114-
# Deploy Firestore rules
146+
# Deploy selected targets only
147+
./build-and-deploy.sh --only hosting
148+
```
149+
150+
### Options
151+
- `--skip-install`: skip dependency install (`npm ci`)
152+
- `--skip-build`: skip build/version steps
153+
- `--skip-deploy`: skip Firebase deploy
154+
- `--bump <patch|minor|major>`: bump versions in all project `package.json` files
155+
- `--project <projectId>`: override Firebase project id
156+
- `--only <targets>`: Firebase deploy targets (default: `functions,hosting,firestore`)
157+
- `-h, --help`: print help
158+
159+
### Version Metadata Notes
160+
Version metadata is generated by custom scripts (not `genversion`):
161+
- `snapsign.com.au/scripts/write-version.mjs` writes `snapsign.com.au/src/lib/version.js`
162+
- `Decodocs/web/scripts/write-version.mjs` writes `Decodocs/web/src/lib/version.js`
163+
- `Decodocs/admin/scripts/write-version.mjs` writes `Decodocs/admin/src/lib/version.js`
164+
- `functions/scripts/write-version.mjs` writes `functions/lib/version.js`
165+
166+
Each generated version string includes the package version and build metadata (git SHA/time), so version files may change on each build.
167+
168+
### Manual Firebase Deploy (Fallback)
169+
```bash
170+
firebase deploy --only functions
171+
firebase deploy --only hosting
115172
firebase deploy --only firestore:rules
116173
```
117174

build-and-deploy.sh

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
6+
SNAPSIGN_DIR="$ROOT_DIR/snapsign.com.au"
7+
DECO_WEB_DIR="$ROOT_DIR/Decodocs/web"
8+
DECO_ADMIN_DIR="$ROOT_DIR/Decodocs/admin"
9+
FUNCTIONS_DIR="$ROOT_DIR/functions"
10+
11+
SNAPSIGN_OUT="$SNAPSIGN_DIR/dist"
12+
DECO_WEB_OUT="$DECO_WEB_DIR/decodocs.com"
13+
DECO_ADMIN_OUT="$DECO_ADMIN_DIR/dist"
14+
15+
SKIP_INSTALL=0
16+
SKIP_BUILD=0
17+
SKIP_DEPLOY=0
18+
PROJECT_ID=""
19+
FIREBASE_ONLY="functions,hosting,firestore"
20+
VERSION_BUMP=""
21+
22+
usage() {
23+
cat <<USAGE
24+
Usage: $(basename "$0") [options]
25+
26+
Builds all dependent subprojects and deploys via Firebase from repo root.
27+
28+
Options:
29+
--skip-install Skip npm dependency installation
30+
--skip-build Skip npm build steps
31+
--skip-deploy Skip Firebase deploy step
32+
--bump <type> Bump version in all project package.json files (patch|minor|major)
33+
--project <projectId> Firebase project id override (default from .firebaserc)
34+
--only <targets> Firebase deploy targets (default: functions,hosting,firestore)
35+
-h, --help Show this help
36+
37+
Examples:
38+
./build-and-deploy.sh
39+
./build-and-deploy.sh --bump patch
40+
./build-and-deploy.sh --bump minor --skip-install
41+
./build-and-deploy.sh --skip-install
42+
./build-and-deploy.sh --skip-deploy
43+
./build-and-deploy.sh --project snapsign-au
44+
USAGE
45+
}
46+
47+
log() {
48+
printf '\n[%s] %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$*"
49+
}
50+
51+
require_cmd() {
52+
if ! command -v "$1" >/dev/null 2>&1; then
53+
echo "Error: required command '$1' is not installed or not in PATH." >&2
54+
exit 1
55+
fi
56+
}
57+
58+
run_npm_ci() {
59+
local dir="$1"
60+
log "Installing dependencies in $dir"
61+
(cd "$dir" && npm ci)
62+
}
63+
64+
run_npm_build() {
65+
local dir="$1"
66+
log "Building $dir"
67+
(cd "$dir" && npm run build)
68+
}
69+
70+
run_npm_script() {
71+
local dir="$1"
72+
local script_name="$2"
73+
log "Running npm script '$script_name' in $dir"
74+
(cd "$dir" && npm run "$script_name")
75+
}
76+
77+
bump_package_version() {
78+
local pkg_path="$1"
79+
local bump="$2"
80+
81+
node - "$pkg_path" "$bump" <<'NODE'
82+
const fs = require('node:fs');
83+
const pkgPath = process.argv[2];
84+
const bump = process.argv[3];
85+
86+
const raw = fs.readFileSync(pkgPath, 'utf8');
87+
const pkg = JSON.parse(raw);
88+
const original = pkg.version || '0.1.0';
89+
90+
const match = String(original).match(/^(\d+)\.(\d+)\.(\d+)/);
91+
if (!match) {
92+
console.error(`Error: unsupported version format in ${pkgPath}: ${original}`);
93+
process.exit(1);
94+
}
95+
96+
let major = Number(match[1]);
97+
let minor = Number(match[2]);
98+
let patch = Number(match[3]);
99+
100+
if (bump === 'patch') {
101+
patch += 1;
102+
} else if (bump === 'minor') {
103+
minor += 1;
104+
patch = 0;
105+
} else if (bump === 'major') {
106+
major += 1;
107+
minor = 0;
108+
patch = 0;
109+
} else {
110+
console.error(`Error: unsupported bump type: ${bump}`);
111+
process.exit(1);
112+
}
113+
114+
pkg.version = `${major}.${minor}.${patch}`;
115+
fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
116+
console.log(`${pkgPath}: ${original} -> ${pkg.version}`);
117+
NODE
118+
}
119+
120+
bump_all_project_versions() {
121+
local bump="$1"
122+
123+
log "Bumping project versions: $bump"
124+
bump_package_version "$SNAPSIGN_DIR/package.json" "$bump"
125+
bump_package_version "$DECO_WEB_DIR/package.json" "$bump"
126+
bump_package_version "$DECO_ADMIN_DIR/package.json" "$bump"
127+
bump_package_version "$FUNCTIONS_DIR/package.json" "$bump"
128+
}
129+
130+
assert_dir_exists() {
131+
local dir="$1"
132+
if [[ ! -d "$dir" ]]; then
133+
echo "Error: required directory does not exist: $dir" >&2
134+
exit 1
135+
fi
136+
}
137+
138+
assert_output_exists() {
139+
local dir="$1"
140+
if [[ ! -d "$dir" ]]; then
141+
echo "Error: expected build output directory not found: $dir" >&2
142+
exit 1
143+
fi
144+
}
145+
146+
while [[ $# -gt 0 ]]; do
147+
case "$1" in
148+
--skip-install)
149+
SKIP_INSTALL=1
150+
shift
151+
;;
152+
--skip-build)
153+
SKIP_BUILD=1
154+
shift
155+
;;
156+
--skip-deploy)
157+
SKIP_DEPLOY=1
158+
shift
159+
;;
160+
--bump)
161+
VERSION_BUMP="${2:-}"
162+
if [[ -z "$VERSION_BUMP" ]]; then
163+
echo "Error: --bump requires a value" >&2
164+
exit 1
165+
fi
166+
if [[ "$VERSION_BUMP" != "patch" && "$VERSION_BUMP" != "minor" && "$VERSION_BUMP" != "major" ]]; then
167+
echo "Error: --bump must be one of: patch, minor, major" >&2
168+
exit 1
169+
fi
170+
shift 2
171+
;;
172+
--project)
173+
PROJECT_ID="${2:-}"
174+
if [[ -z "$PROJECT_ID" ]]; then
175+
echo "Error: --project requires a value" >&2
176+
exit 1
177+
fi
178+
shift 2
179+
;;
180+
--only)
181+
FIREBASE_ONLY="${2:-}"
182+
if [[ -z "$FIREBASE_ONLY" ]]; then
183+
echo "Error: --only requires a value" >&2
184+
exit 1
185+
fi
186+
shift 2
187+
;;
188+
-h|--help)
189+
usage
190+
exit 0
191+
;;
192+
*)
193+
echo "Error: unknown option '$1'" >&2
194+
usage
195+
exit 1
196+
;;
197+
esac
198+
done
199+
200+
require_cmd npm
201+
require_cmd firebase
202+
203+
assert_dir_exists "$SNAPSIGN_DIR"
204+
assert_dir_exists "$DECO_WEB_DIR"
205+
assert_dir_exists "$DECO_ADMIN_DIR"
206+
assert_dir_exists "$FUNCTIONS_DIR"
207+
208+
if [[ -n "$VERSION_BUMP" ]]; then
209+
bump_all_project_versions "$VERSION_BUMP"
210+
fi
211+
212+
if [[ "$SKIP_INSTALL" -eq 0 ]]; then
213+
run_npm_ci "$SNAPSIGN_DIR"
214+
run_npm_ci "$DECO_WEB_DIR"
215+
run_npm_ci "$DECO_ADMIN_DIR"
216+
run_npm_ci "$FUNCTIONS_DIR"
217+
else
218+
log "Skipping dependency installation"
219+
fi
220+
221+
if [[ "$SKIP_BUILD" -eq 0 ]]; then
222+
run_npm_build "$SNAPSIGN_DIR"
223+
run_npm_build "$DECO_WEB_DIR"
224+
run_npm_build "$DECO_ADMIN_DIR"
225+
run_npm_script "$FUNCTIONS_DIR" "version:write"
226+
227+
assert_output_exists "$SNAPSIGN_OUT"
228+
assert_output_exists "$DECO_WEB_OUT"
229+
assert_output_exists "$DECO_ADMIN_OUT"
230+
231+
log "Build outputs verified"
232+
else
233+
log "Skipping build steps"
234+
fi
235+
236+
if [[ "$SKIP_DEPLOY" -eq 0 ]]; then
237+
log "Deploying Firebase targets: $FIREBASE_ONLY"
238+
if [[ -n "$PROJECT_ID" ]]; then
239+
(cd "$ROOT_DIR" && firebase deploy --project "$PROJECT_ID" --only "$FIREBASE_ONLY")
240+
else
241+
(cd "$ROOT_DIR" && firebase deploy --only "$FIREBASE_ONLY")
242+
fi
243+
log "Deployment completed"
244+
else
245+
log "Skipping Firebase deploy"
246+
fi

0 commit comments

Comments
 (0)