-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction.yml
230 lines (197 loc) · 9.04 KB
/
action.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
name: 'SemVer Tagger'
description: 'Tags the current commit generating a valid (and reasonable) Semantic Versioning 2.0 version based on Conventional Commits specification'
inputs:
github_token:
description: 'GitHub token for pushing tags'
required: true
ignore_patterns:
description: 'Pipe-separated list of file patterns to ignore when calculating version bump'
required: false
default: '.md|.github/|.yml|.gitignore'
outputs:
version:
description: 'The new version tag created by the action'
value: ${{ steps.calculate-version.outputs.version }}
version_full:
description: 'Full version string including branch and commit information'
value: ${{ steps.calculate-version.outputs.version_full }}
version_rpm:
description: 'Full version string including branch and commit information for RPM'
value: ${{ steps.calculate-version.outputs.version_rpm }}
version_deb:
description: 'Full version string including branch and commit information for DEB'
value: ${{ steps.calculate-version.outputs.version_deb }}
target:
description: 'Build target - release or dev depending on presence of release tag'
value: ${{ steps.calculate-version.outputs.target }}
runs:
using: "composite"
steps:
- uses: actions/checkout@v4
env:
GH_REPOSITORY_REF: ${{ github.head_ref || github.ref }}
with:
fetch-depth: 0
ref: ${{ env.GH_REPOSITORY_REF }}
- name: Calculate and push new version tag
id: calculate-version
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.github_token }}
IGNORE_PATTERNS: ${{ inputs.ignore_patterns }}
run: |
# Enable case-insensitive matching
shopt -s nocasematch
git fetch --tags
# Debug information
echo "Listing all tags:"
echo $(git tag -l)
# Get all tags that match the pattern
MATCHING_TAGS=$(git tag -l "[0-9]*.[0-9]*.[0-9]*")
echo "Listing tags matching pattern:"
echo "$MATCHING_TAGS"
# Check if there are any matching tags
if [ -n "$MATCHING_TAGS" ]; then
# Get the latest semver tag
LATEST_TAG=$(echo "$MATCHING_TAGS" | sort -V | tail -1)
fi
echo "Latest tag: $LATEST_TAG"
# Get commit hashes since the latest tag (or all commits if no tag exists)
if [ -z "$LATEST_TAG" ]; then
COMMIT_HASHES=$(git log --reverse --format="%H")
LATEST_TAG="0.0.0"
else
COMMIT_HASHES=$(git log --reverse ${LATEST_TAG}..HEAD --format="%H")
fi
echo "Latest tag: $LATEST_TAG";
# Check if current commit has a release tag
HAS_RELEASE_TAG=$(git tag --points-at HEAD | grep -E '^release' || true)
# Set target based on release tag presence
if [ -n "$HAS_RELEASE_TAG" ]; then
echo "target=release" >> $GITHUB_OUTPUT
else
echo "target=dev" >> $GITHUB_OUTPUT
fi
# Skip if no commits found
if [ -z "$COMMIT_HASHES" ]; then
echo "No new commits found since $LATEST_TAG, skipping version bump"
if [ -n "$HAS_RELEASE_TAG" ]; then
# Get current commit hash (first 8 chars)
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
# Get timestamp from the commit
TIMESTAMP=$(git log -1 --format="%cd" --date=format:'%y%m%d%H' HEAD)
# Output version info for release tag
VERSION_FULL="${LATEST_TAG}+${TIMESTAMP}-${COMMIT_HASH}"
echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "version_full=$VERSION_FULL" >> $GITHUB_OUTPUT
echo "version_rpm=$(echo "$VERSION_FULL" | tr '-' '.')" >> $GITHUB_OUTPUT
echo "version_deb=$VERSION_FULL" >> $GITHUB_OUTPUT
fi
echo "RESULT: "; cat $GITHUB_OUTPUT
exit 0
fi
# Parse current version
IFS='.' read -r MAJOR MINOR PATCH <<< "$LATEST_TAG"
# Default ignore patterns
IGNORE_PATTERNS="${IGNORE_PATTERNS}"
# Process each commit
while IFS= read -r commit_hash; do
# Get commit message
commit_message=$(git log -1 --format="%B" $commit_hash)
# Get changed files for this commit
changed_files=$(git diff-tree --no-commit-id --name-only -r "$commit_hash")
echo "Analyzing commit: '$commit_hash' with message: '$commit_message' and updated files: '$changed_files'"
# Skip if no files were changed (e.g. merge commits)
if [ -z "$changed_files" ]; then
echo "No files changed in this commit, skipping version bump"
continue
fi
# Check if commit touches only ignored files
all_files_ignored=true
while IFS= read -r file; do
if [[ ! "$file" =~ ($IGNORE_PATTERNS)$ ]]; then
all_files_ignored=false
break
fi
done <<< "$changed_files"
# Skip version bump if all changed files are ignored
if [ "$all_files_ignored" = true ]; then
echo "All changed files are ignored, skipping version bump"
continue
fi
# Check for breaking changes
if [[ "$commit_message" =~ breaking ]]; then
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
# Check for fixes
elif [[ "$commit_message" =~ ([^a-zA-Z0-9]|^)(fix|bugfix|bugfixing|fixed|fixes|fixing|fixup)([^a-zA-Z0-9]|$) ]]; then
PATCH=$((PATCH + 1))
# All other changes are considered minor
else
MINOR=$((MINOR + 1))
PATCH=0
fi
echo "Bumping version to: $MAJOR.$MINOR.$PATCH"
done <<< "$COMMIT_HASHES"
# Create new tag
NEW_TAG="${MAJOR}.${MINOR}.${PATCH}"
# Get current branch name
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
# Semver does not allow some symbols that branch may have
VERSION_SUFFIX=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9-]//g')
# Get current commit hash (first 8 chars)
COMMIT_HASH=$(git rev-parse --short=8 HEAD)
# Get timestamp from the commit in YYMMDDHH format
TIMESTAMP=$(git log -1 --format="%cd" --date=format:'%y%m%d%H' HEAD)
# Generate full version string
if [ -z "$HAS_RELEASE_TAG" ]; then
if [[ "$BRANCH_NAME" == "master" || "$BRANCH_NAME" == "main" ]]; then
VERSION_FULL="${NEW_TAG}+${TIMESTAMP}-${COMMIT_HASH}-dev"
else
VERSION_FULL="${NEW_TAG}+${TIMESTAMP}-${COMMIT_HASH}-${VERSION_SUFFIX}"
fi
else
VERSION_FULL="${NEW_TAG}+${TIMESTAMP}-${COMMIT_HASH}"
fi
VERSION_RPM=$(echo "$VERSION_FULL" | tr '-' '.')
VERSION_DEB=$(echo "$VERSION_FULL")
# Create and push new tag if it's different from the latest
if [ "$NEW_TAG" != "$LATEST_TAG" ]; then
echo "New version: $NEW_TAG (previous was $LATEST_TAG)"
echo "Full version: $VERSION_FULL"
echo "RPM version: $VERSION_RPM"
echo "DEB version: $VERSION_DEB"
# Create tag
git tag $NEW_TAG
# Debug info
if [ -n "$GITHUB_ACTOR" -a -n "$GITHUB_REPOSITORY" ]; then
echo "Repository: $GITHUB_REPOSITORY"
echo "Actor: $GITHUB_ACTOR"
# Configure git
git config --global user.name "$GITHUB_ACTOR"
git config --global user.email "[email protected]"
# Set up authentication and push
echo "remote set-url origin ..."
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
echo "git push origin $NEW_TAG"
git push origin $NEW_TAG || {
echo "::error::Failed to push new tag. Please check if the provided token has sufficient permissions."
exit 1
}
echo "version=$NEW_TAG" >> $GITHUB_OUTPUT
echo "version_full=$VERSION_FULL" >> $GITHUB_OUTPUT
echo "version_rpm=$VERSION_RPM" >> $GITHUB_OUTPUT
echo "version_deb=$VERSION_DEB" >> $GITHUB_OUTPUT
fi
elif [ -n "$HAS_RELEASE_TAG" ]; then
# Output version info even if tag hasn't changed, when release tag is present
echo "version=$NEW_TAG" >> $GITHUB_OUTPUT
echo "version_full=$VERSION_FULL" >> $GITHUB_OUTPUT
echo "version_rpm=$VERSION_RPM" >> $GITHUB_OUTPUT
echo "version_deb=$VERSION_DEB" >> $GITHUB_OUTPUT
fi
echo "RESULT: "; cat $GITHUB_OUTPUT
branding:
icon: git-merge
color: green