@zairakai/js-dev-tools 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,7 +40,7 @@ include:
40
40
  # ================================
41
41
  workflow:
42
42
  rules:
43
- - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
43
+ - if: $CI_COMMIT_TAG
44
44
  - if: $CI_PIPELINE_SOURCE == "schedule"
45
45
  - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_MERGE_REQUEST_ID
46
46
  - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
@@ -137,6 +137,29 @@ secret_detection:
137
137
  - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_MERGE_REQUEST_ID
138
138
  - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
139
139
 
140
+ # A tag whose format is not the one of VERSION_TAG_REGEX (group variable) fails here,
141
+ # and the jobs that publish do not run for it.
142
+ js:tag-format:
143
+ <<: *base_job
144
+ stage: security
145
+ image: ${ALPINE_IMAGE}
146
+ rules:
147
+ - if: $CI_COMMIT_TAG
148
+ script:
149
+ - |
150
+ regex="${VERSION_TAG_REGEX:-}"
151
+ regex="${regex#/}"
152
+ regex="${regex%/}"
153
+ if [ -z "$regex" ]; then
154
+ echo "ERROR: VERSION_TAG_REGEX is not set. It is a variable of the zairakai group."
155
+ exit 1
156
+ fi
157
+ if ! printf '%s\n' "$CI_COMMIT_TAG" | grep -Eq "$regex"; then
158
+ echo "ERROR: the tag \"$CI_COMMIT_TAG\" does not match $VERSION_TAG_REGEX (X.Y.Z or X.Y.Z-prerelease)."
159
+ exit 1
160
+ fi
161
+ echo "Tag $CI_COMMIT_TAG: format OK"
162
+
140
163
  # ================================
141
164
  # INSTALL
142
165
  # ================================
@@ -229,7 +252,7 @@ js:quality:bats:
229
252
  stage: quality
230
253
  image: ${ALPINE_IMAGE}
231
254
  before_script:
232
- - apk add --no-cache bash bats
255
+ - apk add --no-cache bash bats git
233
256
  script:
234
257
  - |
235
258
  if [[ -d tests/bats ]]; then
@@ -291,7 +314,7 @@ js:build:
291
314
  expire_in: 1 week
292
315
  when: on_success
293
316
  rules:
294
- - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
317
+ - if: $CI_COMMIT_TAG =~ $VERSION_TAG_REGEX
295
318
  - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
296
319
  - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_MERGE_REQUEST_ID
297
320
 
@@ -303,7 +326,7 @@ js:publish:
303
326
  stage: publish
304
327
  image: ${NODE_IMAGE}
305
328
  rules:
306
- - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
329
+ - if: $CI_COMMIT_TAG =~ $VERSION_TAG_REGEX
307
330
  script:
308
331
  - |
309
332
  if [[ -z "${NPM_TOKEN:-}" ]]; then
@@ -313,14 +336,14 @@ js:publish:
313
336
  fi
314
337
  - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > "${CI_PROJECT_DIR}/.npmrc"
315
338
  - |
