Skip to content

Commit 23a6f14

Browse files
authored
Merge pull request #24 from AlexAtkinson/feature/mono_repo_safety
Feature/mono repo safety
2 parents fd9bb4e + b929d79 commit 23a6f14

File tree

6 files changed

+308
-27
lines changed

6 files changed

+308
-27
lines changed

README.md

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ This is accomplished by counting the merges of branches matching the [naming sch
2222
2323
## Recent Changes
2424

25+
- 1.0.0: (non-breaking) Addition of support for mono-repos. IE: Discretely version specific directories.
26+
- NOTE: Github, Jira, etc., were designed to host one product per repo/project. DO NOT create new mono-repo projects unless you're specifically tooling out to support them well.
2527
- 0.3.1: Update the checkout action version to v4.
2628
- 0.3.0: Bring back the unshallowing, which ensures the full git log is available.
2729
- TODO: Adjust scripts to use `git log --remotes` to avoid unshallowing large repos.
@@ -56,6 +58,28 @@ git push --set-upstream origin fix/not-a-feature
5658
# THEN: Click the link to create a PR & merge it</pre></dd>
5759
</dl>
5860

61+
### Inputs
62+
63+
Note: Only required for setting up mono-repo versioning.
64+
65+
<dl>
66+
<dt>mono-repo-product-name: [string]</dt>
67+
<dd>Enables mono-repo mode. The product name to match against.<br>
68+
Eg: 'bob', would match the tags like 'bob_1.2.3'.<br>
69+
<i>Required:</i> if mono-repo-mode: true<br>
70+
<i>Default:</i> ''</dd>
71+
<dt>mono-repo-product-path: [string]</dt>
72+
<dd>The path to the product.<br>
73+
Eg: path/to/bob<br>
74+
<i>Required:</i> if mono-repo-mode: true<br>
75+
<i>Default:</i> ''</dd>
76+
<dt>force-patch-increment: [bool]</dt>
77+
<dd>Forces a PATCH increment if no other increment detected.<br>
78+
(Intended for development purposes only.)<br>
79+
<i>Required:</i> false<br>
80+
<i>Default:</i> false</dd>
81+
</dl>
82+
5983
### Outputs
6084

6185
<dl>
@@ -84,14 +108,22 @@ Below is a valid workflow utilizing this action. If you wanted to extend it to d
84108
- uses: actions/checkout@v3
85109
- name: Run GitOps Automatic Versioning Action
86110
id: gitops-autover
87-
uses: AlexAtkinson/github-action-gitops-autover@0.3.0
111+
uses: AlexAtkinson/github-action-gitops-autover@0.3.1
88112
- name: Verify Outputs
89113
run: |
90114
NEW_VERSION=${{ steps.gitops-autover.outputs.new-version }}
91115
echo "new-version: $NEW_VERSION"
92116
PREVIOUS_VERSION=${{ steps.gitops-autover.outputs.previous-version }}
93117
echo "previous-version: $PREVIOUS_VERSION"
94118

119+
To make use of the mono-repo support, simply add a block for the director you wish to version.
120+
121+
- name: Run GitOps Automatic Versioning Action
122+
id: gitops-autover
123+
uses: AlexAtkinson/github-action-gitops-autover@0.3.1
124+
with:
125+
mono-repo-product-name: bob
126+
95127
This results in outputs like:
96128

97129
_major:_
@@ -151,7 +183,7 @@ Additionally, this repo uses its own action for versioning, so feel free to inve
151183
echo "PRODUCT_NAME_LOWER=$PRODUCT_NAME_LOWER" >> $GITHUB_OUTPUT
152184
- name: GitOps Automatic Versioning
153185
id: gitops-autover
154-
uses: AlexAtkinson/github-action-gitops-autover@0.3.0
186+
uses: AlexAtkinson/github-action-gitops-autover@0.3.1
155187
build:
156188
name: "Build"
157189
runs-on: ubuntu-latest
@@ -265,5 +297,5 @@ For those interested, here's some pseudo code:
265297
PRs are welcome.
266298

267299
- input(s): iteration-branches (map) - inform MINOR and PATCH incrementing branch name patterns.
268-
- input(s): mono-mode (bool) - version subdirs discretely
269-
- ~~CAN'T DO~~: DONE: unshallow from last version tag to latest commit to... Seems a limitation of (git at first glance). See the [Checkout From Tag](https://github.com/marketplace/actions/checkout-from-tag) action.
300+
- DONE: input(s): mono-mode (bool) - version subdirs discretely
301+
- UNDONE-CAN'T DO: ~~CAN'T DO~~: ~~DONE:~~ unshallow from last version tag to latest commit to... Seems a limitation of (git at first glance). See the [Checkout From Tag](https://github.com/marketplace/actions/checkout-from-tag) action.

action.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ inputs:
1313
description: "Forces a PATCH increment if no other increment detected. NOTE: This is intended for development purposes only."
1414
required: false
1515
default: 'false'
16+
mono-repo-product-name:
17+
description: "Enables mono-repo mode. The product name to match against. EG: 'bob', match the tags like 'bob_1.2.3'."
18+
required: false
19+
default: ''
20+
mono-repo-product-path:
21+
description: "The path to the product. IE: 'path/to/bob'. Required if 'mono-repo-mode' is enabled."
22+
required: false
23+
default: ''
1624
outputs:
1725
new-version:
1826
description: "New Version"
@@ -41,8 +49,13 @@ runs:
4149
run: |
4250
cd $GITHUB_WORKSPACE
4351
opt=''
44-
[[ "${{ inputs.force-re-evaluate }}" == 'true' ]] && opt='-f'
45-
[[ "${{ inputs.force-patch-increment }}" == 'true' ]] && opt='-p'
52+
[[ "${{ inputs.force-re-evaluate }}" == 'true' ]] && opt='$opt -f'
53+
[[ "${{ inputs.force-patch-increment }}" == 'true' ]] && opt='$opt -p'
54+
if [[ -z ${{ inputs.mono-repo-product-name }} ]]; then
55+
echo -e "ERROR: 571 - mono-repo-product-name must be set and NOT null!"
56+
exit 1 || true
57+
fi
58+
[[ -n "${{ inputs.mono-repo-product-name }}" ]] && opt='$opt -n ${{ inputs.mono-repo-product-name }}'
4659
new_version="$(${{ github.action_path }}/scripts/detectNewVersion.sh $opt)" || true
4760
echo "new-version=$new_version" | tee $GITHUB_OUTPUT
4861
if [[ "$new_version" =~ "520" ]]; then

scripts/detectNewVersion.sh

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ NAME
2929
${0##*/}
3030
3131
SYNOPSIS
32-
${0##*/} [-hv]
32+
${0##*/} [-hefpnd]
3333
3434
DESCRIPTION
3535
Detects the new version for the repository by analyzing the gitflow branch history since the
@@ -47,6 +47,12 @@ DESCRIPTION
4747
-p Increments PATCH version on _every_ run.
4848
WARN: This is intended development use only.
4949
50+
-n Enables mono-repo mode allowing the product name to match against tags.
51+
EG: 'bob' would match tags like 'bob_1.2.3'.
52+
TIP: dir names and product names should match. This arg exists in case they do not.
53+
54+
-d The directory of the product to version. EG: 'path/to/bob'.
55+
5056
EXAMPLES
5157
The following detects the new version for the repo.
5258
@@ -75,7 +81,7 @@ fi
7581
# --------------------------------------------------------------------------------------------------
7682

7783
OPTIND=1
78-
while getopts "he:vfp" opt; do
84+
while getopts "he:vfpn:d:" opt; do
7985
case $opt in
8086
h)
8187
printHelp
@@ -95,6 +101,17 @@ while getopts "he:vfp" opt; do
95101
p)
96102
arg_p='set'
97103
;;
104+
n)
105+
arg_n='set'
106+
arg_n_val="$OPTARG"
107+
arg_opts="$arg_opts -n $OPTARG"
108+
;;
109+
d)
110+
arg_d='set'
111+
arg_d_val="$OPTARG"
112+
arg_d_opt="--full-history"
113+
arg_opts="$arg_opts -d $OPTARG"
114+
;;
98115
*)
99116
echo -e "\e[01;31mERROR\e[00m: 570 - Invalid argument!"
100117
printHelp
@@ -118,13 +135,13 @@ tsCmd='date --utc +%FT%T.%3NZ'
118135
relative_path="$(dirname "${BASH_SOURCE[0]}")"
119136
dir="$(realpath "${relative_path}")"
120137

