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" ]
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+ if [ ! -d " $PKG_ROOT /Samples~" ]
112+ then
113+ mkdir -p " $PKG_ROOT /Samples~"
114+ fi
115+
116+ cp -Rf " $PKG_ROOT /Samples/." " $PKG_ROOT /Samples~/"
117+
118+ rm -rf " $PKG_ROOT /Samples"
119+ rm -f " $PKG_ROOT /Samples.meta"
120+
121+ echo " [RENAMED] Samples => $PKG_ROOT /Samples~"
122+ fi
123+ if [ -d " $PKG_ROOT /Documentation" ] && [ ! -d " $PKG_ROOT /Documentation~" ]
124+ then
125+ mv " $PKG_ROOT /Documentation" " $PKG_ROOT /Documentation~"
126+ rm -f " $PKG_ROOT /Documentation.meta"
127+
128+ echo " [RENAMED] Documentation => $PKG_ROOT /Documentation~"
129+ fi
130+ }
131+
132+ #
133+ # @description Commit with a new version of the package and push the $PKG_BRANCH
134+ # new orphan branch (usually "upm" branch)
135+ #
136+ # @see $PKG_BRANCH
137+ # @see renameInvalidDirs()
138+ # @see fixEnvFile()
139+ commitAndPush () {
140+ # Incrementing LAST_RELEASE_TAG+1.
141+ # Keep here just to store the history, and if need this to the future/others repositories
142+ #
143+ # 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)
144+ # [[ "$LAST_RELEASE_TAG" =~ (.*[^0-9])([0-9]+)$ ]] && LAST_RELEASE_TAG="${BASH_REMATCH[1]}$((${BASH_REMATCH[2]} + 1))";
145+
146+ local release_version=$( packageVersion " ./package.json" )
147+
148+ echo " [COMMIT AND PUSH] New version: $release_version "
149+
150+ renameInvalidDirs
151+
152+ git config --global user.name ' github-bot'
153+ git config --global user.email
' [email protected] ' 154+ git add .
155+ git commit --allow-empty -am " $COMMIT_MESSAGE "
156+
157+ echo $release_version > VERSION.md~
158+
159+ # .env (default) file path fix
160+ fixEnvFile
161+
162+ git add VERSION.md~
163+ git commit -am " fix: Samples => Samples~ and commit a new version: $release_version "
164+ git push -f -u origin " $PKG_BRANCH "
165+ }
166+
167+ # TODO: Move this function to another script file (e.g .github/scripts/local.sh)
168+ #
169+ # @description Copy a list of files and dirs from the ROOT to the package folder
170+ #
171+ # @arg $1 string A path configured as "$repository_root" local variable to be used as an origin
172+ # path to copy content into package dir
173+ # @arg $2 string A path configured as "$PKG_ROOT" environment variable to be used as
174+ # root path of the package
175+ #
176+ # @see $PKG_ROOT
177+ # @see [Exit the Bash Script if a Certain Condition Occurs](https://itslinuxfoss.com/exit-bash-script-if-certain-condition-occurs)
178+ # @see [How to Check if a File or Directory Exists in Bash](https://linuxize.com/post/bash-check-if-file-exists)
179+ copyFilesForPublish () {
180+ local repository_root=$1
181+
182+ # $PKG_ROOT environment variable check
183+ checkPkgRoot $2
184+ local pkg_root_full_path=$( realpath $PKG_ROOT )
185+
186+ if [ -z " $repository_root " ]
187+ then
188+ echo " [COPY FILES] The parameter \$ 1 => \$ repository_root is required: '$repository_root '"
189+ return 1
190+ else
191+ if [[ " $repository_root " =~ \. $ ]]
192+ then
193+ repository_root=" $repository_root /"
194+ fi
195+ fi
196+
197+ if [[ $repository_root == $pkg_root_full_path ]]
198+ then
199+ echo " [COPY FILES] Cannot copy a directory FROM: \$ repository_root => '$repository_root ' to \$ PKG_ROOT => '$pkg_root_full_path ', into itself"
200+ return 1
201+ fi
202+
203+ chmod -R 777 " $PKG_ROOT /"
204+
205+ echo " [COPY FILES] From \$ repository_root: '$( realpath $repository_root ) ', to => \$ PKG_ROOT: '$pkg_root_full_path '"
206+
207+ local files_copy=(README.md README.md.meta LICENSE LICENSE.meta Images Images.meta)
208+ for file_name in " ${files_copy[@]} "
209+ do
210+ if [[ -f " $repository_root /$file_name " && ! -f " $PKG_ROOT /$file_name " ]] || [[ -d " $repository_root /$file_name " && ! -d " $PKG_ROOT /$file_name " ]]
211+ then
212+ cp -rf " $repository_root /$file_name " " $PKG_ROOT /$file_name "
213+ echo " [COPY FILES] Copied: $PKG_ROOT /$file_name "
214+ fi
215+ done
216+ }
217+
218+ # TODO: [Feature] Use this function to loop over all packages and do all operations (copy files, rename and publish)
219+ # @see checkPkgRoot
220+ # @see [How do you store a list of directories into an array in Bash?](https://stackoverflow.com/a/4495304)
221+ fetchPackages () {
222+ local packages_root=$1
223+ checkPkgRoot
224+
225+ # PS: "<PATH>/*/" is a glob that list only directories
226+ if [ -z $packages_root ]
227+ then
228+ packages_root=(
229+ $PKG_ROOT /Packages/* /
230+ )
231+ elif [ -d $packages_root ]
232+ then
233+ packages_root=(
234+ $packages_root /* /
235+ )
236+ fi
237+
238+ for package_path in " ${packages_root[@]} "
239+ do
240+ echo " [FETCH PACKAGES] Package: '$package_path '"
241+ done
242+ }
243+
244+ # TODO: Move this function to another script file (e.g .github/scripts/local.sh)
245+ # TODO: Move common functions dependencies to another script file in order to reuse (e.g .github/scripts/common.sh)
246+ #
247+ # @description Automate all actions required before PUBLISH a package in a remote registry
248+ #
249+ # @arg $1 string A path configured as "$repository_root" local variable to be used as an origin
250+ # path to copy content into package dir
251+ # @arg $2 string A path configured as "$PKG_ROOT" environment variable to be used as
252+ # root path of the package
253+ #
254+ # @arg $3 string A flag configured as "$PUBLISH_FORCE" environment variable to force
255+ # publish from "./" root path (usually when publishing packages from a local repo)
256+ #
257+ # @see $PKG_ROOT
258+ # @see $PUBLISH_FORCE
259+ # @see renameInvalidDirs($PKG_ROOT)
260+ # @see copyFilesForPublish($1)
261+ # @see [Using Boolean Variables in Shell Scripts](https://tecadmin.net/boolean-variable-in-shell-script)
262+ localBeforePublish () {
263+ local repository_root=$1
264+ local publish_forced=' false'
265+
266+ # Check if publish "force" is true
267+ if [ -z " $PUBLISH_FORCE " ]
268+ then
269+ PUBLISH_FORCE=$3
270+ if [ -z " $PUBLISH_FORCE " ]
271+ then
272+ PUBLISH_FORCE=0
273+ fi
274+ fi
275+
276+ if [ $PUBLISH_FORCE -eq 1 ]
277+ then
278+ publish_forced=' true'
279+ fi
280+
281+ if [ -d $repository_root ] && [[ $repository_root != " ./" && $repository_root != " ." || $PUBLISH_FORCE -eq 1 ]]
282+ then
283+
284+ echo " [PUBLISH: BEFORE/PRE] Forced => '$publish_forced '"
285+
286+ # $PKG_ROOT environment variable check
287+ checkPkgRoot $2
288+
289+ renameInvalidDirs $PKG_ROOT
290+ copyFilesForPublish $repository_root
291+ else
292+ echo " [PUBLISH: BEFORE/PRE] [Skip] Bypass package preparation because \$ 1 : \$ repository_root => '$repository_root ' is invalid"
293+ fi
294+ }
295+
296+ # TODO: Move this function to another script file (e.g .github/scripts/local.sh)
297+ #
298+ # @description PUBLISH a package in a remote registry. Usually used inside of a npm script
299+ #
300+ # @arg $1 string Overrides the $PKG_ROOT environment variable with a path to a package
301+ #
302+ # @see $PKG_ROOT
303+ localPublish () {
304+ # $PKG_ROOT environment variable check
305+ checkPkgRoot $1
306+
307+ cd $PKG_ROOT
308+
309+ # Install dev dependencies if weren't installed yet
310+ if [ ! -d " ./node_modules" ]
311+ then
312+ npm i
313+ fi
314+ npm run package:prepare && npm publish
315+ }
316+
317+ run () {
318+ if [ $1 == " push" ]
319+ then
320+ commitAndPush
321+ elif [ $1 == " movePackagesFolder" ]
322+ then
323+ copyPackagesContent
324+ elif [ $1 == " githubActionsVariables" ]
325+ then
326+ githubActionsOutputs
327+ elif [ $1 == " fetchPackages" ]
328+ then
329+ fetchPackages $2
330+ elif [ $1 == " copyFilesForPublish" ]
331+ then
332+ copyFilesForPublish $2 $3
333+ elif [ $1 == " fixEnvFile" ]
334+ then
335+ fixEnvFile $2
336+ elif [ $1 == " renameInvalidDirs" ]
337+ then
338+ renameInvalidDirs $2
339+ elif [ $1 == " localBeforePublish" ]
340+ then
341+ localBeforePublish $2
342+ elif [ $1 == " localPublish" ]
343+ then
344+ localPublish $2
345+ else
346+ echo " [ERROR] INVALID SCRIPT OPERATION"
347+ exit 1
348+ fi
349+ }
350+
351+ run $1 $2 $3
0 commit comments