316
- if [[ $CI_COMMIT_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
317
- echo "Publishing ${NPM_PACKAGE_NAME}@${CI_COMMIT_TAG#v} to npm..."
318
- npm version "${CI_COMMIT_TAG#v}" --no-git-tag-version --allow-same-version
319
- npm publish --access public
320
- else
321
- echo "Invalid tag format: ${CI_COMMIT_TAG}. Expected: v1.0.0"
322
- exit 1
339
+ # A pre-release (2.3.0-rc.1) goes to the npm tag "next", so it never becomes "latest"
340
+ npm_tag="latest"
341
+ if [[ $CI_COMMIT_TAG == *-* ]]; then
342
+ npm_tag="next"
323
343
  fi
344
+ echo "Publishing ${NPM_PACKAGE_NAME}@${CI_COMMIT_TAG} to npm (tag ${npm_tag})..."
345
+ npm version "${CI_COMMIT_TAG}" --no-git-tag-version --allow-same-version
346
+ npm publish --access public --tag "${npm_tag}"
324
347
  environment:
325
348
  name: production
326
349
  url: https://www.npmjs.com/package/${NPM_PACKAGE_NAME}
@@ -333,7 +356,7 @@ js:release:
333
356
  stage: release
334
357
  image: ${RELEASE_CLI_IMAGE}
335
358
  rules:
336
- - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
359
+ - if: $CI_COMMIT_TAG =~ $VERSION_TAG_REGEX
337
360
  before_script:
338
361
  - apk add --no-cache bash git jq
339
362
  - git config --global --add safe.directory '*'
@@ -341,7 +364,8 @@ js:release:
341
364
  - git config --global user.email "ci@gitlab.com"
342
365
  script:
343
366
  - |
344
- PREVIOUS_TAG=$(git tag --sort=-version:refname | head -n 2 | tail -n 1 || echo "")
367
+ # Tags are listed newest first, with or without the old "v" prefix (v2.1.0 then 2.2.0)
368
+ PREVIOUS_TAG=$(git tag | sed -E 's/^v?(.*)$/\1 &/' | sort -k1,1 -Vr | cut -d' ' -f2 | grep -A1 -Fx "${CI_COMMIT_TAG}" | tail -n 1 || echo "")
345
369
  if [[ -n "$PREVIOUS_TAG" && "$PREVIOUS_TAG" != "$CI_COMMIT_TAG" ]]; then
346
370
  COMMITS=$(git log --pretty=format:"- %s" "${PREVIOUS_TAG}..${CI_COMMIT_TAG}" | head -20)
347
371
  else
@@ -356,7 +380,7 @@ js:release:
356
380
  --tag-name "${CI_COMMIT_TAG}" \
357
381
  --name "Release ${CI_COMMIT_TAG}" \
358
382
  --description "$(cat release_notes.md)" \
359
- --assets-link "{\"name\":\"npm\",\"url\":\"https://www.npmjs.com/package/${NPM_PACKAGE_NAME}/v/${CI_COMMIT_TAG#v}\"}"
383
+ --assets-link "{\"name\":\"npm\",\"url\":\"https://www.npmjs.com/package/${NPM_PACKAGE_NAME}/v/${CI_COMMIT_TAG}\"}"
360
384
  artifacts:
361
385
  paths:
362
386
  - release_notes.md
package/README.md CHANGED
@@ -146,7 +146,7 @@ Include in your consumer project's `.gitlab-ci.yml`:
146
146
  # npm package pipeline
147
147
  include:
148
148
  - project: 'zairakai/npm-packages/js-dev-tools'
149
- ref: v1.0.0 # pin to a release tag for reproducible builds
149
+ ref: 1.0.0 # pin to a release tag for reproducible builds
150
150
  file: '.gitlab/ci/pipeline-js-package.yml'
151
151
 
152
152
  variables:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zairakai/js-dev-tools",
3
- "version": "2.1.0",
3
+ "version": "3.0.0",
4
4
  "description": "The unified and centralized development toolkit for JavaScript/TypeScript projects - ESLint, Prettier, Stylelint, Knip, Vitest, Git Hooks, and GitLab CI pipeline templates",
5
5
  "keywords": [
6
6
  "dev-tools",
@@ -382,7 +382,7 @@ replace_gitlab_ci_placeholders() {
382
382
  fi
383
383
 
384
384
  if [[ -n "$dev_tools_version" ]]; then
385
- sed -i "s|v0.0.0|v${dev_tools_version}|g" "$target"
385
+ sed -i "s|ref: 0\.0\.0|ref: ${dev_tools_version}|g" "$target"
386
386
  fi
387
387
  }
388
388
 
@@ -417,7 +417,7 @@ publish_gitlab_ci_npm() {
417
417
 
418
418
  track_published ".gitlab-ci.yml"
419
419
  log_success "Published: .gitlab-ci.yml"
420
- log_info "ref: v0.0.0 will be updated automatically on: ${PM} update @zairakai/js-dev-tools"
420
+ log_info "ref: 0.0.0 will be updated automatically on: ${PM} update @zairakai/js-dev-tools"
421
421
  }
422
422
 
423
423
  # ============================================================================
@@ -650,7 +650,7 @@ sync_gitlab_ci_ref() {
650
650
 
651
651
  # Resolve installed version from the package's own package.json
652
652
  local installed_version
653
- installed_version="$(node -e "try{const p=require('${DEV_TOOLS_ROOT}/package.json');console.log('v'+(p.version||'').replace(/^v/,''))}catch(e){}" 2>/dev/null || echo "")"
653
+ installed_version="$(node -e "try{const p=require('${DEV_TOOLS_ROOT}/package.json');console.log((p.version||'').replace(/^v/,''))}catch(e){}" 2>/dev/null || echo "")"
654
654
 
655
655
  [[ -n "$installed_version" ]] || return 0
656
656
 
@@ -1,34 +1,59 @@
1
1
  #!/usr/bin/env bash
2
+ # Commit message validation hook
3
+ # Published by: zairakai/laravel-dev-tools. Same hook as php-dev-tools and js-dev-tools, aligned on the commit convention of the zairakai handbook
4
+ # (policies/git-rules.md), which is the only convention of the zairakai tools:
2
5
  #
3
- # Zairakai Git Hooks - Commit Message Validator
4
- # Ensures commit messages follow Conventional Commits format
6
+ # <type>(<scope>): #TICKET <subject>
7
+ #
8
+ # - type: feat, fix, docs, style, refactor, perf, test, chore, ci or build
9
+ # - scope: optional, in lowercase
10
+ # - #TICKET: the number of the issue
11
+ # - the first line has 72 characters at most, and the second line is blank
12
+ #
13
+ # A work in progress follows the same format. The messages that Git writes itself
14
+ # (Merge, Revert, fixup!, squash!) are accepted as they are.
5
15
  #
6
16
  # To bypass (emergency only):
7
17
  # git commit --no-verify
8
18
 
9
- set -euo pipefail
10
-
11
- # ANSI Colors
12
- RED='\033[0;31m'
13
- NC='\033[0m'
19
+ commit_msg_file="$1"
20
+ first_line=$(sed -n 1p "$commit_msg_file")
21
+ second_line=$(sed -n 2p "$commit_msg_file")
14
22
 
15
- COMMIT_MSG_FILE=$1
16
- COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
23
+ case "$first_line" in
24
+ "Merge "* | "Revert \""* | "fixup! "* | "squash! "* | "amend! "*) exit 0 ;;
25
+ esac
17
26
 
18
- # Conventional Commits regex
19
- # Format: <type>(<scope>): <subject>
20
- CONVENTIONAL_RE='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert|init)(\(.+\))?!?: .+$'
27
+ PATTERN='^(feat|fix|docs|style|refactor|perf|test|chore|ci|build)(\([a-z0-9][a-z0-9._/-]*\))?: #[0-9]+ [^[:space:]].*$'
21
28
 
22
- if [[ ! $COMMIT_MSG =~ $CONVENTIONAL_RE ]]; then
29
+ fail() {
23
30
  echo ""
24
- echo -e "${RED}❌ Invalid commit message format!${NC}"
31
+ echo "❌ $1"
25
32
  echo ""
26
- echo "Commit messages must follow Conventional Commits:"
27
- echo " feat: add new feature"
28
- echo " fix: resolve a bug"
29
- echo " chore(deps): update dependencies"
33
+ echo " Format of the zairakai handbook: <type>(<scope>): #TICKET <subject>"
34
+ echo " Types: feat, fix, docs, style, refactor, perf, test, chore, ci, build"
30
35
  echo ""
31
- echo "See: https://www.conventionalcommits.org/"
36
+ echo " Your message: \"$first_line\""
37
+ echo ""
38
+ echo " Examples:"
39
+ echo " feat(auth): #102 add OAuth2 provider support"
40
+ echo " fix(api): #87 handle null response from payment gateway"
41
+ echo " docs: #31 update installation instructions"
32
42
  echo ""
33
43
  exit 1
44
+ }
45
+
46
+ if ! [[ $first_line =~ $PATTERN ]]; then
47
+ fail "Invalid commit message format"
34
48
  fi
49
+
50
+ if [[ ${#first_line} -gt 72 ]]; then
51
+ fail "The first line has ${#first_line} characters: the limit is 72"
52
+ fi
53
+
54
+ if [[ -n $second_line ]]; then
55
+ fail "The second line must be blank"
56
+ fi
57
+
58
+ echo "✅ Commit message OK"
59
+ exit 0
@@ -1,39 +1,33 @@
1
1
  #!/usr/bin/env bash
2
+ # Prepare commit message hook - adds the ticket of the branch to the message
3
+ # Published by: zairakai/laravel-dev-tools. Same hook as php-dev-tools and js-dev-tools. The fix: the ticket goes after "type(scope): ",
4
+ # which is the form that the hook commit-msg asks for.
2
5
  #
3
- # Zairakai Git Hooks - Commit Message Preparer
4
- # Auto-prefixes the ticket number from branch name (e.g. feature/ABC-123 -> ABC-123: )
6
+ # Branch naming convention:
7
+ # feature/#123-description → "feat(scope): subject" becomes "feat(scope): #123 subject"
8
+ # fix/#456-bug-description → the same with #456
9
+ # hotfix/#789-critical → the same with #789
5
10
  #
11
+ # Nothing is changed for a merge, a squash or an amend, when the message already has the ticket,
12
+ # or when its first line is not "type(scope): subject".
6
13
 
7
- set -euo pipefail
14
+ commit_msg_file="$1"
15
+ commit_source="$2"
8
16
 
9
- COMMIT_MSG_FILE=$1
10
- BRANCH_NAME=$(git symbolic-ref --short HEAD 2>/dev/null || true)
17
+ case "$commit_source" in
18
+ merge | squash | commit) exit 0 ;;
19
+ esac
11
20
 
12
- # Skip for special commits
13
- COMMIT_SOURCE=${2:-}
14
- if [[ "$COMMIT_SOURCE" == "merge" || "$COMMIT_SOURCE" == "squash" || "$COMMIT_SOURCE" == "message" ]]; then
15
- exit 0
16
- fi
21
+ branch=$(git symbolic-ref --short HEAD 2>/dev/null)
17
22
 
18
- # Extract ticket number (Jira/GitLab style: PROJECT-123)
19
- TICKET_RE='[A-Z]+-[0-9]+'
20
- if [[ $BRANCH_NAME =~ $TICKET_RE ]]; then
21
- TICKET="${BASH_REMATCH[0]}"
22
- COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
23
+ # Extract the ticket from a branch named type/#NUMBER-description
24
+ if [[ $branch =~ (feature|fix|hotfix)/#([0-9]+) ]]; then
25
+ ticket="#${BASH_REMATCH[2]}"
23
26
 
24
- # Only prefix if not already present
25
- if [[ ! $COMMIT_MSG =~ $TICKET ]]; then
26
- # If it's a conventional commit type: subject format, inject after type:
27
- # Before: feat: my change
28
- # After: feat(ABC-123): my change
29
- CONVENTIONAL_RE='^([a-z]+)(\(.*\))?!?: (.+)$'
30
- if [[ $COMMIT_MSG =~ $CONVENTIONAL_RE ]]; then
31
- TYPE="${BASH_REMATCH[1]}"
32
- REMAINDER="${BASH_REMATCH[3]}"
33
- echo "${TYPE}(${TICKET}): ${REMAINDER}" > "$COMMIT_MSG_FILE"
34
- else
35
- # Fallback: simple prefix
36
- echo "${TICKET}: ${COMMIT_MSG}" > "$COMMIT_MSG_FILE"
37
- fi
27
+ if ! grep -qE "${ticket}([^0-9]|$)" "$commit_msg_file"; then
28
+ sed -i.bak -E "1s/^([a-z]+(\([^)]*\))?: )/\1${ticket} /" "$commit_msg_file"
29
+ rm -f "$commit_msg_file.bak"
38
30
  fi
39
31
  fi
32
+
33
+ exit 0
@@ -7,7 +7,7 @@
7
7
 
8
8
  include:
9
9
  - project: 'zairakai/npm-packages/js-dev-tools'
10
- ref: v0.0.0
10
+ ref: 0.0.0
11
11
  file: '.gitlab/ci/pipeline-js-package.yml'
12
12
 
13
13
  variables:
@@ -8,7 +8,7 @@
8
8
 
9
9
  include:
10
10
  - project: 'zairakai/npm-packages/js-dev-tools'
11
- ref: v0.0.0
11
+ ref: 0.0.0
12
12
  file: '.gitlab/ci/pipeline-js-app.yml'
13
13
 
14
14
  variables: