@codfish/actions 0.0.0-PR-58--24ced07

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.
@@ -0,0 +1,228 @@
1
+ name: setup-node-and-install
2
+
3
+ description:
4
+ Sets up Node.js environment and installs dependencies with automatic package manager detection (npm/pnpm/yarn),
5
+ intelligent caching, and version detection via input, .node-version, .nvmrc, or package.json volta.node
6
+
7
+ inputs:
8
+ node-version:
9
+ description:
10
+ 'Node.js version to install (e.g. "24", "lts/*"). Precedence: node-version input > .node-version > .nvmrc >
11
+ package.json volta.node.'
12
+ required: false
13
+ install-options:
14
+ description: Extra command-line options to pass to npm/pnpm/yarn install.
15
+ default: ''
16
+ working-directory:
17
+ description: Directory containing package.json and lockfile.
18
+ default: .
19
+ registry-url:
20
+ description:
21
+ 'Optional registry URL to configure for publishing (e.g. "https://registry.npmjs.org/"). Creates .npmrc with
22
+ NODE_AUTH_TOKEN placeholder. NOT recommended if using semantic-release (it handles auth independently). Only
23
+ needed for publishing with manual npm publish or other non-semantic-release workflows.'
24
+ required: false
25
+ upgrade-npm:
26
+ description:
27
+ Whether to upgrade npm to v11.5.1. This is required for OIDC trusted publishing but can be disabled if you want to
28
+ shave off some run time and you are still using token-based authentication.
29
+ default: true
30
+
31
+ outputs:
32
+ node-version:
33
+ description: The installed node version.
34
+ value: ${{ steps.setup-node.outputs.node-version }}
35
+ cache-hit:
36
+ description: Whether the dependency cache was hit (true/false).
37
+ value: "${{ steps.setup-node.outputs.cache-hit == 'true' && 'true' || 'false' }}"
38
+ pnpm-dest:
39
+ description: Expanded path of pnpm dest.
40
+ value: ${{ steps.pnpm-setup.outputs.dest }}
41
+ pnpm-bin-dest:
42
+ description: Location of pnpm and pnpx command.
43
+ value: ${{ steps.pnpm-setup.outputs.bin_dest }}
44
+
45
+ runs:
46
+ using: composite
47
+
48
+ steps:
49
+ - name: Validate environment and detect package manager
50
+ id: detect-package-manager
51
+ working-directory: ${{ inputs.working-directory }}
52
+ shell: bash
53
+ run: |
54
+ # Validate package.json exists
55
+ if [ ! -f "./package.json" ]; then
56
+ echo "❌ ERROR: package.json not found in '${{ inputs.working-directory }}'"
57
+ echo "Make sure the working-directory contains a valid Node.js project"
58
+ exit 1
59
+ fi
60
+
61
+ # Detect package manager based on lockfiles (including yarn)
62
+ if [ -f "./pnpm-lock.yaml" ]; then
63
+ echo "package-manager=pnpm" >> $GITHUB_OUTPUT
64
+ echo "lockfile-exists=true" >> $GITHUB_OUTPUT
65
+ echo "lockfile-path=pnpm-lock.yaml" >> $GITHUB_OUTPUT
66
+ echo "📦 Detected package manager: pnpm"
67
+ elif [ -f "./yarn.lock" ]; then
68
+ echo "package-manager=yarn" >> $GITHUB_OUTPUT
69
+ echo "lockfile-exists=true" >> $GITHUB_OUTPUT
70
+ echo "lockfile-path=yarn.lock" >> $GITHUB_OUTPUT
71
+ echo "📦 Detected package manager: yarn"
72
+ elif [ -f "./package-lock.json" ]; then
73
+ echo "package-manager=npm" >> $GITHUB_OUTPUT
74
+ echo "lockfile-exists=true" >> $GITHUB_OUTPUT
75
+ echo "lockfile-path=package-lock.json" >> $GITHUB_OUTPUT
76
+ echo "📦 Detected package manager: npm"
77
+ else
78
+ echo "package-manager=npm" >> $GITHUB_OUTPUT
79
+ echo "lockfile-exists=false" >> $GITHUB_OUTPUT
80
+ echo "lockfile-path=" >> $GITHUB_OUTPUT
81
+ echo "📦 No lockfile found, defaulting to: npm"
82
+ fi
83
+
84
+ - name: Install pnpm
85
+ if: steps.detect-package-manager.outputs.package-manager == 'pnpm'
86
+ uses: pnpm/action-setup@v4
87
+ id: pnpm-setup
88
+ with:
89
+ run_install: false
90
+
91
+ # Detect Node.js version to use (input > .node-version > .nvmrc > package.json volta.node)
92
+ - name: Detect node version
93
+ id: detect-node-version
94
+ working-directory: ${{ inputs.working-directory }}
95
+ shell: bash
96
+ run: |
97
+ resolved_version=""
98
+
99
+ if [ -n "${INPUT_NODE_VERSION}" ]; then
100
+ resolved_version="$INPUT_NODE_VERSION"
101
+ echo "📋 Using Node version from input: $resolved_version"
102
+ elif [ -f "./.node-version" ]; then
103
+ file_version=$(cat ./.node-version | tr -d '\n\r' | xargs)
104
+ if [ -n "$file_version" ]; then
105
+ resolved_version="$file_version"
106
+ echo "📋 Using Node version from .node-version: $resolved_version"
107
+ fi
108
+ fi
109
+
110
+ if [ -z "$resolved_version" ] && [ -f "./.nvmrc" ]; then
111
+ nvmrc_version=$(cat ./.nvmrc | tr -d '\n\r' | xargs)
112
+ if [ -n "$nvmrc_version" ]; then
113
+ resolved_version="$nvmrc_version"
114
+ echo "📋 Using Node version from .nvmrc: $resolved_version"
115
+ fi
116
+ fi
117
+
118
+ if [ -z "$resolved_version" ]; then
119
+ volta_node=$(jq -r '.volta.node // empty' package.json 2>/dev/null || true)
120
+ if [ -n "$volta_node" ]; then
121
+ resolved_version="$volta_node"
122
+ echo "📋 Using Node version from package.json volta.node: $resolved_version"
123
+ fi
124
+ fi
125
+
126
+ echo "version=$resolved_version" >> $GITHUB_OUTPUT
127
+ env:
128
+ INPUT_NODE_VERSION: ${{ inputs.node-version }}
129
+
130
+ - name: Setup Node.js
131
+ uses: actions/setup-node@v6
132
+ id: setup-node
133
+ with:
134
+ # use detected package manager cache
135
+ cache: ${{ steps.detect-package-manager.outputs.package-manager }}
136
+ cache-dependency-path: ${{ inputs.working-directory }}
137
+ node-version: ${{ steps.detect-node-version.outputs.version }}
138
+ registry-url: ${{ inputs.registry-url }}
139
+
140
+ - name: Upgrade npm for OIDC support
141
+ if: inputs.upgrade-npm == 'true'
142
+ shell: bash
143
+ run: |
144
+ echo "📦 Current npm version: $(npm --version)"
145
+ echo "🔄 Upgrading npm to v11 (required for OIDC trusted publishing)..."
146
+ if ! npm install -g npm@^11.5.1; then
147
+ echo "❌ Failed to upgrade npm to v11.5.1. Check network access or permissions."
148
+ exit 1
149
+ fi
150
+ echo "✅ Updated to npm version: $(npm --version)"
151
+
152
+ # Apply `./node_modules` cache only if a lockfile is present and using `npm`
153
+ # Will remove the need to run install commands twice. Risk reduced by using a very specific cache key.
154
+ # Cache wont be used if the lockfile changes, package manager, node version, or OS changes.
155
+ - name: Setup node_modules dependency cache
156
+ if:
157
+ steps.detect-package-manager.outputs.lockfile-exists == 'true' &&
158
+ steps.detect-package-manager.outputs.package-manager == 'npm'
159
+ uses: actions/cache@v5
160
+ id: cache
161
+ with:
162
+ path: ${{ inputs.working-directory }}/node_modules
163
+ key:
164
+ ${{ runner.os }}-node_modules-${{ steps.detect-package-manager.outputs.package-manager }}-${{
165
+ steps.setup-node.outputs.node-version }}-${{ hashFiles(format('{0}/{1}', inputs.working-directory,
166
+ steps.detect-package-manager.outputs.lockfile-path)) }}
167
+
168
+ - name: Install dependencies with pnpm
169
+ if: steps.detect-package-manager.outputs.package-manager == 'pnpm' && steps.cache.outputs.cache-hit != 'true'
170
+ working-directory: ${{ inputs.working-directory }}
171
+ shell: bash
172
+ run: |
173
+ echo "🔧 Installing dependencies with pnpm..."
174
+ if [ "$LOCKFILE_EXISTS" = "true" ]; then
175
+ INPUT_INSTALL_OPTIONS="--frozen-lockfile $INPUT_INSTALL_OPTIONS"
176
+ else
177
+ echo "⚠️ Warning: No lockfile found, not using --frozen-lockfile"
178
+ fi
179
+ if ! pnpm i $INPUT_INSTALL_OPTIONS; then
180
+ echo "❌ ERROR: pnpm install failed"
181
+ exit 1
182
+ fi
183
+ echo "✅ pnpm install completed successfully"
184
+ env:
185
+ INPUT_INSTALL_OPTIONS: ${{ inputs.install-options }}
186
+ LOCKFILE_EXISTS: ${{ steps.detect-package-manager.outputs.lockfile-exists }}
187
+
188
+ - name: Install dependencies with yarn
189
+ if: steps.detect-package-manager.outputs.package-manager == 'yarn' && steps.cache.outputs.cache-hit != 'true'
190
+ working-directory: ${{ inputs.working-directory }}
191
+ shell: bash
192
+ run: |
193
+ echo "🔧 Installing dependencies with yarn..."
194
+ if [ "$LOCKFILE_EXISTS" = "true" ]; then
195
+ INPUT_INSTALL_OPTIONS="--frozen-lockfile $INPUT_INSTALL_OPTIONS"
196
+ else
197
+ echo "⚠️ Warning: No lockfile found, results may vary"
198
+ fi
199
+ if ! yarn install $INPUT_INSTALL_OPTIONS; then
200
+ echo "❌ ERROR: yarn install failed"
201
+ exit 1
202
+ fi
203
+ echo "✅ yarn install completed successfully"
204
+ env:
205
+ INPUT_INSTALL_OPTIONS: ${{ inputs.install-options }}
206
+ LOCKFILE_EXISTS: ${{ steps.detect-package-manager.outputs.lockfile-exists }}
207
+
208
+ - name: Install dependencies with npm
209
+ if: steps.detect-package-manager.outputs.package-manager == 'npm' && steps.cache.outputs.cache-hit != 'true'
210
+ working-directory: ${{ inputs.working-directory }}
211
+ shell: bash
212
+ run: |
213
+ NPM_CMD=""
214
+ if [ "$LOCKFILE_EXISTS" = "true" ]; then
215
+ NPM_CMD="ci"
216
+ else
217
+ echo "⚠️ Warning: No lockfile found, versions may vary"
218
+ NPM_CMD="install"
219
+ fi
220
+ echo "🔧 Installing dependencies with npm $NPM_CMD..."
221
+ if ! npm $NPM_CMD --no-save --prefer-offline --no-audit $INPUT_INSTALL_OPTIONS; then
222
+ echo "❌ ERROR: npm $NPM_CMD failed"
223
+ exit 1
224
+ fi
225
+ echo "✅ npm $NPM_CMD completed successfully"
226
+ env:
227
+ INPUT_INSTALL_OPTIONS: ${{ inputs.install-options }}
228
+ LOCKFILE_EXISTS: ${{ steps.detect-package-manager.outputs.lockfile-exists }}