121-
lastVersion=$(/usr/bin/env bash -c "${dir}/detectPreviousVersion.sh")
122-
lastVersionMajor=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -p major $lastVersion")
123-
lastVersionMinor=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -p minor $lastVersion")
124-
lastVersionPatch=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -p patch $lastVersion")
125-
lastVersionCommitHash=$(/usr/bin/env bash -c "${dir}/detectPreviousVersion.sh -c")
138+
lastVersion=$(/usr/bin/env bash -c "${dir}/detectPreviousVersion.sh -9 $arg_opts")
139+
lastVersionMajor=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -p major $lastVersion $arg_opts")
140+
lastVersionMinor=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -p minor $lastVersion $arg_opts")
141+
lastVersionPatch=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -p patch $lastVersion $arg_opts")
142+
lastVersionCommitHash=$(/usr/bin/env bash -c "${dir}/detectPreviousVersion.sh -9 -c $arg_opts")
126143
lastCommitHash=$(git rev-parse HEAD)
127-
firstCommitHash=$(git rev-list --max-parents=0 HEAD)
144+
firstCommitHash=$(git rev-list --max-parents=0 HEAD | tail -n 1)
128145

129146
ci_name=$("${dir}/detect-ci.sh")
130147
origin=$(git config --get remote.origin.url)
@@ -169,20 +186,20 @@ if [[ -n $arg_e ]]; then
169186
fi
170187
fi
171188

