1
+ #! /bin/bash
2
+ # @file functions
3
+ # @brief CI and local package release "automation" functions.
4
+
5
+ #
6
+ # @description Parse and return a version value from a "package.json" file
7
+ #
8
+ # @see [shdoc](https://github.com/reconquest/shdoc)
9
+ # @example
10
+ # packageVersion "<PATH>/package.json"
11
+ packageVersion () {
12
+ local package_json_file=$1
13
+ local version=" "
14
+ while read a b ; do
15
+ [ " $a " = ' "version":' ] && { b=" ${b% \" * } " ; version=" ${b# \" } " ; break ; }
16
+ done < $package_json_file
17
+ echo $version
18
+ }
19
+
20
+ #
21
+ # @description $PKG_ROOT environment variable check. Should be a string
22
+ # with a root path of the package
23
+ #
24
+ # @see $PKG_ROOT
25
+ checkPkgRoot () {
26
+ if [ -z " $PKG_ROOT " ]
27
+ then
28
+ PKG_ROOT=$1
29
+ if [ -z " $PKG_ROOT " ]
30
+ then
31
+ PKG_ROOT=" ."
32
+ fi
33
+ fi
34
+ }
35
+
36
+ #
37
+ # @description Replace .env (default) file content with $PKG_ROOT variable value
38
+ #
39
+ # @see $PKG_ROOT
40
+ fixEnvFile () {
41
+ # $PKG_ROOT environment variable check
42
+ checkPkgRoot $1
43
+
44
+ # Fix env (default) file with correct value
45
+ # for environment variables
46
+ if [ -f " $PKG_ROOT /.env" ]
47
+ then
48
+ echo " [FIX .ENV] Replaced $( cat " $PKG_ROOT /.env" ) to => REPOSITORY_ROOT=."
49
+ echo " REPOSITORY_ROOT=." > " $PKG_ROOT /.env"
50
+ fi
51
+ }
52
+
53
+ # @description Add github actions state and output variables to be handled on .yml workflow files
54
+ #
55
+ # @see $GITHUB_OUTPUT
56
+ # @see [Deprecating save-state and set-output commands](https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands)
57
+ # @see [Github Actions: Output parameter](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter)
58
+ githubActionsOutputs () {
59
+ # PS: CURRENT_TAG and COMMIT_MESSAGE are handled here as "global/environment" variables
60
+ CURRENT_TAG=$( git describe --tags $( git rev-list --tags --max-count=1) )
61
+ COMMIT_MESSAGE=$( git log -1 --pretty=%B)
62
+
63
+ echo " [GITHUB VARIABLES] Commit => $COMMIT_MESSAGE "
64
+
65
+ # Use the format {name}={value} instead of ::set-output
66
+ echo " TAG=$CURRENT_TAG " >> $GITHUB_OUTPUT
67
+ echo " COMMIT_MESSAGE=$COMMIT_MESSAGE " >> $GITHUB_OUTPUT
68
+ }
69
+
70
+ # @description Copy all content of the package folder to the ROOT dir
71
+ #
72
+ # @see [shdoc](https://github.com/reconquest/shdoc)
73
+ # @example
74
+ # # From the root folder, with "Packages/<PACKAGE_NAME>"
75
+ # copyPackagesContent
76
+ # # result: Copy "Packages/<PACKAGE_NAME>/*.*" to ROOT/
77
+ copyPackagesContent () {
78
+ shopt -s extglob dotglob
79
+
80
+ cp -rvf " Packages/$PKG_NAME /." " $PKG_ROOT /"
81
+ rm -rf ./Packages
82
+ }
83
+
84
+ # TODO: Move this common function to another script file in order to reuse (e.g .github/scripts/common.sh)
85
+ #
86
+ # @description Rename invalid package directories to be "untracked" by game engine, adding a "~" suffix
87
+ # (e.g "Samples" => "Samples~", "Documentation" => "Documentation~")
88
+ #
89
+ # @see $PKG_ROOT
90
+ # @see [shdoc](https://github.com/reconquest/shdoc)
91
+ renameInvalidDirs () {
92
+ # $PKG_ROOT environment variable check
93
+ checkPkgRoot $1
94
+
95
+ if [ $PKG_ROOT = " ./" ]
96
+ then
97
+ echo " [RENAME DIRECTORIES] [Error] The \$ PKG_ROOT => '$PKG_ROOT ' should be just '.' for current directory."
98
+ return 1
99
+ fi
100
+
101
+ echo " [RENAME DIRECTORIES] Package Root: $PKG_ROOT /"
102
+
103
+ chmod -R 777 " $PKG_ROOT /"
104
+
105
+ # Rename UPM special directories with suffix "~"
106
+ if [ -d " $PKG_ROOT /Samples" ] && [ ! -d " $PKG_ROOT /Samples~" ]
107
+ then
108
+ # PS: Replaced "mv" to "copy" + "remove" of Samples~ dir, because sometimes
109
+ # shows the error Permission Denied. Specially if Samples
110
+ # have several sub-directories
111
+ mkdir -p " $PKG_ROOT /Samples~"
112
+ cp -R " $PKG_ROOT /Samples/." " $PKG_ROOT /Samples~/"
113
+
114
+ rm -rf " $PKG_ROOT /Samples"
115
+ rm -f " $PKG_ROOT /Samples.meta"
116
+
117
+ echo " [RENAMED] Samples => $PKG_ROOT /Samples~"
118
+ fi
119
+ if [ -d " $PKG_ROOT /Documentation" ] && [ ! -d " $PKG_ROOT /Documentation~" ]
120
+ then
121
+ mv " $PKG_ROOT /Documentation" " $PKG_ROOT /Documentation~"
122
+ rm -f " $PKG_ROOT /Documentation.meta"
123
+
124
+ echo " [RENAMED] Documentation => $PKG_ROOT /Documentation~"
125
+ fi
126
+ }
127
+
128
+ #
129
+ # @description Commit with a new version of the package and push the $PKG_BRANCH
130
+ # new orphan branch (usually "upm" branch)
131
+ #
132
+ # @see $PKG_BRANCH
133
+ # @see renameInvalidDirs()
134
+ # @see fixEnvFile()
135
+ commitAndPush () {
136
+ # Incrementing LAST_RELEASE_TAG+1.
137
+ # Keep here just to store the history, and if need this to the future/others repositories
138
+ #
139
+ # PS: Keep in mind that not always you would like to increment the git tag version (e.g rewriting with force an existent git tag)
140
+ # [[ "$LAST_RELEASE_TAG" =~ (.*[^0-9])([0-9]+)$ ]] && LAST_RELEASE_TAG="${BASH_REMATCH[1]}$((${BASH_REMATCH[2]} + 1))";
141
+
142
+ local release_version=$( packageVersion " ./package.json" )
143
+
144
+ echo " [COMMIT AND PUSH] New version: $release_version "
145
+
146
+ renameInvalidDirs
147
+
148
+ git config --global user.name ' github-bot'
149
+ git config --global user.email
' [email protected] '
150
+ git add .
151
+ git commit --allow-empty -am " $COMMIT_MESSAGE "
152
+
153
+ echo $release_version > VERSION.md~
154
+
155
+ # .env (default) file path fix
156
+ fixEnvFile
157
+
158
+ git add VERSION.md~
159
+ git commit -am " fix: Samples => Samples~ and commit a new version: $release_version "
160
+ git push -f -u origin " $PKG_BRANCH "
161
+ }
162
+
163
+ # TODO: Move this function to another script file (e.g .github/scripts/local.sh)
164
+ #
165
+ # @description Copy a list of files and dirs from the ROOT to the package folder
166
+ #
167
+ # @arg $1 string A path configured as "$repository_root" local variable to be used as an origin
168
+ # path to copy content into package dir
169
+ # @arg $2 string A path configured as "$PKG_ROOT" environment variable to be used as
170
+ # root path of the package
171
+ #
172
+ # @see $PKG_ROOT
173
+ # @see [Exit the Bash Script if a Certain Condition Occurs](https://itslinuxfoss.com/exit-bash-script-if-certain-condition-occurs)
174
+ # @see [How to Check if a File or Directory Exists in Bash](https://linuxize.com/post/bash-check-if-file-exists)
175
+ copyFilesForPublish () {
176
+ local repository_root=$1
177
+
178
+ # $PKG_ROOT environment variable check
179
+ checkPkgRoot $2
180
+ local pkg_root_full_path=$( realpath $PKG_ROOT )
181
+
182
+ if [ -z " $repository_root " ]
183
+ then
184
+ echo " [COPY FILES] The parameter \$ 1 => \$ repository_root is required: '$repository_root '"
185
+ return 1
186
+ else
187
+ if [[ " $repository_root " =~ \. $ ]]
188
+ then
189
+ repository_root=" $repository_root /"
190
+ fi
191
+ fi
192
+
193
+ if [[ $repository_root == $pkg_root_full_path ]]
194
+ then
195
+ echo " [COPY FILES] Cannot copy a directory FROM: \$ repository_root => '$repository_root ' to \$ PKG_ROOT => '$pkg_root_full_path ', into itself"
196
+ return 1
197
+ fi
198
+
199
+ chmod -R 777 " $PKG_ROOT /"
200
+
201
+ echo " [COPY FILES] From \$ repository_root: '$( realpath $repository_root ) ', to => \$ PKG_ROOT: '$pkg_root_full_path '"
202
+
203
+ local files_copy=(README.md README.md.meta LICENSE LICENSE.meta Images Images.meta)
204
+ for file_name in " ${files_copy[@]} "
205
+ do
206
+ if [[ -f " $repository_root /$file_name " && ! -f " $PKG_ROOT /$file_name " ]] || [[ -d " $repository_root /$file_name " && ! -d " $PKG_ROOT /$file_name " ]]
207
+ then
208
+ cp -rf " $repository_root /$file_name " " $PKG_ROOT /$file_name "
209
+ echo " [COPY FILES] Copied: $PKG_ROOT /$file_name "
210
+ fi
211
+ done
212
+ }
213
+
214
+ # TODO: [Feature] Use this function to loop over all packages and do all operations (copy files, rename and publish)
215
+ # @see checkPkgRoot
216
+ # @see [How do you store a list of directories into an array in Bash?](https://stackoverflow.com/a/4495304)
217
+ fetchPackages () {
218
+ local packages_root=$1
219
+ checkPkgRoot
220
+
221
+ # PS: "<PATH>/*/" is a glob that list only directories
222
+ if [ -z $packages_root ]
223
+ then
224
+ packages_root=(
225
+ $PKG_ROOT /Packages/* /
226
+ )
227
+ elif [ -d $packages_root ]
228
+ then
229
+ packages_root=(
230
+ $packages_root /* /
231
+ )
232
+ fi
233
+
234
+ for package_path in " ${packages_root[@]} "
235
+ do
236
+ echo " [FETCH PACKAGES] Package: '$package_path '"
237
+ done
238
+ }
239
+
240
+ # TODO: Move this function to another script file (e.g .github/scripts/local.sh)
241
+ # TODO: Move common functions dependencies to another script file in order to reuse (e.g .github/scripts/common.sh)
242
+ #
243
+ # @description Automate all actions required before PUBLISH a package in a remote registry
244
+ #
245
+ # @arg $1 string A path configured as "$repository_root" local variable to be used as an origin
246
+ # path to copy content into package dir
247
+ # @arg $2 string A path configured as "$PKG_ROOT" environment variable to be used as
248
+ # root path of the package
249
+ #
250
+ # @arg $3 string A flag configured as "$PUBLISH_FORCE" environment variable to force
251
+ # publish from "./" root path (usually when publishing packages from a local repo)
252
+ #
253
+ # @see $PKG_ROOT
254
+ # @see $PUBLISH_FORCE
255
+ # @see renameInvalidDirs($PKG_ROOT)
256
+ # @see copyFilesForPublish($1)
257
+ # @see [Using Boolean Variables in Shell Scripts](https://tecadmin.net/boolean-variable-in-shell-script)
258
+ localBeforePublish () {
259
+ local repository_root=$1
260
+ local publish_forced=' false'
261
+
262
+ # Check if publish "force" is true
263
+ if [ -z " $PUBLISH_FORCE " ]
264
+ then
265
+ PUBLISH_FORCE=$3
266
+ if [ -z " $PUBLISH_FORCE " ]
267
+ then
268
+ PUBLISH_FORCE=0
269
+ fi
270
+ fi
271
+
272
+ if [ $PUBLISH_FORCE -eq 1 ]
273
+ then
274
+ publish_forced=' true'
275
+ fi
276
+
277
+ if [ -d $repository_root ] && [[ $repository_root != " ./" && $repository_root != " ." || $PUBLISH_FORCE -eq 1 ]]
278
+ then
279
+
280
+ echo " [PUBLISH: BEFORE/PRE] Forced => '$publish_forced '"
281
+
282
+ # $PKG_ROOT environment variable check
283
+ checkPkgRoot $2
284
+
285
+ renameInvalidDirs $PKG_ROOT
286
+ copyFilesForPublish $repository_root
287
+ else
288
+ echo " [PUBLISH: BEFORE/PRE] [Skip] Bypass package preparation because \$ 1 : \$ repository_root => '$repository_root ' is invalid"
289
+ fi
290
+ }
291
+
292
+ # TODO: Move this function to another script file (e.g .github/scripts/local.sh)
293
+ #
294
+ # @description PUBLISH a package in a remote registry. Usually used inside of a npm script
295
+ #
296
+ # @arg $1 string Overrides the $PKG_ROOT environment variable with a path to a package
297
+ #
298
+ # @see $PKG_ROOT
299
+ localPublish () {
300
+ # $PKG_ROOT environment variable check
301
+ checkPkgRoot $1
302
+
303
+ cd $PKG_ROOT
304
+
305
+ # Install dev dependencies if weren't installed yet
306
+ if [ ! -d " ./node_modules" ]
307
+ then
308
+ npm i
309
+ fi
310
+ npm run package:prepare && npm publish
311
+ }
312
+
313
+ run () {
314
+ if [ $1 == " push" ]
315
+ then
316
+ commitAndPush
317
+ elif [ $1 == " movePackagesFolder" ]
318
+ then
319
+ copyPackagesContent
320
+ elif [ $1 == " githubActionsVariables" ]
321
+ then
322
+ githubActionsOutputs
323
+ elif [ $1 == " fetchPackages" ]
324
+ then
325
+ fetchPackages $2
326
+ elif [ $1 == " copyFilesForPublish" ]
327
+ then
328
+ copyFilesForPublish $2 $3
329
+ elif [ $1 == " fixEnvFile" ]
330
+ then
331
+ fixEnvFile $2
332
+ elif [ $1 == " renameInvalidDirs" ]
333
+ then
334
+ renameInvalidDirs $2
335
+ elif [ $1 == " localBeforePublish" ]
336
+ then
337
+ localBeforePublish $2
338
+ elif [ $1 == " localPublish" ]
339
+ then
340
+ localPublish $2
341
+ else
342
+ echo " [ERROR] INVALID SCRIPT OPERATION"
343
+ exit 1
344
+ fi
345
+ }
346
+
347
+ run $1 $2 $3
0 commit comments