|
1 | 1 | version: '3' |
2 | | - |
3 | 2 | silent: true |
4 | | - |
5 | 3 | vars: |
6 | 4 | PR_TEMPLATE: https://raw.githubusercontent.com/devops-infra/.github/refs/tags/v1/PULL_REQUEST_TEMPLATE.md |
7 | 5 | CONFIGS_BASE_URL: https://raw.githubusercontent.com/devops-infra/.github/refs/tags/v1/templates/actions/configs |
8 | 6 | TASKFILES_BASE_URL: https://raw.githubusercontent.com/devops-infra/.github/refs/tags/v1/templates/actions/taskfiles |
9 | | - |
10 | 7 | tasks: |
11 | 8 | pre-commit: |
12 | 9 | desc: Run all pre-commit hooks |
13 | 10 | cmds: |
14 | 11 | - pre-commit run --all-files |
15 | | - |
16 | 12 | pre-commit:install: |
17 | 13 | desc: Install pre-commit hooks |
18 | 14 | cmds: |
19 | 15 | - pre-commit install |
20 | | - |
21 | 16 | lint: |
22 | 17 | desc: Run all linters (Dockerfile, shell scripts, workflows, YAML) |
23 | 18 | cmds: |
24 | 19 | - task: lint:actionlint |
25 | 20 | - task: lint:hadolint |
26 | 21 | - task: lint:shellcheck |
27 | 22 | - task: lint:yamllint |
28 | | - |
29 | 23 | lint:actionlint: |
30 | 24 | desc: Lint GitHub Actions workflows with actionlint |
31 | 25 | cmds: |
32 | | - - | |
33 | | - echo "▶️ Running actionlint..." |
34 | | - set +e |
35 | | - docker run --rm -i -v "$PWD:/work" -w /work rhysd/actionlint:latest -color |
36 | | - rc=$? |
37 | | - set -e |
38 | | - if [ "$rc" -eq 0 ]; then |
39 | | - echo "✅ actionlint passed" |
40 | | - else |
41 | | - echo "❌ actionlint failed" |
42 | | - exit $rc |
43 | | - fi |
44 | | -
|
| 26 | + - task: scripts:lint:actionlint |
45 | 27 | lint:hadolint: |
46 | 28 | desc: Lint Dockerfile with hadolint |
47 | 29 | cmds: |
48 | | - - | |
49 | | - echo "▶️ Running hadolint..." |
50 | | - set +e |
51 | | - docker run --rm -i -v "$PWD:/work" -w /work hadolint/hadolint:latest-debian < Dockerfile |
52 | | - rc=$? |
53 | | - set -e |
54 | | - if [ "$rc" -eq 0 ]; then |
55 | | - echo "✅ hadolint passed" |
56 | | - else |
57 | | - echo "❌ hadolint failed" |
58 | | - exit $rc |
59 | | - fi |
60 | | -
|
| 30 | + - task: scripts:lint:hadolint |
61 | 31 | lint:shellcheck: |
62 | 32 | desc: Lint shell scripts with shellcheck |
63 | 33 | cmds: |
64 | | - - | |
65 | | - echo "▶️ Running shellcheck..." |
66 | | - set +e |
67 | | - docker run --rm -i -v "$PWD:/work" -w /work koalaman/shellcheck:stable -x -S style entrypoint.sh |
68 | | - rc=$? |
69 | | - set -e |
70 | | - if [ "$rc" -eq 0 ]; then |
71 | | - echo "✅ shellcheck passed" |
72 | | - else |
73 | | - echo "❌ shellcheck failed" |
74 | | - exit $rc |
75 | | - fi |
76 | | -
|
| 34 | + - task: scripts:lint:shellcheck |
77 | 35 | lint:yamllint: |
78 | 36 | desc: Lint YAML files with yamllint |
79 | 37 | cmds: |
80 | | - - | |
81 | | - echo "▶️ Running yamllint..." |
82 | | - set +e |
83 | | - docker run --rm -i -v "$PWD:/work" -w /work cytopia/yamllint -c .yamllint.yml . |
84 | | - rc=$? |
85 | | - set -e |
86 | | - if [ "$rc" -eq 0 ]; then |
87 | | - echo "✅ yamllint passed" |
88 | | - else |
89 | | - echo "❌ yamllint failed" |
90 | | - exit $rc |
91 | | - fi |
92 | | -
|
| 38 | + - task: scripts:lint:yamllint |
93 | 39 | dependency:update: |
94 | | - desc: Check main dependency not covered by dependabot |
| 40 | + desc: 'No-op: no dedicated dependency updater configured for this profile' |
95 | 41 | cmds: |
96 | | - - | |
97 | | - echo "ℹ️ No dedicated dependency updater configured for this repository." |
98 | | - echo "ℹ️ Dependabot handles GitHub Actions and package metadata updates." |
99 | | - echo "ℹ️ Docker build validation remains the runtime safety net." |
100 | | -
|
| 42 | + - task: scripts:dependency:update |
101 | 43 | version:set: |
102 | 44 | desc: Update version in README.md and action.yml |
103 | 45 | cmds: |
104 | | - - | |
105 | | - if [ -z "{{.VERSION}}" ]; then |
106 | | - echo "❌ ERROR: VERSION is empty" |
107 | | - exit 1 |
108 | | - fi |
109 | | - if ! echo "{{.VERSION}}" | grep -Eq '^v?[0-9]+\.[0-9]+\.[0-9]+$'; then |
110 | | - echo "❌ ERROR: VERSION '{{.VERSION}}' is not a valid semantic version (expected vX.Y.Z or X.Y.Z)" |
111 | | - exit 1 |
112 | | - fi |
113 | | - - echo Updating full version from {{.VERSION_FROM_ACTION_YML}} to {{.VERSION}} |
114 | | - - echo Updating minor version from {{.MINOR_FROM_ACTION_YML}} to {{.VERSION_MINOR}} |
115 | | - - echo Updating major version from {{.MAJOR_FROM_ACTION_YML}} to {{.VERSION_MAJOR}} |
116 | | - - "{{.SED}} -i 's#{{.DOCKER_NAME}}:{{.VERSION_FROM_ACTION_YML}}#{{.DOCKER_NAME}}:{{.VERSION}}#g' action.yml" |
117 | | - - "{{.SED}} -i 's#{{.DOCKER_NAME}}@{{.VERSION_FROM_ACTION_YML}}#{{.DOCKER_NAME}}@{{.VERSION}}#g' README.md" |
118 | | - - "{{.SED}} -i 's#{{.GITHUB_NAME}}@{{.VERSION_FROM_ACTION_YML}}#{{.GITHUB_NAME}}@{{.VERSION}}#g' README.md" |
119 | | - - "{{.SED}} -i 's#{{.DOCKER_NAME}}@{{.MINOR_FROM_ACTION_YML}}#{{.DOCKER_NAME}}@{{.VERSION_MINOR}}#g' README.md" |
120 | | - - "{{.SED}} -i 's#{{.GITHUB_NAME}}@{{.MINOR_FROM_ACTION_YML}}#{{.GITHUB_NAME}}@{{.VERSION_MINOR}}#g' README.md" |
121 | | - - "{{.SED}} -i 's#{{.DOCKER_NAME}}@{{.MAJOR_FROM_ACTION_YML}}#{{.DOCKER_NAME}}@{{.VERSION_MAJOR}}#g' README.md" |
122 | | - - "{{.SED}} -i 's#{{.GITHUB_NAME}}@{{.MAJOR_FROM_ACTION_YML}}#{{.GITHUB_NAME}}@{{.VERSION_MAJOR}}#g' README.md" |
123 | | - |
| 46 | + - task: scripts:version:set |
124 | 47 | version:update:patch: |
125 | 48 | desc: Increment patch version (e.g., 1.2.3 -> 1.2.4) |
126 | 49 | cmds: |
127 | 50 | - task version:set VERSION=v{{.MAJOR}}.{{.MINOR}}.{{.NEXT_PATCH}} |
128 | | - |
129 | 51 | version:update:minor: |
130 | 52 | desc: Increment minor version (e.g., 1.2.3 -> 1.3.0) |
131 | 53 | cmds: |
132 | 54 | - task version:set VERSION=v{{.MAJOR}}.{{.NEXT_MINOR}}.0 |
133 | | - |
134 | 55 | version:update:major: |
135 | 56 | desc: Increment major version (e.g., 1.2.3 -> 2.0.0) |
136 | 57 | cmds: |
137 | 58 | - task version:set VERSION=v{{.NEXT_MAJOR}}.0.0 |
138 | | - |
139 | 59 | version:resolve-next: |
140 | 60 | desc: Resolve next version from bump type and profile |
141 | 61 | cmds: |
142 | | - - | |
143 | | - set -eu |
144 | | - bump_type="${BUMP_TYPE:-patch}" |
145 | | - input_version="${INPUT_VERSION:-}" |
146 | | -
|
147 | | - normalize_version() { |
148 | | - candidate="${1#v}" |
149 | | - if ! printf "%s" "${candidate}" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then |
150 | | - return 1 |
151 | | - fi |
152 | | - printf "v%s" "${candidate}" |
153 | | - } |
154 | | -
|
155 | | - current="$(task version:get 2>/dev/null || true)" |
156 | | -
|
157 | | - case "$bump_type" in |
158 | | - set) |
159 | | - [ -n "$input_version" ] || { echo "Missing version for type=set"; exit 1; } |
160 | | - next="$(normalize_version "$input_version")" || { |
161 | | - echo "Invalid explicit version: $input_version. Expected vX.Y.Z or X.Y.Z" |
162 | | - exit 1 |
163 | | - } |
164 | | - ;; |
165 | | - patch|minor|major) |
166 | | - [ -n "$current" ] || { echo "Current version not found or invalid. Expected vX.Y.Z"; exit 1; } |
167 | | - current="$(normalize_version "$current")" || { echo "Current version not found or invalid. Expected vX.Y.Z"; exit 1; } |
168 | | - no_v="${current#v}" |
169 | | - major="$(printf "%s" "$no_v" | awk -F. '{print $1}')" |
170 | | - minor="$(printf "%s" "$no_v" | awk -F. '{print $2}')" |
171 | | - patch="$(printf "%s" "$no_v" | awk -F. '{print $3}')" |
172 | | - case "$bump_type" in |
173 | | - patch) next="v${major}.${minor}.$((patch + 1))" ;; |
174 | | - minor) next="v${major}.$((minor + 1)).0" ;; |
175 | | - major) next="v$((major + 1)).0.0" ;; |
176 | | - esac |
177 | | - ;; |
178 | | - *) |
179 | | - echo "Unknown type: $bump_type" |
180 | | - exit 1 |
181 | | - ;; |
182 | | - esac |
183 | | -
|
184 | | - printf "%s" "$next" |
185 | | -
|
| 62 | + - task: scripts:version:resolve-next |
186 | 63 | version:tag-release: |
187 | 64 | desc: Create set of git tags |
188 | 65 | cmds: |
189 | | - - | |
190 | | - set -eu |
191 | | - if (set -o | grep -q pipefail) 2>/dev/null; then set -o pipefail; fi |
192 | | -
|
193 | | - REMOTE='origin' |
194 | | - FULL='{{.VERSION_FULL}}' |
195 | | - MINOR='{{.VERSION_MINOR}}' |
196 | | - MAJOR='{{.VERSION_MAJOR}}' |
197 | | -
|
198 | | - # Validate vX.Y.Z |
199 | | - if ! printf "%s" "$FULL" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then |
200 | | - echo "❌ ERROR: VERSION '$FULL' must match vX.Y.Z" >&2 |
201 | | - exit 1 |
202 | | - fi |
203 | | -
|
204 | | - tag_sha() { git rev-parse "refs/tags/$1" 2>/dev/null || true; } |
205 | | - remote_tag_sha() { git ls-remote --tags "$REMOTE" "refs/tags/$1" 2>/dev/null | awk '{print $1}' || true; } |
206 | | -
|
207 | | - echo "ℹ️ INFO: Tags - Full: $FULL | Minor: $MINOR | Major: $MAJOR" |
208 | | -
|
209 | | - # Full tag: must NOT exist on remote; fail fast if it does |
210 | | - full_remote_sha="$(remote_tag_sha "$FULL")" |
211 | | - if [ -n "$full_remote_sha" ]; then |
212 | | - echo "❌ ERROR: Full tag '$FULL' already exists on remote; aborting" >&2 |
213 | | - exit 1 |
214 | | - fi |
215 | | -
|
216 | | - # Create full tag locally (if missing) and push |
217 | | - if git rev-parse --quiet --verify "refs/tags/$FULL" >/dev/null 2>&1; then |
218 | | - echo "ℹ️ INFO: Full tag '$FULL' exists locally but not on remote; pushing" |
219 | | - else |
220 | | - echo "ℹ️ INFO: Creating full tag '$FULL'" |
221 | | - git tag --annotate "$FULL" --message "$FULL" |
222 | | - fi |
223 | | - git push "$REMOTE" "refs/tags/$FULL" |
224 | | - echo "✅ OK: Pushed full tag '$FULL'" |
225 | | -
|
226 | | - # Minor tag: create or update |
227 | | - git tag --force --annotate "$MINOR" --message "$FULL" |
228 | | - minor_local_sha="$(tag_sha "$MINOR")" |
229 | | - minor_remote_sha="$(remote_tag_sha "$MINOR")" |
230 | | - if [ -z "$minor_remote_sha" ]; then |
231 | | - git push "$REMOTE" "refs/tags/$MINOR" |
232 | | - echo "✅ OK: Created and pushed minor tag '$MINOR' -> $minor_local_sha" |
233 | | - else |
234 | | - if [ "$minor_local_sha" != "$minor_remote_sha" ]; then |
235 | | - echo "⚠️ WARN: Updating remote minor tag '$MINOR' to $minor_local_sha (was $minor_remote_sha)" |
236 | | - git push --force "$REMOTE" "refs/tags/$MINOR" |
237 | | - else |
238 | | - echo "ℹ️ INFO: Minor tag '$MINOR' already up-to-date" |
239 | | - fi |
240 | | - fi |
241 | | -
|
242 | | - # Major tag: create or update |
243 | | - git tag --force --annotate "$MAJOR" --message "$FULL" |
244 | | - major_local_sha="$(tag_sha "$MAJOR")" |
245 | | - major_remote_sha="$(remote_tag_sha "$MAJOR")" |
246 | | - if [ -z "$major_remote_sha" ]; then |
247 | | - git push "$REMOTE" "refs/tags/$MAJOR" |
248 | | - echo "✅ OK: Created and pushed major tag '$MAJOR' -> $major_local_sha" |
249 | | - else |
250 | | - if [ "$major_local_sha" != "$major_remote_sha" ]; then |
251 | | - echo "⚠️ WARN: Updating remote major tag '$MAJOR' to $major_local_sha (was $major_remote_sha)" |
252 | | - git push --force "$REMOTE" "refs/tags/$MAJOR" |
253 | | - else |
254 | | - echo "ℹ️ INFO: Major tag '$MAJOR' already up-to-date" |
255 | | - fi |
256 | | - fi |
257 | | -
|
| 66 | + - task: scripts:version:tag-release |
258 | 67 | git:get-pr-template: |
259 | 68 | desc: Get pull request template |
260 | 69 | cmds: |
261 | | - - mkdir -p .tmp |
262 | | - - curl -LsS {{.PR_TEMPLATE}} -o .tmp/PULL_REQUEST_TEMPLATE.md |
263 | | - |
| 70 | + - task: scripts:git:get-pr-template |
264 | 71 | git:set-config: |
265 | 72 | desc: Set git user config |
266 | 73 | cmds: |
267 | | - - git config user.name "github-actions[bot]" |
268 | | - - git config user.email "github-actions[bot]@users.noreply.github.com" |
269 | | - |
| 74 | + - task: scripts:git:set-config |
270 | 75 | version:get: |
271 | 76 | desc: Get current version |
272 | 77 | cmds: |
273 | | - - echo "{{.VERSION}}" |
| 78 | + - task: scripts:version:get |
0 commit comments