172-
git log --pretty=oneline "$lastVersionCommitHash".."$lastCommitHash" | grep '+semver' | grep -q 'major\|breaking' && incrementMajor='true'
189+
git log $arg_d_opt --pretty=oneline "$lastVersionCommitHash".."$lastCommitHash" $arg_d_val | grep '+semver' | grep -q 'major\|breaking' && incrementMajor='true'
173190

174191
if [[ $incrementMajor != 'true' ]]; then
175192
IFS=$'\r\n'
176193
if [[ -n $arg_f ]]; then
177-
for i in $(git log --pretty=oneline "${firstCommitHash}".."${lastCommitHash}" | awk -v s="$merge_string" -v c="$column" '$0 ~ s {print $c}' | awk -v f="$field" -F'/' '{print $f}' | tr -d "'" | grep -i '^enhancement$\|^feature$\|^fix$\|^hotfix$\|^bugfix$\|^ops$' | awk -F '\r' '{print $1}' | sort | uniq -c | sort -nr) ; do
194+
for i in $(git log $arg_d_opt --pretty=oneline "${firstCommitHash}".."${lastCommitHash}" $arg_d_val | awk -v s="$merge_string" -v c="$column" '$0 ~ s {print $c}' | awk -v f="$field" -F'/' '{print $f}' | tr -d "'" | grep -i '^enhancement$\|^feature$\|^fix$\|^hotfix$\|^bugfix$\|^ops$' | awk -F '\r' '{print $1}' | sort | uniq -c | sort -nr) ; do
178195
varname=$(echo "$i" | awk '{print $2}')
179196
varname=${varname,,}
180197
value=$(echo "$i" | awk '{print $1}')
181198
value=${value,,}
182199
declare count_"$varname"="$value"
183200
done
184201
else
185-
for i in $(git log --pretty=oneline "${lastVersionCommitHash}".."${lastCommitHash}" | awk -v s="$merge_string" -v c="$column" '$0 ~ s {print $c}' | awk -v f="$field" -F'/' '{print $f}' | tr -d "'" | grep -i '^enhancement$\|^feature$\|^fix$\|^hotfix$\|^bugfix$\|^ops$' | awk -F '\r' '{print $1}' | sort | uniq -c | sort -nr) ; do
202+
for i in $(git log $arg_d_opt --pretty=oneline "${lastVersionCommitHash}".."${lastCommitHash}" $arg_d_val | awk -v s="$merge_string" -v c="$column" '$0 ~ s {print $c}' | awk -v f="$field" -F'/' '{print $f}' | tr -d "'" | grep -i '^enhancement$\|^feature$\|^fix$\|^hotfix$\|^bugfix$\|^ops$' | awk -F '\r' '{print $1}' | sort | uniq -c | sort -nr) ; do
186203
varname=$(echo "$i" | awk '{print $2}')
187204
varname=${varname,,}
188205
value=$(echo "$i" | awk '{print $1}')
@@ -236,12 +253,13 @@ elif [[ -n $arg_p ]]; then
236253
newVersionPatch=$((lastVersionPatch + 1))
237254
fi
238255

239-
newVersion=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -9p full $newVersionMajor.$newVersionMinor.$newVersionPatch")
256+
newVersion=$(/usr/bin/env bash -c "${dir}/validateSemver.sh -9p full $newVersionMajor.$newVersionMinor.$newVersionPatch $arg_opts")
257+
[[ -n $arg_n ]] && newVersion="${arg_n_val}_${newVersion}"
240258

241259
if [[ -n $arg_e ]]; then
242260
export_var="$arg_e_val"
243261
eval "${export_var}=${newVersion}"
244262
export export_var
245263
else
246264
echo "$newVersion"
247-
fi
265+
fi

