@smi-digital/create-smi-app 2.9.1 → 2.9.2

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/dist/index.js CHANGED
@@ -702,21 +702,23 @@ async function activateVaultFilter(projectRoot) {
702
702
  } catch {
703
703
  return;
704
704
  }
705
- const setFilter = async (key, value) => runCommandQuiet(
706
- "git",
707
- ["config", `filter.ansible-vault.${key}`, value],
708
- projectRoot
709
- );
705
+ const setConfig = async (key, value) => runCommandQuiet("git", ["config", key, value], projectRoot);
710
706
  try {
711
- await setFilter(
712
- "clean",
713
- "ansible-vault encrypt --vault-password-file .vault-password --output=- -"
714
- );
715
- await setFilter(
716
- "smudge",
707
+ await setConfig("filter.ansible-vault.clean", "sh .gitvault/clean.sh %f");
708
+ await setConfig(
709
+ "filter.ansible-vault.smudge",
717
710
  "ansible-vault decrypt --vault-password-file .vault-password --output=- -"
718
711
  );
719
- await setFilter("required", "true");
712
+ await setConfig("filter.ansible-vault.required", "true");
713
+ await setConfig(
714
+ "merge.ansible-vault.name",
715
+ "Ansible-Vault aware 3-way merge"
716
+ );
717
+ await setConfig(
718
+ "merge.ansible-vault.driver",
719
+ "sh .gitvault/merge.sh %O %A %B %P"
720
+ );
721
+ await setConfig("diff.ansible-vault.textconv", "sh .gitvault/textconv.sh");
720
722
  } catch {
721
723
  console.warn(
722
724
  "Could not configure the Ansible-Vault git filter automatically. Run `npm run setup:vault` before committing."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smi-digital/create-smi-app",
3
- "version": "2.9.1",
3
+ "version": "2.9.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -9,7 +9,7 @@
9
9
  "prettier": "npx prettier --write .",
10
10
  "lint": "npx eslint .",
11
11
  "prepare": "husky",
12
- "setup:vault": "git config filter.ansible-vault.clean \"ansible-vault encrypt --vault-password-file .vault-password --output=- -\" && git config filter.ansible-vault.smudge \"ansible-vault decrypt --vault-password-file .vault-password --output=- -\" && git config filter.ansible-vault.required true && echo '✅ Ansible-Vault Git Filters configured successfully!'",
12
+ "setup:vault": "git config filter.ansible-vault.clean 'sh .gitvault/clean.sh %f' && git config filter.ansible-vault.smudge 'ansible-vault decrypt --vault-password-file .vault-password --output=- -' && git config filter.ansible-vault.required true && git config merge.ansible-vault.name 'Ansible-Vault aware 3-way merge' && git config merge.ansible-vault.driver 'sh .gitvault/merge.sh %O %A %B %P' && git config diff.ansible-vault.textconv 'sh .gitvault/textconv.sh' && echo '✅ Ansible-Vault Git filters configured successfully!'",
13
13
  "knip": "knip",
14
14
  "depcruise": "depcruise . --exclude \"node_modules|dist|.husky|test\"",
15
15
  "depcheck": "npm run knip && npm run depcruise",
@@ -1,2 +1,6 @@
1
1
  # Use Ansible-Vault Git filters for production environment files
2
2
  production.*.env filter=ansible-vault diff=ansible-vault merge=ansible-vault
3
+
4
+ # The vault filter/merge/diff helpers are invoked as shell scripts; force LF so a
5
+ # CRLF checkout on Windows can't break them.
6
+ .gitvault/*.sh text eol=lf
@@ -0,0 +1,41 @@
1
+ #!/bin/sh
2
+ # Idempotent Ansible-Vault "clean" filter (encrypt on the way INTO git).
3
+ #
4
+ # Why this exists: `ansible-vault encrypt` uses a random salt, so encrypting the
5
+ # same plaintext twice produces DIFFERENT ciphertext. With a naive clean filter
6
+ # git re-encrypts on every status/diff/checkout and therefore ALWAYS sees the
7
+ # file as "modified" — phantom diffs, salt-only churn baked into history, and
8
+ # rebases/stashes that conflict on the ciphertext.
9
+ #
10
+ # This wrapper makes the filter deterministic: if the plaintext is unchanged
11
+ # from what is already committed, it re-emits the EXISTING ciphertext verbatim
12
+ # (no re-salt), so git sees no change. Only a real plaintext edit re-encrypts.
13
+ #
14
+ # Invoked by git as: sh .gitvault/clean.sh %f (%f = repo-relative path)
15
+ # stdin = working-tree plaintext
16
+ # stdout = ciphertext to store in the index/commit
17
+ set -eu
18
+
19
+ path="${1:-}"
20
+ pwfile=".vault-password"
21
+
22
+ new="$(mktemp)"
23
+ old_cipher="$(mktemp)"
24
+ old_plain="$(mktemp)"
25
+ trap 'rm -f "$new" "$old_cipher" "$old_plain"' EXIT
26
+
27
+ cat > "$new"
28
+
29
+ # The ciphertext already recorded for this path in the index (if any). Missing on
30
+ # a first add, or unreadable if it was committed as plaintext once — both cases
31
+ # fall through to a fresh encrypt.
32
+ if [ -n "$path" ] \
33
+ && git cat-file -p ":$path" > "$old_cipher" 2>/dev/null \
34
+ && ansible-vault decrypt --vault-password-file "$pwfile" --output=- "$old_cipher" > "$old_plain" 2>/dev/null \
35
+ && cmp -s "$new" "$old_plain"; then
36
+ # Plaintext identical to what's stored → reuse the stored ciphertext (no re-salt).
37
+ cat "$old_cipher"
38
+ else
39
+ # New file or a genuine plaintext change → encrypt fresh.
40
+ ansible-vault encrypt --vault-password-file "$pwfile" --output=- "$new"
41
+ fi
@@ -0,0 +1,42 @@
1
+ #!/bin/sh
2
+ # Ansible-Vault aware merge driver — merges at the PLAINTEXT level.
3
+ #
4
+ # Git's default merge would 3-way-merge the opaque ciphertext and conflict on
5
+ # nearly everything (different salts even when the plaintext agrees). This driver
6
+ # decrypts the three inputs, runs a normal 3-way text merge, then RE-ENCRYPTS the
7
+ # result. Git stores %A's bytes verbatim and then runs the smudge filter on them,
8
+ # so %A must contain CIPHERTEXT (verified behaviour).
9
+ #
10
+ # Invoked by git as: sh .gitvault/merge.sh %O %A %B %P
11
+ # %O = common-ancestor (base) ciphertext file
12
+ # %A = our version ciphertext file (ALSO the output file git reads back)
13
+ # %B = their version ciphertext file
14
+ # %P = the real pathname (used only for conflict-marker labels)
15
+ # Exit 0 = clean merge; non-zero = conflict (git marks the path unmerged, then
16
+ # smudges %A so the working tree shows readable plaintext conflict markers).
17
+ set -eu
18
+
19
+ base="$1"; ours="$2"; theirs="$3"; path="${4:-file}"
20
+ pwfile=".vault-password"
21
+
22
+ # Decrypt $1 to stdout; if it isn't vault-encrypted (e.g. an empty base), pass
23
+ # it through unchanged so the merge still has something to work with.
24
+ dec() {
25
+ ansible-vault decrypt --vault-password-file "$pwfile" --output=- "$1" 2>/dev/null || cat "$1"
26
+ }
27
+
28
+ o="$(mktemp)"; a="$(mktemp)"; b="$(mktemp)"
29
+ trap 'rm -f "$o" "$a" "$b"' EXIT
30
+ dec "$base" > "$o"
31
+ dec "$ours" > "$a"
32
+ dec "$theirs" > "$b"
33
+
34
+ # 3-way merge on plaintext, written in place into "$a". Returns the conflict
35
+ # count (0 = clean); capture it instead of letting `set -e` abort.
36
+ status=0
37
+ git merge-file -L "ours ($path)" -L "base ($path)" -L "theirs ($path)" "$a" "$o" "$b" || status=$?
38
+
39
+ # Re-encrypt the (possibly conflict-marked) result back into %A as ciphertext.
40
+ ansible-vault encrypt --vault-password-file "$pwfile" --output=- "$a" > "$ours"
41
+
42
+ exit "$status"
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+ # Ansible-Vault diff textconv: render a vault file as plaintext for `git diff`.
3
+ #
4
+ # git applies this to BOTH sides of a diff — the committed blob (ciphertext) and
5
+ # the working-tree copy (already decrypted by the smudge filter). So decrypt when
6
+ # possible and fall back to cat when the input isn't vault-encrypted, otherwise
7
+ # the working-tree side errors with "Input is not vault encrypted data".
8
+ #
9
+ # Invoked by git as: sh .gitvault/textconv.sh <path>
10
+ ansible-vault decrypt --vault-password-file .vault-password --output=- "$1" 2>/dev/null || cat "$1"
@@ -81,6 +81,18 @@
81
81
  "template": ".gitattributes.template",
82
82
  "target": ".gitattributes"
83
83
  },
84
+ {
85
+ "template": ".gitvault/clean.sh.template",
86
+ "target": ".gitvault/clean.sh"
87
+ },
88
+ {
89
+ "template": ".gitvault/merge.sh.template",
90
+ "target": ".gitvault/merge.sh"
91
+ },
92
+ {
93
+ "template": ".gitvault/textconv.sh.template",
94
+ "target": ".gitvault/textconv.sh"
95
+ },
84
96
  {
85
97
  "template": "production.frontend.env.template",
86
98
  "target": "production.frontend.env"