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