scripts/detectPreviousVersion.sh

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ NAME
1515
detectPreviousVersion.sh
1616
1717
SYNOPSIS
18-
${0##*/} [-hvc]
18+
${0##*/} [-hvcnd]
1919
2020
DESCRIPTION
2121
Detects most recent version tag of the repository.
@@ -30,6 +30,12 @@ DESCRIPTION
3030
3131
-c Prints the commit hash instead of the detected version to stdout.
3232
33+
-n Enables mono-repo mode allowing the product name to match against tags.
34+
EG: 'bob' would match tags like 'bob_1.2.3'.
35+
TIP: dir names and product names should match. This arg exists in case they do not.
36+
37+
-d The directory of the product to version. EG: 'path/to/bob'.
38+
3339
EXAMPLES
3440
Detects previous version, printing additional information if available.
3541
@@ -59,7 +65,7 @@ fi
5965
# --------------------------------------------------------------------------------------------------
6066

6167
OPTIND=1
62-
while getopts "hvc" opt; do
68+
while getopts "hv9cn:d:" opt; do
6369
case $opt in
6470
h)
6571
printHelp
@@ -71,6 +77,20 @@ while getopts "hvc" opt; do
7177
c)
7278
arg_c='set'
7379
;;
80+
9)
81+
arg_9='set'
82+
;;
83+
n)
84+
arg_n='set'
85+
arg_n_val="$OPTARG"
86+
arg_opts="$arg_opts -n $OPTARG"
87+
;;
88+
d)
89+
arg_d='set'
90+
arg_d_val="$OPTARG"
91+
arg_d_opt="--full-history"
92+
arg_opts="$arg_opts -d $OPTARG"
93+
;;
7494
*)
7595
echo -e "\e[01;31mERROR\e[00m: Invalid argument!"
7696
printHelp
@@ -85,31 +105,43 @@ shift $((OPTIND-1))
85105
# --------------------------------------------------------------------------------------------------
86106

87107
tsCmd='date --utc +%FT%T.%3NZ'
88-
semverRegex="^[v]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-([0-9A-Za-z]+))?(\\+((([1-9])|([1-9][0-9]+))))?$"
108+
109+
if [[ -n $arg_9 ]]; then
110+
semverRegex="^[v]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
111+
[[ -n $arg_d ]] && semverRegex="([0-9A-Za-z]+)?[_-]?[v]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
112+
else
113+
semverRegex="^[v]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-([0-9A-Za-z]+))?(\\+((([1-9])|([1-9][0-9]+))))?$"
114+
[[ -n $arg_d ]] && semverRegex="^([0-9A-Za-z]+)?[_-]?[v]?(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-([0-9A-Za-z]+))?(\\+((([1-9])|([1-9][0-9]+))))?$"
115+
fi
89116

90117
relative_path="$(dirname "${BASH_SOURCE[0]}")"
91118
dir="$(realpath "${relative_path}")"
92119

93120
lastVersion=$(git for-each-ref --sort=creatordate --format '%(refname:lstrip=2)' refs/tags | grep -E "$semverRegex" | tail -n 1)
121+
# Support mono-repos where a product name is specified.
122+
[[ -n $arg_n ]] && lastVersion=$(git for-each-ref --sort=creatordate --format '%(refname:lstrip=2)' refs/tags | grep "$arg_n_val" | grep -E "$semverRegex" | tail -n 1)
94123

95124
# --------------------------------------------------------------------------------------------------
96125
# Sanity (2/2)
97126
# --------------------------------------------------------------------------------------------------
98127

99128
if [[ "$lastVersion" == '' ]]; then
100-
[[ -n $arg_v ]] && echo -e "[$(${tsCmd})] INFO: No previous version detected. Initializing at '0.0.0'.\n"
129+
[[ -n $arg_v && -z $arg_n ]] && echo -e "[$(${tsCmd})] INFO: No previous version detected. Initializing at '0.0.0'.\n"
130+
[[ -n $arg_v && -n $arg_n ]] && echo -e "[$(${tsCmd})] INFO: No previous version detected. Initializing at '${arg_n_val}_0.0.0'.\n"
101131
lastVersion='0.0.0'
102132
lastVersionCommitHash=$(git rev-list --max-parents=0 HEAD)
103133
else
104-
if ! bash -c "${dir}/validateSemver.sh -v9 $lastVersion"; then
134+
if ! bash -c "${dir}/validateSemver.sh -v9 $arg_opts $lastVersion"; then
105135
exit 1
106136
else
107137
lastVersionCommitHash=$(git rev-list -n 1 "$lastVersion")
108138
# Ensure lastVersion does not include a leading [vV]
109-
lastVersion=$(bash -c "${dir}/validateSemver.sh -v9p full $lastVersion")
139+
lastVersion=$(bash -c "${dir}/validateSemver.sh -v9p full $arg_opts $lastVersion")
110140
fi
111141
fi
112142

143+
[[ -n $arg_n ]] && lastVersion="${arg_n_val}_${lastVersion}"
144+
113145
# --------------------------------------------------------------------------------------------------
114146
# Main Operations
115147
# --------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)