@opencrvs/create-countryconfig 2.0.1-rc.fed4de8 → 2.0.2-rc.0534cee

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.
Files changed (2) hide show
  1. package/index.js +210 -25
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -17,8 +17,183 @@ const fs = require('fs')
17
17
 
18
18
  const COUNTRYCONFIG_REPO_URL =
19
19
  'https://github.com/opencrvs/opencrvs-countryconfig.git'
20
- const INFRASTRUCTURE_REPO_URL =
21
- 'https://github.com/opencrvs/infrastructure.git'
20
+ const INFRASTRUCTURE_REPO_URL = 'https://github.com/opencrvs/infrastructure.git'
21
+
22
+ const { version } = JSON.parse(
23
+ fs.readFileSync(path.join(__dirname, 'package.json'), 'utf-8')
24
+ )
25
+
26
+ function tagExists(repoUrl, tag) {
27
+ try {
28
+ execSync(
29
+ 'git ls-remote --exit-code --tags ' + repoUrl + ' refs/tags/' + tag,
30
+ {
31
+ stdio: 'pipe'
32
+ }
33
+ )
34
+ return true
35
+ } catch (err) {
36
+ return false
37
+ }
38
+ }
39
+
40
+ function branchExists(repoUrl, branch) {
41
+ try {
42
+ execSync(
43
+ 'git ls-remote --exit-code --heads ' + repoUrl + ' refs/heads/' + branch,
44
+ {
45
+ stdio: 'pipe'
46
+ }
47
+ )
48
+ return true
49
+ } catch (err) {
50
+ return false
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Release tags (e.g. "v2.1.0"), highest first. Delegates the version-aware
56
+ * ordering to git itself rather than hand-parsing semver, then filters down
57
+ * to strict "vX.Y.Z" tags - `--sort=-version:refname` alone still leaves in
58
+ * non-release refs (e.g. "vtesting", "v2.0.0-beta") and peeled annotated-tag
59
+ * lines ("refs/tags/v2.0.0^{}").
60
+ */
61
+ function listReleaseTags(repoUrl) {
62
+ const output = execSync(
63
+ 'git ls-remote --tags --sort=-version:refname ' + repoUrl,
64
+ { encoding: 'utf-8' }
65
+ )
66
+
67
+ return output
68
+ .split('\n')
69
+ .map((line) => line.split('\t')[1])
70
+ .filter(Boolean)
71
+ .map((ref) => ref.replace('refs/tags/', ''))
72
+ .filter((tag) => /^v\d+\.\d+\.\d+$/.test(tag))
73
+ }
74
+
75
+ /**
76
+ * The highest release tag present in *both* repositories - used as the
77
+ * fallback when the version-specific tag can't be found in one or both, so
78
+ * scaffolding still lands on a real, matched release rather than develop.
79
+ */
80
+ function getLatestCommonReleaseTag() {
81
+ const infrastructureTags = new Set(listReleaseTags(INFRASTRUCTURE_REPO_URL))
82
+ return (
83
+ listReleaseTags(COUNTRYCONFIG_REPO_URL).find((tag) =>
84
+ infrastructureTags.has(tag)
85
+ ) || null
86
+ )
87
+ }
88
+
89
+ /**
90
+ * A prerelease-shaped own version (e.g. "2.1.0-rc.f5ea803", what npm resolves
91
+ * `@next` to - a build published from every push to a branch) never has a
92
+ * matching release tag, so it's resolved as a branch instead. Its base
93
+ * version (stripped of the "-rc.<sha>" suffix) tells apart two different
94
+ * situations: an RC for a version already being stabilized on its own
95
+ * "release/X.Y.Z" branch (e.g. "2.0.1-rc.*" while a patch release is in
96
+ * progress) versus an RC for a version that hasn't been branched off yet and
97
+ * only exists on develop (e.g. "2.1.0-rc.*" while that release branch hasn't
98
+ * been cut). Scaffold from the release branch when it exists in both
99
+ * repositories, otherwise fall back to develop.
100
+ *
101
+ * Otherwise, the own "X.Y.Z" version - whether resolved via npm's `latest`
102
+ * dist-tag (bare invocation) or an explicit `@X.Y.Z` pin - scaffolds from the
103
+ * matching "vX.Y.Z" tag when it exists in both repositories. If it doesn't
104
+ * (e.g. `latest` lagging behind the repos, or a pin that predates one repo's
105
+ * tagging), fall back to the highest release tag common to both, rather than
106
+ * a mismatched pairing of one tagged repo at that version and another repo
107
+ * at a different release. Exits with an error if no matching release tag
108
+ * exists in both repositories.
109
+ */
110
+ function resolveRef() {
111
+ if (version.includes('-')) {
112
+ const releaseBranch = 'release/' + version.split('-')[0]
113
+ if (
114
+ branchExists(COUNTRYCONFIG_REPO_URL, releaseBranch) &&
115
+ branchExists(INFRASTRUCTURE_REPO_URL, releaseBranch)
116
+ ) {
117
+ return releaseBranch
118
+ }
119
+ return 'develop'
120
+ }
121
+
122
+ const tag = 'v' + version
123
+ if (
124
+ tagExists(COUNTRYCONFIG_REPO_URL, tag) &&
125
+ tagExists(INFRASTRUCTURE_REPO_URL, tag)
126
+ ) {
127
+ return tag
128
+ }
129
+
130
+ const latestCommonTag = getLatestCommonReleaseTag()
131
+ if (latestCommonTag) {
132
+ console.warn(
133
+ '\nWarning: tag "' +
134
+ tag +
135
+ '" was not found in both repositories; falling back to the latest ' +
136
+ 'available release, ' +
137
+ latestCommonTag +
138
+ '.'
139
+ )
140
+ return latestCommonTag
141
+ }
142
+
143
+ console.error(
144
+ '\nError: no matching release tag was found in both the country config and ' +
145
+ 'infrastructure repositories.'
146
+ )
147
+ process.exit(1)
148
+ }
149
+
150
+ function cloneRepository(
151
+ repoUrl,
152
+ ref,
153
+ targetDir,
154
+ { keepHistory = false } = {}
155
+ ) {
156
+ const depthFlag = keepHistory ? '' : '--depth 1 '
157
+ execSync(
158
+ 'git clone ' +
159
+ depthFlag +
160
+ '--branch ' +
161
+ ref +
162
+ ' ' +
163
+ repoUrl +
164
+ ' ' +
165
+ targetDir,
166
+ { stdio: 'inherit' }
167
+ )
168
+
169
+ if (!keepHistory) {
170
+ try {
171
+ fs.rmSync(path.join(targetDir, '.git'), {
172
+ recursive: true,
173
+ force: true
174
+ })
175
+ } catch (err) {
176
+ console.error(
177
+ 'Failed to remove .git directory from ' + targetDir + ':',
178
+ err.message
179
+ )
180
+ process.exit(1)
181
+ }
182
+ return
183
+ }
184
+
185
+ console.log(
186
+ "Replacing 'origin' remote with 'upstream' in " + targetDir + '...'
187
+ )
188
+ execSync('git remote remove origin', {
189
+ cwd: targetDir,
190
+ stdio: 'inherit'
191
+ })
192
+ execSync('git remote add upstream ' + repoUrl, {
193
+ cwd: targetDir,
194
+ stdio: 'inherit'
195
+ })
196
+ }
22
197
 
23
198
  const projectName = process.argv[2]
24
199
 
@@ -33,31 +208,35 @@ const countryconfigDirName = projectName + '-countryconfig'
33
208
  const infrastructureDirName = projectName + '-infrastructure'
34
209
 
35
210
  const countryconfigTargetDir = path.resolve(process.cwd(), countryconfigDirName)
36
- const infrastructureTargetDir = path.resolve(process.cwd(), infrastructureDirName)
211
+ const infrastructureTargetDir = path.resolve(
212
+ process.cwd(),
213
+ infrastructureDirName
214
+ )
37
215
 
38
216
  if (fs.existsSync(countryconfigTargetDir)) {
39
- console.error('Error: Directory "' + countryconfigDirName + '" already exists.')
217
+ console.error(
218
+ 'Error: Directory "' + countryconfigDirName + '" already exists.'
219
+ )
40
220
  process.exit(1)
41
221
  }
42
222
 
43
223
  if (fs.existsSync(infrastructureTargetDir)) {
44
- console.error('Error: Directory "' + infrastructureDirName + '" already exists.')
224
+ console.error(
225
+ 'Error: Directory "' + infrastructureDirName + '" already exists.'
226
+ )
45
227
  process.exit(1)
46
228
  }
47
229
 
48
- console.log('\nScaffolding OpenCRVS country config in ./' + countryconfigDirName + '...\n')
230
+ const ref = resolveRef()
49
231
 
50
- try {
51
- execSync('git clone --depth 1 ' + COUNTRYCONFIG_REPO_URL + ' ' + countryconfigDirName, { stdio: 'inherit' })
52
- } catch (err) {
53
- console.error('Failed to clone the country config repository:', err.message)
54
- process.exit(1)
55
- }
232
+ console.log(
233
+ '\nScaffolding OpenCRVS country config in ./' + countryconfigDirName + '...\n'
234
+ )
56
235
 
57
236
  try {
58
- fs.rmSync(path.join(countryconfigTargetDir, '.git'), { recursive: true, force: true })
237
+ cloneRepository(COUNTRYCONFIG_REPO_URL, ref, countryconfigDirName)
59
238
  } catch (err) {
60
- console.error('Failed to remove .git directory from country config:', err.message)
239
+ console.error('Failed to clone the country config repository:', err.message)
61
240
  process.exit(1)
62
241
  }
63
242
 
@@ -72,25 +251,26 @@ if (fs.existsSync(pkgPath)) {
72
251
  process.exit(1)
73
252
  }
74
253
  } else {
75
- console.warn('Warning: No package.json found in the cloned country config repository. Project name was not updated.')
254
+ console.warn(
255
+ 'Warning: No package.json found in the cloned country config repository. Project name was not updated.'
256
+ )
76
257
  }
77
258
 
78
- console.log('\nScaffolding OpenCRVS infrastructure in ./' + infrastructureDirName + '...\n')
259
+ console.log(
260
+ '\nScaffolding OpenCRVS infrastructure in ./' +
261
+ infrastructureDirName +
262
+ '...\n'
263
+ )
79
264
 
80
265
  try {
81
- execSync('git clone --depth 1 ' + INFRASTRUCTURE_REPO_URL + ' ' + infrastructureDirName, { stdio: 'inherit' })
266
+ cloneRepository(INFRASTRUCTURE_REPO_URL, ref, infrastructureDirName, {
267
+ keepHistory: true
268
+ })
82
269
  } catch (err) {
83
270
  console.error('Failed to clone the infrastructure repository:', err.message)
84
271
  process.exit(1)
85
272
  }
86
273
 
87
- try {
88
- fs.rmSync(path.join(infrastructureTargetDir, '.git'), { recursive: true, force: true })
89
- } catch (err) {
90
- console.error('Failed to remove .git directory from infrastructure:', err.message)
91
- process.exit(1)
92
- }
93
-
94
274
  console.log('\nDone! Your project has been set up in two directories:\n')
95
275
  console.log(' ./' + countryconfigDirName + ' -- country configuration')
96
276
  console.log(' ./' + infrastructureDirName + ' -- server infrastructure\n')
@@ -100,4 +280,9 @@ console.log(' git init')
100
280
  console.log(' npm install\n')
101
281
  console.log('To get started with the infrastructure:\n')
102
282
  console.log(' cd ' + infrastructureDirName)
103
- console.log(' git init\n')
283
+ console.log(' git remote add origin <your-infrastructure-repo-url>')
284
+ console.log(' git push -u origin ' + ref + '\n')
285
+ console.log(
286
+ 'The "upstream" remote points at the official infrastructure repository, ' +
287
+ 'so you can pull future releases with `git fetch upstream`.\n'
288
+ )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencrvs/create-countryconfig",
3
- "version": "2.0.1-rc.fed4de8",
3
+ "version": "2.0.2-rc.0534cee",
4
4
  "description": "Scaffold a new OpenCRVS country configuration",
5
5
  "bin": {
6
6
  "create-countryconfig": "./index.js"