@devopsplaybook.io/common-utils 1.10.1-beta.23.b1906d7 → 1.11.0-beta.24.d8f9aef
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.
- package/README.md +73 -27
- package/dist/src/ConfigBase.d.ts +31 -0
- package/dist/src/ConfigBase.js +58 -16
- package/dist/src/DbUtils.d.ts +20 -3
- package/dist/src/DbUtils.js +93 -2
- package/dist/src/DbUtilsNoTelemetry.d.ts +4 -1
- package/dist/src/DbUtilsNoTelemetry.js +62 -6
- package/dist/src/PostgresDbUtils.d.ts +41 -10
- package/dist/src/PostgresDbUtils.js +357 -304
- package/dist/src/SqlDbUtils.d.ts +12 -4
- package/dist/src/SqlDbUtils.js +76 -30
- package/dist/src/users/Auth.d.ts +11 -1
- package/dist/src/users/Auth.js +160 -44
- package/dist/src/users/User.d.ts +10 -0
- package/dist/src/users/User.js +30 -10
- package/dist/src/users/UserApiToken.d.ts +4 -0
- package/dist/src/users/UserApiToken.js +11 -0
- package/dist/src/users/UsersApiTokensData.d.ts +12 -0
- package/dist/src/users/UsersApiTokensData.js +130 -33
- package/dist/src/users/UsersData.d.ts +20 -1
- package/dist/src/users/UsersData.js +150 -52
- package/dist/src/users/UsersRoutes.js +178 -61
- package/dist/src/users/index.d.ts +8 -0
- package/dist/src/users/index.js +24 -0
- package/package.json +58 -1
- package/.github/workflows/main-build.yml +0 -18
- package/.github/workflows/pr-check.yml +0 -27
- package/.github/workflows/reusable-merge-build.yml +0 -197
- package/.github/workflows/reusable-npm-merge.yml +0 -135
- package/.github/workflows/reusable-npm-pr.yml +0 -183
- package/.github/workflows/reusable-npm-upgrade.yml +0 -92
- package/.github/workflows/reusable-pr-verify.yml +0 -181
- package/AGENTS.md +0 -105
- package/index.ts +0 -18
- package/jest.config.js +0 -17
- package/prettierrc.json +0 -5
- package/src/ConfigBase.spec.ts +0 -108
- package/src/ConfigBase.ts +0 -297
- package/src/DbUtils.spec.ts +0 -23
- package/src/DbUtils.ts +0 -116
- package/src/DbUtilsNoTelemetry.spec.ts +0 -168
- package/src/DbUtilsNoTelemetry.ts +0 -117
- package/src/LLM.spec.ts +0 -303
- package/src/LLM.ts +0 -204
- package/src/Notifications.spec.ts +0 -265
- package/src/Notifications.ts +0 -201
- package/src/OTelContext.spec.ts +0 -58
- package/src/OTelContext.ts +0 -63
- package/src/PostgresDbUtils.spec.ts +0 -153
- package/src/PostgresDbUtils.ts +0 -666
- package/src/SqlDbUtils.spec.ts +0 -108
- package/src/SqlDbUtils.ts +0 -152
- package/src/SystemCommand.spec.ts +0 -18
- package/src/SystemCommand.ts +0 -23
- package/src/Timeout.spec.ts +0 -18
- package/src/Timeout.ts +0 -12
- package/src/users/Auth.spec.ts +0 -268
- package/src/users/Auth.ts +0 -202
- package/src/users/User.ts +0 -75
- package/src/users/UserApiToken.ts +0 -55
- package/src/users/UserPassword.spec.ts +0 -28
- package/src/users/UserPassword.ts +0 -20
- package/src/users/UserSession.ts +0 -9
- package/src/users/UsersApiTokensData.spec.ts +0 -158
- package/src/users/UsersApiTokensData.ts +0 -125
- package/src/users/UsersData.ts +0 -141
- package/src/users/UsersRoutes.ts +0 -374
- package/tsconfig.json +0 -15
- package/tsconfig.spec.json +0 -8
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
name: "Reusable: Merge Build"
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_call:
|
|
5
|
-
inputs:
|
|
6
|
-
docker_platforms:
|
|
7
|
-
description: "Docker platforms, used only by the fallback build when no PR image can be promoted"
|
|
8
|
-
required: false
|
|
9
|
-
type: string
|
|
10
|
-
default: "linux/arm64/v8,linux/amd64"
|
|
11
|
-
node_app_directories:
|
|
12
|
-
description: "Deprecated and unused. Kept so existing callers stay valid: the merge build runs no build, lint or test."
|
|
13
|
-
required: false
|
|
14
|
-
type: string
|
|
15
|
-
default: ""
|
|
16
|
-
node_version:
|
|
17
|
-
description: "Deprecated and unused. Kept so existing callers stay valid: the merge build runs no Node.js job."
|
|
18
|
-
required: false
|
|
19
|
-
type: string
|
|
20
|
-
default: "22"
|
|
21
|
-
secrets:
|
|
22
|
-
DOCKER_HUB_USERNAME:
|
|
23
|
-
required: true
|
|
24
|
-
DOCKER_HUB_ACCESS_TOKEN:
|
|
25
|
-
required: true
|
|
26
|
-
QUALITY_DASHBOARD_TOKEN:
|
|
27
|
-
required: false
|
|
28
|
-
QUALITY_DASHBOARD_URL:
|
|
29
|
-
required: false
|
|
30
|
-
|
|
31
|
-
# Immutable build strategy: the image validated on the pull request is promoted
|
|
32
|
-
# as-is, so merging runs no build, lint or test.
|
|
33
|
-
#
|
|
34
|
-
# `contents: read` only. Callers run with the default read-only token, whose
|
|
35
|
-
# ceiling is `contents: read, pull-requests: none`, so requesting anything more
|
|
36
|
-
# here makes the caller fail to start with "Invalid workflow file". The PR is
|
|
37
|
-
# therefore resolved without needing pull-request scopes.
|
|
38
|
-
permissions:
|
|
39
|
-
contents: read
|
|
40
|
-
|
|
41
|
-
jobs:
|
|
42
|
-
promote-image:
|
|
43
|
-
runs-on: ubuntu-latest
|
|
44
|
-
steps:
|
|
45
|
-
- uses: actions/checkout@v7
|
|
46
|
-
|
|
47
|
-
- name: Set up QEMU
|
|
48
|
-
uses: docker/setup-qemu-action@v4
|
|
49
|
-
|
|
50
|
-
- name: Set up Docker Buildx
|
|
51
|
-
uses: docker/setup-buildx-action@v4
|
|
52
|
-
|
|
53
|
-
- name: Login to Docker Hub
|
|
54
|
-
uses: docker/login-action@v4
|
|
55
|
-
with:
|
|
56
|
-
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
|
57
|
-
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
|
58
|
-
|
|
59
|
-
- name: Resolve the image validated by the merged PR
|
|
60
|
-
id: resolve
|
|
61
|
-
env:
|
|
62
|
-
GH_TOKEN: ${{ github.token }}
|
|
63
|
-
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
|
|
64
|
-
run: |
|
|
65
|
-
set -e
|
|
66
|
-
SERVICE_NAME=$(jq -r '.name' package.json)
|
|
67
|
-
SERVICE_VERSION=$(jq -r '.version' package.json)
|
|
68
|
-
IMAGE="${DOCKER_HUB_USERNAME}/${SERVICE_NAME}"
|
|
69
|
-
|
|
70
|
-
PR_NUMBER=""
|
|
71
|
-
PR_SOURCE="none"
|
|
72
|
-
|
|
73
|
-
# Preferred: ask the API which PR introduced this commit. This needs
|
|
74
|
-
# `pull-requests: read`, which callers on the default token are not
|
|
75
|
-
# granted, so a failure here is expected rather than exceptional.
|
|
76
|
-
PR_NUMBER=$(curl -sfL \
|
|
77
|
-
-H "Authorization: Bearer ${GH_TOKEN}" \
|
|
78
|
-
-H "Accept: application/vnd.github+json" \
|
|
79
|
-
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/pulls" \
|
|
80
|
-
| jq -r '.[0].number // empty' || true)
|
|
81
|
-
if [ -n "${PR_NUMBER}" ]; then
|
|
82
|
-
PR_SOURCE="api"
|
|
83
|
-
fi
|
|
84
|
-
|
|
85
|
-
# Fallback: parse the commit title, where GitHub writes the PR number
|
|
86
|
-
# for squash ("<title> (#123)") and merge ("Merge pull request #123")
|
|
87
|
-
# commits. Only the title is read, so a "fixes #99" reference in the
|
|
88
|
-
# commit body cannot select the wrong pull request.
|
|
89
|
-
if [ -z "${PR_NUMBER}" ]; then
|
|
90
|
-
TITLE=$(git log -1 --pretty=%s)
|
|
91
|
-
PR_NUMBER=$(printf '%s' "${TITLE}" | grep -oE '\(#[0-9]+\)' | tail -1 | tr -d '(#)' || true)
|
|
92
|
-
if [ -z "${PR_NUMBER}" ]; then
|
|
93
|
-
PR_NUMBER=$(printf '%s' "${TITLE}" | grep -oE 'Merge pull request #[0-9]+' | grep -oE '[0-9]+' | head -1 || true)
|
|
94
|
-
fi
|
|
95
|
-
if [ -n "${PR_NUMBER}" ]; then
|
|
96
|
-
PR_SOURCE="commit-title"
|
|
97
|
-
fi
|
|
98
|
-
fi
|
|
99
|
-
|
|
100
|
-
SOURCE_IMAGE=""
|
|
101
|
-
if [ -z "${PR_NUMBER}" ]; then
|
|
102
|
-
echo "::warning::No pull request found for ${GITHUB_SHA}, falling back to a build."
|
|
103
|
-
else
|
|
104
|
-
CANDIDATE="${IMAGE}:beta-pr-${PR_NUMBER}"
|
|
105
|
-
if docker buildx imagetools inspect "${CANDIDATE}" > /dev/null 2>&1; then
|
|
106
|
-
SOURCE_IMAGE="${CANDIDATE}"
|
|
107
|
-
else
|
|
108
|
-
echo "::warning::${CANDIDATE} not found in the registry, falling back to a build."
|
|
109
|
-
fi
|
|
110
|
-
fi
|
|
111
|
-
|
|
112
|
-
if [ -n "${SOURCE_IMAGE}" ]; then
|
|
113
|
-
STRATEGY="retag"
|
|
114
|
-
else
|
|
115
|
-
STRATEGY="build"
|
|
116
|
-
fi
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
echo "image=${IMAGE}"
|
|
120
|
-
echo "service_name=${SERVICE_NAME}"
|
|
121
|
-
echo "service_version=${SERVICE_VERSION}"
|
|
122
|
-
echo "pr_number=${PR_NUMBER}"
|
|
123
|
-
echo "pr_source=${PR_SOURCE}"
|
|
124
|
-
echo "source_image=${SOURCE_IMAGE}"
|
|
125
|
-
echo "strategy=${STRATEGY}"
|
|
126
|
-
} >> "${GITHUB_OUTPUT}"
|
|
127
|
-
|
|
128
|
-
echo "Service: ${SERVICE_NAME} ${SERVICE_VERSION}"
|
|
129
|
-
echo "PR: ${PR_NUMBER:-none} (resolved via ${PR_SOURCE})"
|
|
130
|
-
echo "Source: ${SOURCE_IMAGE:-none}"
|
|
131
|
-
echo "Strategy: ${STRATEGY}"
|
|
132
|
-
|
|
133
|
-
- name: Promote the PR image to the release tags
|
|
134
|
-
if: steps.resolve.outputs.strategy == 'retag'
|
|
135
|
-
env:
|
|
136
|
-
RELEASE_IMAGE: ${{ steps.resolve.outputs.image }}
|
|
137
|
-
RELEASE_VERSION: ${{ steps.resolve.outputs.service_version }}
|
|
138
|
-
SOURCE_IMAGE: ${{ steps.resolve.outputs.source_image }}
|
|
139
|
-
MERGED_PR_NUMBER: ${{ steps.resolve.outputs.pr_number }}
|
|
140
|
-
run: |
|
|
141
|
-
set -e
|
|
142
|
-
MAJOR=$(echo "${RELEASE_VERSION}" | cut -f1 -d".")
|
|
143
|
-
MINOR=$(echo "${RELEASE_VERSION}" | cut -f1-2 -d".")
|
|
144
|
-
|
|
145
|
-
SOURCE_DIGEST=$(docker buildx imagetools inspect "${SOURCE_IMAGE}" --format '{{.Manifest.Digest}}')
|
|
146
|
-
|
|
147
|
-
echo "Promoting ${SOURCE_IMAGE} (PR #${MERGED_PR_NUMBER})"
|
|
148
|
-
echo " digest ${SOURCE_DIGEST}"
|
|
149
|
-
echo " -> ${RELEASE_IMAGE}:${RELEASE_VERSION}"
|
|
150
|
-
echo " -> ${RELEASE_IMAGE}:${MAJOR}"
|
|
151
|
-
echo " -> ${RELEASE_IMAGE}:${MINOR}"
|
|
152
|
-
echo " -> ${RELEASE_IMAGE}:latest"
|
|
153
|
-
|
|
154
|
-
# --prefer-index=false forces a carbon copy of the source manifest, so
|
|
155
|
-
# the released image keeps the exact digest validated on the pull
|
|
156
|
-
# request. Without it, a single-platform source would be rewrapped into
|
|
157
|
-
# a new image index and the digest would change.
|
|
158
|
-
docker buildx imagetools create \
|
|
159
|
-
--prefer-index=false \
|
|
160
|
-
-t "${RELEASE_IMAGE}:${RELEASE_VERSION}" \
|
|
161
|
-
-t "${RELEASE_IMAGE}:${MAJOR}" \
|
|
162
|
-
-t "${RELEASE_IMAGE}:${MINOR}" \
|
|
163
|
-
-t "${RELEASE_IMAGE}:latest" \
|
|
164
|
-
"${SOURCE_IMAGE}"
|
|
165
|
-
|
|
166
|
-
# Fail loudly rather than publish an artifact that differs from the one
|
|
167
|
-
# tested on the pull request.
|
|
168
|
-
for TAG in "${RELEASE_VERSION}" "${MAJOR}" "${MINOR}" "latest"; do
|
|
169
|
-
PROMOTED_DIGEST=$(docker buildx imagetools inspect "${RELEASE_IMAGE}:${TAG}" --format '{{.Manifest.Digest}}')
|
|
170
|
-
if [ "${PROMOTED_DIGEST}" != "${SOURCE_DIGEST}" ]; then
|
|
171
|
-
echo "::error::${RELEASE_IMAGE}:${TAG} has digest ${PROMOTED_DIGEST}, expected ${SOURCE_DIGEST}"
|
|
172
|
-
exit 1
|
|
173
|
-
fi
|
|
174
|
-
echo " verified ${RELEASE_IMAGE}:${TAG} -> ${PROMOTED_DIGEST}"
|
|
175
|
-
done
|
|
176
|
-
|
|
177
|
-
- name: Build and Push Docker Image (fallback)
|
|
178
|
-
if: steps.resolve.outputs.strategy == 'build'
|
|
179
|
-
env:
|
|
180
|
-
RELEASE_IMAGE: ${{ steps.resolve.outputs.image }}
|
|
181
|
-
RELEASE_VERSION: ${{ steps.resolve.outputs.service_version }}
|
|
182
|
-
DOCKER_PLATFORMS: ${{ inputs.docker_platforms }}
|
|
183
|
-
run: |
|
|
184
|
-
set -e
|
|
185
|
-
MAJOR=$(echo "${RELEASE_VERSION}" | cut -f1 -d".")
|
|
186
|
-
MINOR=$(echo "${RELEASE_VERSION}" | cut -f1-2 -d".")
|
|
187
|
-
|
|
188
|
-
echo "Building ${RELEASE_IMAGE}:${RELEASE_VERSION} from ${GITHUB_SHA}"
|
|
189
|
-
docker buildx build \
|
|
190
|
-
--platform "${DOCKER_PLATFORMS}" \
|
|
191
|
-
--push \
|
|
192
|
-
-f Dockerfile \
|
|
193
|
-
-t "${RELEASE_IMAGE}:latest" \
|
|
194
|
-
-t "${RELEASE_IMAGE}:${RELEASE_VERSION}" \
|
|
195
|
-
-t "${RELEASE_IMAGE}:${MAJOR}" \
|
|
196
|
-
-t "${RELEASE_IMAGE}:${MINOR}" \
|
|
197
|
-
.
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
name: "Reusable: NPM Merge"
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_call:
|
|
5
|
-
inputs:
|
|
6
|
-
node_version:
|
|
7
|
-
description: "Node.js version to use"
|
|
8
|
-
required: false
|
|
9
|
-
type: string
|
|
10
|
-
default: "22"
|
|
11
|
-
npm_package_name:
|
|
12
|
-
description: "NPM package name (e.g. @devopsplaybook.io/otel-utils)"
|
|
13
|
-
required: true
|
|
14
|
-
type: string
|
|
15
|
-
secrets:
|
|
16
|
-
NPM_TOKEN:
|
|
17
|
-
required: true
|
|
18
|
-
QUALITY_DASHBOARD_TOKEN:
|
|
19
|
-
required: false
|
|
20
|
-
QUALITY_DASHBOARD_URL:
|
|
21
|
-
required: false
|
|
22
|
-
|
|
23
|
-
jobs:
|
|
24
|
-
test-and-build:
|
|
25
|
-
runs-on: ubuntu-latest
|
|
26
|
-
|
|
27
|
-
steps:
|
|
28
|
-
- uses: actions/checkout@v7
|
|
29
|
-
|
|
30
|
-
- name: Setup Node.js
|
|
31
|
-
uses: actions/setup-node@v7
|
|
32
|
-
with:
|
|
33
|
-
node-version: ${{ inputs.node_version }}
|
|
34
|
-
cache: "npm"
|
|
35
|
-
|
|
36
|
-
- name: Install dependencies
|
|
37
|
-
run: npm ci
|
|
38
|
-
|
|
39
|
-
- name: Run linting
|
|
40
|
-
run: npm run lint
|
|
41
|
-
|
|
42
|
-
- name: Run tests
|
|
43
|
-
run: npm test
|
|
44
|
-
|
|
45
|
-
- name: Zip coverage and upload to Quality Dashboard
|
|
46
|
-
if: always()
|
|
47
|
-
env:
|
|
48
|
-
QUALITY_DASHBOARD_URL: ${{ secrets.QUALITY_DASHBOARD_URL }}
|
|
49
|
-
QUALITY_DASHBOARD_TOKEN: ${{ secrets.QUALITY_DASHBOARD_TOKEN }}
|
|
50
|
-
run: |
|
|
51
|
-
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
52
|
-
REPORT_KEY=$(echo "$PACKAGE_NAME" | sed 's/[^a-zA-Z0-9._:\-\/]/_/g')
|
|
53
|
-
REPORT_KEY="${REPORT_KEY}_coverage"
|
|
54
|
-
|
|
55
|
-
if [ -d coverage ]; then
|
|
56
|
-
if [ -z "$QUALITY_DASHBOARD_URL" ] || [ -z "$QUALITY_DASHBOARD_TOKEN" ]; then
|
|
57
|
-
echo "Quality Dashboard URL or token not set, skipping upload"
|
|
58
|
-
exit 0
|
|
59
|
-
fi
|
|
60
|
-
# Zip coverage contents at root level so the jest processor
|
|
61
|
-
# finds coverage-final.json / clover.xml directly
|
|
62
|
-
(cd coverage && zip -r "${{ runner.temp }}/coverage.zip" .)
|
|
63
|
-
|
|
64
|
-
META=$(jq -n \
|
|
65
|
-
--arg key "$REPORT_KEY" \
|
|
66
|
-
--arg pkg "$PACKAGE_NAME" \
|
|
67
|
-
'{
|
|
68
|
-
key: $key,
|
|
69
|
-
displayName: "Coverage: \($pkg)",
|
|
70
|
-
processor: "jest"
|
|
71
|
-
}')
|
|
72
|
-
|
|
73
|
-
echo "Uploading coverage: $REPORT_KEY"
|
|
74
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
75
|
-
-X POST "$QUALITY_DASHBOARD_URL/api/reports/" \
|
|
76
|
-
-H "x-upload-token: $QUALITY_DASHBOARD_TOKEN" \
|
|
77
|
-
-F "meta=$META" \
|
|
78
|
-
-F "file=@${{ runner.temp }}/coverage.zip" \
|
|
79
|
-
--max-time 30)
|
|
80
|
-
|
|
81
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
82
|
-
echo "\u2713 Coverage uploaded ($HTTP_CODE)"
|
|
83
|
-
else
|
|
84
|
-
echo "\u26a0 Upload returned HTTP $HTTP_CODE"
|
|
85
|
-
fi
|
|
86
|
-
else
|
|
87
|
-
echo "No coverage/ directory found, skipping upload"
|
|
88
|
-
fi
|
|
89
|
-
|
|
90
|
-
- name: Build package
|
|
91
|
-
run: npm run build
|
|
92
|
-
|
|
93
|
-
publish-release:
|
|
94
|
-
runs-on: ubuntu-latest
|
|
95
|
-
needs: test-and-build
|
|
96
|
-
|
|
97
|
-
steps:
|
|
98
|
-
- uses: actions/checkout@v7
|
|
99
|
-
with:
|
|
100
|
-
fetch-depth: 0
|
|
101
|
-
|
|
102
|
-
- name: Setup Node.js
|
|
103
|
-
uses: actions/setup-node@v7
|
|
104
|
-
with:
|
|
105
|
-
node-version: ${{ inputs.node_version }}
|
|
106
|
-
cache: "npm"
|
|
107
|
-
registry-url: "https://registry.npmjs.org"
|
|
108
|
-
|
|
109
|
-
- name: Install dependencies
|
|
110
|
-
run: npm ci
|
|
111
|
-
|
|
112
|
-
- name: Build package
|
|
113
|
-
run: npm run build
|
|
114
|
-
|
|
115
|
-
- name: Check if version changed
|
|
116
|
-
id: version-check
|
|
117
|
-
run: |
|
|
118
|
-
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
119
|
-
echo "current-version=${CURRENT_VERSION}" >> $GITHUB_OUTPUT
|
|
120
|
-
|
|
121
|
-
if npm view ${{ inputs.npm_package_name }}@${CURRENT_VERSION} version &> /dev/null; then
|
|
122
|
-
echo "version-exists=true" >> $GITHUB_OUTPUT
|
|
123
|
-
echo "Version ${CURRENT_VERSION} already exists on npm"
|
|
124
|
-
else
|
|
125
|
-
echo "version-exists=false" >> $GITHUB_OUTPUT
|
|
126
|
-
echo "Version ${CURRENT_VERSION} is new, will publish"
|
|
127
|
-
fi
|
|
128
|
-
|
|
129
|
-
- name: Publish release package
|
|
130
|
-
if: steps.version-check.outputs.version-exists == 'false'
|
|
131
|
-
run: |
|
|
132
|
-
echo "Publishing version ${{ steps.version-check.outputs.current-version }}"
|
|
133
|
-
npm publish
|
|
134
|
-
env:
|
|
135
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
name: "Reusable: NPM PR"
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_call:
|
|
5
|
-
inputs:
|
|
6
|
-
node_version:
|
|
7
|
-
description: "Node.js version to use"
|
|
8
|
-
required: false
|
|
9
|
-
type: string
|
|
10
|
-
default: "22"
|
|
11
|
-
npm_package_name:
|
|
12
|
-
description: "NPM package name (e.g. @devopsplaybook.io/otel-utils)"
|
|
13
|
-
required: true
|
|
14
|
-
type: string
|
|
15
|
-
secrets:
|
|
16
|
-
NPM_TOKEN:
|
|
17
|
-
required: true
|
|
18
|
-
QUALITY_DASHBOARD_TOKEN:
|
|
19
|
-
required: false
|
|
20
|
-
QUALITY_DASHBOARD_URL:
|
|
21
|
-
required: false
|
|
22
|
-
|
|
23
|
-
jobs:
|
|
24
|
-
version-check:
|
|
25
|
-
runs-on: ubuntu-latest
|
|
26
|
-
steps:
|
|
27
|
-
- uses: actions/checkout@v7
|
|
28
|
-
|
|
29
|
-
- name: Fetch main branch
|
|
30
|
-
run: git fetch origin main --depth=1
|
|
31
|
-
|
|
32
|
-
- name: Verify version is higher than main
|
|
33
|
-
run: |
|
|
34
|
-
PR_VERSION=$(jq -r '.version' package.json)
|
|
35
|
-
MAIN_VERSION=$(git show origin/main:package.json | jq -r '.version')
|
|
36
|
-
|
|
37
|
-
echo "PR version: ${PR_VERSION}"
|
|
38
|
-
echo "Main version: ${MAIN_VERSION}"
|
|
39
|
-
|
|
40
|
-
if [ "$PR_VERSION" = "$MAIN_VERSION" ]; then
|
|
41
|
-
echo "::error::PR version (${PR_VERSION}) must be higher than main branch version (${MAIN_VERSION}). Please bump the version in package.json."
|
|
42
|
-
exit 1
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
HIGHER=$(printf '%s\n%s' "$PR_VERSION" "$MAIN_VERSION" | sort -V | tail -n1)
|
|
46
|
-
if [ "$HIGHER" != "$PR_VERSION" ]; then
|
|
47
|
-
echo "::error::PR version (${PR_VERSION}) is lower than main branch version (${MAIN_VERSION}). Please bump the version in package.json."
|
|
48
|
-
exit 1
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
echo "Version check passed: ${PR_VERSION} > ${MAIN_VERSION}"
|
|
52
|
-
|
|
53
|
-
test-and-build:
|
|
54
|
-
needs: version-check
|
|
55
|
-
runs-on: ubuntu-latest
|
|
56
|
-
|
|
57
|
-
steps:
|
|
58
|
-
- uses: actions/checkout@v7
|
|
59
|
-
|
|
60
|
-
- name: Setup Node.js
|
|
61
|
-
uses: actions/setup-node@v7
|
|
62
|
-
with:
|
|
63
|
-
node-version: ${{ inputs.node_version }}
|
|
64
|
-
cache: "npm"
|
|
65
|
-
|
|
66
|
-
- name: Install dependencies
|
|
67
|
-
run: npm ci
|
|
68
|
-
|
|
69
|
-
- name: Run linting
|
|
70
|
-
run: npm run lint
|
|
71
|
-
|
|
72
|
-
- name: Run tests
|
|
73
|
-
run: npm test
|
|
74
|
-
|
|
75
|
-
- name: Zip coverage and upload to Quality Dashboard
|
|
76
|
-
if: always()
|
|
77
|
-
env:
|
|
78
|
-
QUALITY_DASHBOARD_URL: ${{ secrets.QUALITY_DASHBOARD_URL }}
|
|
79
|
-
QUALITY_DASHBOARD_TOKEN: ${{ secrets.QUALITY_DASHBOARD_TOKEN }}
|
|
80
|
-
run: |
|
|
81
|
-
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
82
|
-
REPORT_KEY=$(echo "$PACKAGE_NAME" | sed 's/[^a-zA-Z0-9._:\-\/]/_/g')
|
|
83
|
-
REPORT_KEY="${REPORT_KEY}_coverage"
|
|
84
|
-
|
|
85
|
-
if [ -d coverage ]; then
|
|
86
|
-
if [ -z "$QUALITY_DASHBOARD_URL" ] || [ -z "$QUALITY_DASHBOARD_TOKEN" ]; then
|
|
87
|
-
echo "Quality Dashboard URL or token not set, skipping upload"
|
|
88
|
-
exit 0
|
|
89
|
-
fi
|
|
90
|
-
# Zip coverage contents at root level so the jest processor
|
|
91
|
-
# finds coverage-final.json / clover.xml directly
|
|
92
|
-
(cd coverage && zip -r "${{ runner.temp }}/coverage.zip" .)
|
|
93
|
-
|
|
94
|
-
META=$(jq -n \
|
|
95
|
-
--arg key "$REPORT_KEY" \
|
|
96
|
-
--arg pkg "$PACKAGE_NAME" \
|
|
97
|
-
'{
|
|
98
|
-
key: $key,
|
|
99
|
-
displayName: "Coverage: \($pkg)",
|
|
100
|
-
processor: "jest"
|
|
101
|
-
}')
|
|
102
|
-
|
|
103
|
-
echo "Uploading coverage: $REPORT_KEY"
|
|
104
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
105
|
-
-X POST "$QUALITY_DASHBOARD_URL/api/reports/" \
|
|
106
|
-
-H "x-upload-token: $QUALITY_DASHBOARD_TOKEN" \
|
|
107
|
-
-F "meta=$META" \
|
|
108
|
-
-F "file=@${{ runner.temp }}/coverage.zip" \
|
|
109
|
-
--max-time 30)
|
|
110
|
-
|
|
111
|
-
if [ "$HTTP_CODE" = "201" ]; then
|
|
112
|
-
echo "\u2713 Coverage uploaded ($HTTP_CODE)"
|
|
113
|
-
else
|
|
114
|
-
echo "\u26a0 Upload returned HTTP $HTTP_CODE"
|
|
115
|
-
fi
|
|
116
|
-
else
|
|
117
|
-
echo "No coverage/ directory found, skipping upload"
|
|
118
|
-
fi
|
|
119
|
-
|
|
120
|
-
- name: Build package
|
|
121
|
-
run: npm run build
|
|
122
|
-
|
|
123
|
-
publish-beta:
|
|
124
|
-
runs-on: ubuntu-latest
|
|
125
|
-
needs: test-and-build
|
|
126
|
-
if: github.event_name == 'pull_request'
|
|
127
|
-
|
|
128
|
-
steps:
|
|
129
|
-
- uses: actions/checkout@v7
|
|
130
|
-
|
|
131
|
-
- name: Setup Node.js
|
|
132
|
-
uses: actions/setup-node@v7
|
|
133
|
-
with:
|
|
134
|
-
node-version: ${{ inputs.node_version }}
|
|
135
|
-
cache: "npm"
|
|
136
|
-
registry-url: "https://registry.npmjs.org"
|
|
137
|
-
|
|
138
|
-
- name: Install dependencies
|
|
139
|
-
run: npm ci
|
|
140
|
-
|
|
141
|
-
- name: Build package
|
|
142
|
-
run: npm run build
|
|
143
|
-
|
|
144
|
-
- name: Generate beta version
|
|
145
|
-
id: beta-version
|
|
146
|
-
run: |
|
|
147
|
-
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
148
|
-
PR_NUMBER=${{ github.event.pull_request.number }}
|
|
149
|
-
COMMIT_SHA=${GITHUB_SHA:0:7}
|
|
150
|
-
BETA_VERSION="${CURRENT_VERSION}-beta.${PR_NUMBER}.${COMMIT_SHA}"
|
|
151
|
-
echo "version=${BETA_VERSION}" >> $GITHUB_OUTPUT
|
|
152
|
-
echo "Beta version will be: ${BETA_VERSION}"
|
|
153
|
-
|
|
154
|
-
- name: Update package.json with beta version
|
|
155
|
-
run: |
|
|
156
|
-
npm version ${{ steps.beta-version.outputs.version }} --no-git-tag-version
|
|
157
|
-
|
|
158
|
-
- name: Publish beta package
|
|
159
|
-
run: npm publish --tag beta
|
|
160
|
-
env:
|
|
161
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
162
|
-
|
|
163
|
-
- name: Comment PR with beta version info
|
|
164
|
-
uses: actions/github-script@v9
|
|
165
|
-
with:
|
|
166
|
-
script: |
|
|
167
|
-
github.rest.issues.createComment({
|
|
168
|
-
issue_number: context.issue.number,
|
|
169
|
-
owner: context.repo.owner,
|
|
170
|
-
repo: context.repo.repo,
|
|
171
|
-
body: `🚀 **Beta version published!**
|
|
172
|
-
|
|
173
|
-
**Package**: \`${{ inputs.npm_package_name }}@${{ steps.beta-version.outputs.version }}\`
|
|
174
|
-
|
|
175
|
-
Install with:
|
|
176
|
-
\`\`\`bash
|
|
177
|
-
npm install ${{ inputs.npm_package_name }}@${{ steps.beta-version.outputs.version }}
|
|
178
|
-
# or
|
|
179
|
-
npm install ${{ inputs.npm_package_name }}@beta
|
|
180
|
-
\`\`\`
|
|
181
|
-
|
|
182
|
-
This beta version will be available for testing until the PR is merged.`
|
|
183
|
-
})
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
name: "Reusable: NPM Upgrade"
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_call:
|
|
5
|
-
inputs:
|
|
6
|
-
npm_services:
|
|
7
|
-
description: "JSON array of sub-folders containing NPM services to update"
|
|
8
|
-
required: true
|
|
9
|
-
type: string
|
|
10
|
-
pr_branch:
|
|
11
|
-
description: "Branch name for the upgrade PR (defaults to feature/YYYY.MM.DD-dependency-updates)"
|
|
12
|
-
required: false
|
|
13
|
-
type: string
|
|
14
|
-
default: ""
|
|
15
|
-
|
|
16
|
-
jobs:
|
|
17
|
-
npm-upgrade:
|
|
18
|
-
runs-on: ubuntu-latest
|
|
19
|
-
permissions:
|
|
20
|
-
contents: write
|
|
21
|
-
pull-requests: write
|
|
22
|
-
steps:
|
|
23
|
-
- uses: actions/checkout@v7
|
|
24
|
-
|
|
25
|
-
- name: Resolve branch name
|
|
26
|
-
id: branch
|
|
27
|
-
run: |
|
|
28
|
-
if [ -n "${{ inputs.pr_branch }}" ]; then
|
|
29
|
-
echo "name=${{ inputs.pr_branch }}" >> $GITHUB_OUTPUT
|
|
30
|
-
else
|
|
31
|
-
echo "name=feature/$(date +'%Y.%m.%d')-dependency-updates" >> $GITHUB_OUTPUT
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
- name: Check for existing PR
|
|
35
|
-
id: check_pr
|
|
36
|
-
env:
|
|
37
|
-
GH_TOKEN: ${{ github.token }}
|
|
38
|
-
run: |
|
|
39
|
-
EXISTING_PR=$(gh pr list --state open --json number --jq 'length')
|
|
40
|
-
if [ "${EXISTING_PR}" -gt 0 ]; then
|
|
41
|
-
echo "An open PR already exists, skipping"
|
|
42
|
-
echo "skip=true" >> $GITHUB_OUTPUT
|
|
43
|
-
else
|
|
44
|
-
echo "skip=false" >> $GITHUB_OUTPUT
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
- name: Update NPM dependencies
|
|
48
|
-
if: steps.check_pr.outputs.skip == 'false'
|
|
49
|
-
run: |
|
|
50
|
-
set -e
|
|
51
|
-
# Update root package
|
|
52
|
-
echo "Updating dependencies in root"
|
|
53
|
-
npx npm-check-updates -u
|
|
54
|
-
npm install
|
|
55
|
-
# Update sub-service packages
|
|
56
|
-
SERVICES='${{ inputs.npm_services }}'
|
|
57
|
-
for FOLDER in $(echo "${SERVICES}" | jq -r '.[]'); do
|
|
58
|
-
echo "Updating dependencies in ${FOLDER}"
|
|
59
|
-
cd "${FOLDER}"
|
|
60
|
-
npx npm-check-updates -u
|
|
61
|
-
npm install
|
|
62
|
-
cd "${GITHUB_WORKSPACE}"
|
|
63
|
-
done
|
|
64
|
-
if [ -n "$(git status --porcelain)" ]; then
|
|
65
|
-
echo "HAS_CHANGES=true" >> $GITHUB_ENV
|
|
66
|
-
fi
|
|
67
|
-
|
|
68
|
-
- name: Bump root package.json patch version
|
|
69
|
-
if: steps.check_pr.outputs.skip == 'false' && env.HAS_CHANGES == 'true'
|
|
70
|
-
run: |
|
|
71
|
-
set -e
|
|
72
|
-
CURRENT_VERSION=$(jq -r '.version' package.json)
|
|
73
|
-
NEW_VERSION=$(echo "${CURRENT_VERSION}" | awk -F. '{print $1"."$2"."$3+1}')
|
|
74
|
-
jq --arg v "${NEW_VERSION}" '.version = $v' package.json > package.json.tmp && mv package.json.tmp package.json
|
|
75
|
-
echo "Bumped root package.json version: ${CURRENT_VERSION} -> ${NEW_VERSION}"
|
|
76
|
-
|
|
77
|
-
- name: Create Pull Request
|
|
78
|
-
if: steps.check_pr.outputs.skip == 'false' && env.HAS_CHANGES == 'true'
|
|
79
|
-
env:
|
|
80
|
-
GH_TOKEN: ${{ github.token }}
|
|
81
|
-
run: |
|
|
82
|
-
git config user.name "github-actions[bot]"
|
|
83
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
84
|
-
git checkout -b "${{ steps.branch.outputs.name }}"
|
|
85
|
-
git add -A
|
|
86
|
-
git commit -m "chore: update NPM dependencies"
|
|
87
|
-
git push origin "${{ steps.branch.outputs.name }}"
|
|
88
|
-
gh pr create \
|
|
89
|
-
--title "chore: update NPM dependencies" \
|
|
90
|
-
--body "Automated NPM dependency update" \
|
|
91
|
-
--head "${{ steps.branch.outputs.name }}" \
|
|
92
|
-
--base main
|