Compare commits
4 Commits
5a1204fbcb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 322741e00c | |||
| da1e46a921 | |||
| 08a9983984 | |||
| e1e5daa30a |
@@ -753,8 +753,13 @@ pipelines</strong>:</p>
|
|||||||
the disaster-recovery / replay path.</li>
|
the disaster-recovery / replay path.</li>
|
||||||
</ol>
|
</ol>
|
||||||
<p>Secrets: <code>NPM_REPO_URL</code>, <code>NPM_USERNAME</code>, <code>NPM_PASSWORD</code>. Auth is a generated
|
<p>Secrets: <code>NPM_REPO_URL</code>, <code>NPM_USERNAME</code>, <code>NPM_PASSWORD</code>. Auth is a generated
|
||||||
<code>.npmrc</code> (<code>registry=</code> + <code>_auth=</code> base64 of <code>user:pass</code>) written from secrets at
|
<code>.npmrc</code> written from secrets at runtime. It sets a <strong>scope-scoped</strong> registry,
|
||||||
runtime — the committed <code>.npmrc</code> in a repo only points at the registry URL.</p>
|
never a global one — <code>@aetoskia:registry=$NPM_REPO_URL</code> — plus a host-scoped
|
||||||
|
auth line <code>//<host>/:_auth=<base64(user:pass)></code>. The scope and host are derived
|
||||||
|
from <code>package.json</code> and <code>NPM_REPO_URL</code> respectively. A global <code>registry=</code> would
|
||||||
|
push public transitive deps through Verdaccio (which has no uplink) and 404
|
||||||
|
<code>npm install</code>; a bare <code>_auth=</code> is rejected by modern npm. See
|
||||||
|
<a href="../93_library_registry/">93 – Library Registry</a>.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Ship as-is.</strong> Name and version come from <code>package.json</code>, so the same file
|
<li><strong>Ship as-is.</strong> Name and version come from <code>package.json</code>, so the same file
|
||||||
is reused verbatim across every npm package.</li>
|
is reused verbatim across every npm package.</li>
|
||||||
|
|||||||
@@ -635,6 +635,39 @@
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<nav class="md-nav" aria-label="Publishing & registry auth">
|
||||||
|
<ul class="md-nav__list">
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#endpoints" class="md-nav__link">
|
||||||
|
<span class="md-ellipsis">
|
||||||
|
Endpoints
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#npm-scope-the-registry-never-set-it-globally" class="md-nav__link">
|
||||||
|
<span class="md-ellipsis">
|
||||||
|
npm: scope the registry, never set it globally
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#verdaccio-storage-permissions" class="md-nav__link">
|
||||||
|
<span class="md-ellipsis">
|
||||||
|
Verdaccio storage permissions
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="md-nav__item">
|
<li class="md-nav__item">
|
||||||
@@ -839,6 +872,67 @@ so the CI credentials (<code>PIP_USERNAME</code> / <code>PIP_PASSWORD</code>, <c
|
|||||||
<code>NPM_PASSWORD</code>) are one and the same account — there is no separate npm user.
|
<code>NPM_PASSWORD</code>) are one and the same account — there is no separate npm user.
|
||||||
Verdaccio requires <strong>bcrypt</strong> htpasswd entries; see
|
Verdaccio requires <strong>bcrypt</strong> htpasswd entries; see
|
||||||
<a href="../90_drone_pipelines/">90 – Drone Pipelines</a> for the CI wiring.</p>
|
<a href="../90_drone_pipelines/">90 – Drone Pipelines</a> for the CI wiring.</p>
|
||||||
|
<h3 id="endpoints">Endpoints</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Registry</th>
|
||||||
|
<th>URL</th>
|
||||||
|
<th>Backend</th>
|
||||||
|
<th>CI secret</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>PyPI</td>
|
||||||
|
<td><code>https://pip.aetoskia.com</code></td>
|
||||||
|
<td>pypiserver (<code>server-pi:6007</code>)</td>
|
||||||
|
<td><code>PIP_REPO_URL</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>npm</td>
|
||||||
|
<td><code>https://npm.aetoskia.com</code></td>
|
||||||
|
<td>Verdaccio (<code>server-pi:6008</code>)</td>
|
||||||
|
<td><code>NPM_REPO_URL</code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>Both are exposed through Traefik on the <code>websecure</code> entrypoint as <strong>bare
|
||||||
|
origins</strong> — no path, no trailing slash. Set the secret values exactly as above.</p>
|
||||||
|
<h3 id="npm-scope-the-registry-never-set-it-globally">npm: scope the registry, never set it globally</h3>
|
||||||
|
<p>Verdaccio here has <strong>no uplink / proxy</strong>, so it can only serve <code>@aetoskia/*</code>
|
||||||
|
packages. A global <code>registry=https://npm.aetoskia.com</code> in <code>.npmrc</code> would route
|
||||||
|
<em>every</em> dependency — including public transitive deps such as
|
||||||
|
<code>zod-to-json-schema</code> (pulled in by <code>@modelcontextprotocol/sdk</code>) — through
|
||||||
|
Verdaccio, which 404s on anything it does not host. Always scope the registry to
|
||||||
|
the account:</p>
|
||||||
|
<div class="language-text highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-1">1</a></span>
|
||||||
|
<span class="normal"><a href="#__codelineno-0-2">2</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1"></a>@aetoskia:registry=https://npm.aetoskia.com
|
||||||
|
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2"></a>//npm.aetoskia.com/:_auth=<base64(user:password)>
|
||||||
|
</span></code></pre></div></td></tr></table></div>
|
||||||
|
<p>Public deps then resolve from <code>registry.npmjs.org</code> and only <code>@aetoskia/*</code> hits
|
||||||
|
the private registry. The auth line must be <strong>scoped to the host</strong>
|
||||||
|
(<code>//host/:_auth=</code>), not a bare <code>_auth=</code> — modern npm rejects the bare form with
|
||||||
|
<code>ERR_INVALID_AUTH</code>. The drone template derives both from the package scope and
|
||||||
|
<code>NPM_REPO_URL</code> automatically; see
|
||||||
|
<a href="../90_drone_pipelines/">90 – Drone Pipelines</a>.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>The Drone pipeline runs each <code>commands:</code> list item in a <strong>separate shell</strong>, so
|
||||||
|
shell variables defined in one item do not survive into the next. Keep the
|
||||||
|
variable definitions and the commands that use them in the same <code>|</code> block.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3 id="verdaccio-storage-permissions">Verdaccio storage permissions</h3>
|
||||||
|
<p>Verdaccio runs as uid <strong>10001</strong> (<code>verdaccio</code>) inside <code>verdaccio/verdaccio</code>.
|
||||||
|
The <code>storage</code> directory is bind-mounted from the server
|
||||||
|
(<code>/mnt/omnissiah-vault/data/verdaccio/storage</code>); if it is owned by <code>root:root</code>
|
||||||
|
(mode <code>755</code>) the process cannot write to it and every publish fails with a
|
||||||
|
confusing <code>404 no such package available</code> (<code>NotFoundError</code> from
|
||||||
|
<code>local-storage</code>). Ensure the directory — and its <code>plugins</code> subdirectory — are
|
||||||
|
owned by <code>10001:101</code>:</p>
|
||||||
|
<div class="language-sh highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-1-1">1</a></span>
|
||||||
|
<span class="normal"><a href="#__codelineno-1-2">2</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1"></a>sudo<span class="w"> </span>chown<span class="w"> </span>-R<span class="w"> </span><span class="m">10001</span>:101<span class="w"> </span>/mnt/omnissiah-vault/data/verdaccio/storage
|
||||||
|
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2"></a>docker<span class="w"> </span>restart<span class="w"> </span>npm-registry
|
||||||
|
</span></code></pre></div></td></tr></table></div>
|
||||||
<h2 id="notes">Notes</h2>
|
<h2 id="notes">Notes</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Hexa</strong> is a full library with its own MCP server on <code>:8008</code>: read
|
<li><strong>Hexa</strong> is a full library with its own MCP server on <code>:8008</code>: read
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -22,17 +22,18 @@ steps:
|
|||||||
from_secret: NPM_PASSWORD
|
from_secret: NPM_PASSWORD
|
||||||
commands:
|
commands:
|
||||||
- apk add --no-cache curl
|
- apk add --no-cache curl
|
||||||
- PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
||||||
- VERSION=$(node -p "require('./package.json').version")
|
|
||||||
- |
|
- |
|
||||||
|
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
||||||
|
VERSION=$(node -p "require('./package.json').version")
|
||||||
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
||||||
echo "Tag '$DRONE_TAG' does not match package.json version '$VERSION'; refusing to publish."
|
echo "Tag '$DRONE_TAG' does not match package.json version '$VERSION'; refusing to publish."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- echo "registry=$NPM_REPO_URL" > /tmp/.npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
- echo "Checking if $PACKAGE_NAME@$VERSION exists on $NPM_REPO_URL ..."
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > /tmp/.npmrc
|
||||||
- |
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
||||||
|
echo "Checking if $PACKAGE_NAME@$VERSION exists on $NPM_REPO_URL ..."
|
||||||
if npm view "$PACKAGE_NAME@$VERSION" version --userconfig /tmp/.npmrc >/dev/null 2>&1; then
|
if npm view "$PACKAGE_NAME@$VERSION" version --userconfig /tmp/.npmrc >/dev/null 2>&1; then
|
||||||
echo "$PACKAGE_NAME@$VERSION already exists; skipping build."
|
echo "$PACKAGE_NAME@$VERSION already exists; skipping build."
|
||||||
exit 78
|
exit 78
|
||||||
@@ -55,8 +56,10 @@ steps:
|
|||||||
echo "NPM_REPO_URL / NPM_USERNAME / NPM_PASSWORD are not set" >&2
|
echo "NPM_REPO_URL / NPM_USERNAME / NPM_PASSWORD are not set" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- echo "registry=$NPM_REPO_URL" > .npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > .npmrc
|
||||||
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
||||||
- npm install
|
- npm install
|
||||||
- echo "Running quality gate..."
|
- echo "Running quality gate..."
|
||||||
- npm run quality-gate
|
- npm run quality-gate
|
||||||
@@ -79,8 +82,11 @@ steps:
|
|||||||
NPM_PASSWORD:
|
NPM_PASSWORD:
|
||||||
from_secret: NPM_PASSWORD
|
from_secret: NPM_PASSWORD
|
||||||
commands:
|
commands:
|
||||||
- echo "registry=$NPM_REPO_URL" > .npmrc
|
- |
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > .npmrc
|
||||||
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
||||||
- echo "Publishing to private npm at $NPM_REPO_URL ..."
|
- echo "Publishing to private npm at $NPM_REPO_URL ..."
|
||||||
- npm publish --access restricted
|
- npm publish --access restricted
|
||||||
|
|
||||||
@@ -117,8 +123,11 @@ steps:
|
|||||||
from_secret: NPM_PASSWORD
|
from_secret: NPM_PASSWORD
|
||||||
commands:
|
commands:
|
||||||
- apk add --no-cache git
|
- apk add --no-cache git
|
||||||
- echo "registry=$NPM_REPO_URL" > /tmp/.npmrc
|
- |
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > /tmp/.npmrc
|
||||||
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
||||||
- |
|
- |
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|||||||
@@ -72,8 +72,13 @@ pipelines**:
|
|||||||
the disaster-recovery / replay path.
|
the disaster-recovery / replay path.
|
||||||
|
|
||||||
Secrets: `NPM_REPO_URL`, `NPM_USERNAME`, `NPM_PASSWORD`. Auth is a generated
|
Secrets: `NPM_REPO_URL`, `NPM_USERNAME`, `NPM_PASSWORD`. Auth is a generated
|
||||||
`.npmrc` (`registry=` + `_auth=` base64 of `user:pass`) written from secrets at
|
`.npmrc` written from secrets at runtime. It sets a **scope-scoped** registry,
|
||||||
runtime — the committed `.npmrc` in a repo only points at the registry URL.
|
never a global one — `@aetoskia:registry=$NPM_REPO_URL` — plus a host-scoped
|
||||||
|
auth line `//<host>/:_auth=<base64(user:pass)>`. The scope and host are derived
|
||||||
|
from `package.json` and `NPM_REPO_URL` respectively. A global `registry=` would
|
||||||
|
push public transitive deps through Verdaccio (which has no uplink) and 404
|
||||||
|
`npm install`; a bare `_auth=` is rejected by modern npm. See
|
||||||
|
[93 – Library Registry](93_library_registry.md).
|
||||||
|
|
||||||
- **Ship as-is.** Name and version come from `package.json`, so the same file
|
- **Ship as-is.** Name and version come from `package.json`, so the same file
|
||||||
is reused verbatim across every npm package.
|
is reused verbatim across every npm package.
|
||||||
|
|||||||
@@ -64,6 +64,56 @@ so the CI credentials (`PIP_USERNAME` / `PIP_PASSWORD`, `NPM_USERNAME` /
|
|||||||
Verdaccio requires **bcrypt** htpasswd entries; see
|
Verdaccio requires **bcrypt** htpasswd entries; see
|
||||||
[90 – Drone Pipelines](90_drone_pipelines.md) for the CI wiring.
|
[90 – Drone Pipelines](90_drone_pipelines.md) for the CI wiring.
|
||||||
|
|
||||||
|
### Endpoints
|
||||||
|
|
||||||
|
| Registry | URL | Backend | CI secret |
|
||||||
|
|---|---|---|---|
|
||||||
|
| PyPI | `https://pip.aetoskia.com` | pypiserver (`server-pi:6007`) | `PIP_REPO_URL` |
|
||||||
|
| npm | `https://npm.aetoskia.com` | Verdaccio (`server-pi:6008`) | `NPM_REPO_URL` |
|
||||||
|
|
||||||
|
Both are exposed through Traefik on the `websecure` entrypoint as **bare
|
||||||
|
origins** — no path, no trailing slash. Set the secret values exactly as above.
|
||||||
|
|
||||||
|
### npm: scope the registry, never set it globally
|
||||||
|
|
||||||
|
Verdaccio here has **no uplink / proxy**, so it can only serve `@aetoskia/*`
|
||||||
|
packages. A global `registry=https://npm.aetoskia.com` in `.npmrc` would route
|
||||||
|
*every* dependency — including public transitive deps such as
|
||||||
|
`zod-to-json-schema` (pulled in by `@modelcontextprotocol/sdk`) — through
|
||||||
|
Verdaccio, which 404s on anything it does not host. Always scope the registry to
|
||||||
|
the account:
|
||||||
|
|
||||||
|
```
|
||||||
|
@aetoskia:registry=https://npm.aetoskia.com
|
||||||
|
//npm.aetoskia.com/:_auth=<base64(user:password)>
|
||||||
|
```
|
||||||
|
|
||||||
|
Public deps then resolve from `registry.npmjs.org` and only `@aetoskia/*` hits
|
||||||
|
the private registry. The auth line must be **scoped to the host**
|
||||||
|
(`//host/:_auth=`), not a bare `_auth=` — modern npm rejects the bare form with
|
||||||
|
`ERR_INVALID_AUTH`. The drone template derives both from the package scope and
|
||||||
|
`NPM_REPO_URL` automatically; see
|
||||||
|
[90 – Drone Pipelines](90_drone_pipelines.md).
|
||||||
|
|
||||||
|
> The Drone pipeline runs each `commands:` list item in a **separate shell**, so
|
||||||
|
> shell variables defined in one item do not survive into the next. Keep the
|
||||||
|
> variable definitions and the commands that use them in the same `|` block.
|
||||||
|
|
||||||
|
### Verdaccio storage permissions
|
||||||
|
|
||||||
|
Verdaccio runs as uid **10001** (`verdaccio`) inside `verdaccio/verdaccio`.
|
||||||
|
The `storage` directory is bind-mounted from the server
|
||||||
|
(`/mnt/omnissiah-vault/data/verdaccio/storage`); if it is owned by `root:root`
|
||||||
|
(mode `755`) the process cannot write to it and every publish fails with a
|
||||||
|
confusing `404 no such package available` (`NotFoundError` from
|
||||||
|
`local-storage`). Ensure the directory — and its `plugins` subdirectory — are
|
||||||
|
owned by `10001:101`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo chown -R 10001:101 /mnt/omnissiah-vault/data/verdaccio/storage
|
||||||
|
docker restart npm-registry
|
||||||
|
```
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- **Hexa** is a full library with its own MCP server on `:8008`: read
|
- **Hexa** is a full library with its own MCP server on `:8008`: read
|
||||||
|
|||||||
@@ -22,17 +22,18 @@ steps:
|
|||||||
from_secret: NPM_PASSWORD
|
from_secret: NPM_PASSWORD
|
||||||
commands:
|
commands:
|
||||||
- apk add --no-cache curl
|
- apk add --no-cache curl
|
||||||
- PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
||||||
- VERSION=$(node -p "require('./package.json').version")
|
|
||||||
- |
|
- |
|
||||||
|
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
||||||
|
VERSION=$(node -p "require('./package.json').version")
|
||||||
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
if [ "$DRONE_TAG" != "$VERSION" ]; then
|
||||||
echo "Tag '$DRONE_TAG' does not match package.json version '$VERSION'; refusing to publish."
|
echo "Tag '$DRONE_TAG' does not match package.json version '$VERSION'; refusing to publish."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- echo "registry=$NPM_REPO_URL" > /tmp/.npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
- echo "Checking if $PACKAGE_NAME@$VERSION exists on $NPM_REPO_URL ..."
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > /tmp/.npmrc
|
||||||
- |
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
||||||
|
echo "Checking if $PACKAGE_NAME@$VERSION exists on $NPM_REPO_URL ..."
|
||||||
if npm view "$PACKAGE_NAME@$VERSION" version --userconfig /tmp/.npmrc >/dev/null 2>&1; then
|
if npm view "$PACKAGE_NAME@$VERSION" version --userconfig /tmp/.npmrc >/dev/null 2>&1; then
|
||||||
echo "$PACKAGE_NAME@$VERSION already exists; skipping build."
|
echo "$PACKAGE_NAME@$VERSION already exists; skipping build."
|
||||||
exit 78
|
exit 78
|
||||||
@@ -55,8 +56,10 @@ steps:
|
|||||||
echo "NPM_REPO_URL / NPM_USERNAME / NPM_PASSWORD are not set" >&2
|
echo "NPM_REPO_URL / NPM_USERNAME / NPM_PASSWORD are not set" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- echo "registry=$NPM_REPO_URL" > .npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > .npmrc
|
||||||
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
||||||
- npm install
|
- npm install
|
||||||
- echo "Running quality gate..."
|
- echo "Running quality gate..."
|
||||||
- npm run quality-gate
|
- npm run quality-gate
|
||||||
@@ -79,8 +82,11 @@ steps:
|
|||||||
NPM_PASSWORD:
|
NPM_PASSWORD:
|
||||||
from_secret: NPM_PASSWORD
|
from_secret: NPM_PASSWORD
|
||||||
commands:
|
commands:
|
||||||
- echo "registry=$NPM_REPO_URL" > .npmrc
|
- |
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > .npmrc
|
||||||
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> .npmrc
|
||||||
- echo "Publishing to private npm at $NPM_REPO_URL ..."
|
- echo "Publishing to private npm at $NPM_REPO_URL ..."
|
||||||
- npm publish --access restricted
|
- npm publish --access restricted
|
||||||
|
|
||||||
@@ -117,8 +123,11 @@ steps:
|
|||||||
from_secret: NPM_PASSWORD
|
from_secret: NPM_PASSWORD
|
||||||
commands:
|
commands:
|
||||||
- apk add --no-cache git
|
- apk add --no-cache git
|
||||||
- echo "registry=$NPM_REPO_URL" > /tmp/.npmrc
|
- |
|
||||||
- echo "_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
NPM_HOST=$(echo "$NPM_REPO_URL" | sed -E 's|^[a-z]+://||; s|/*$||')
|
||||||
|
NPM_SCOPE="@$(node -p "require('./package.json').name.split('/')[0].replace(/^@/,'')")"
|
||||||
|
echo "$NPM_SCOPE:registry=$NPM_REPO_URL" > /tmp/.npmrc
|
||||||
|
echo "//$NPM_HOST/:_auth=$(echo -n "$NPM_USERNAME:$NPM_PASSWORD" | base64 | tr -d '\n')" >> /tmp/.npmrc
|
||||||
- |
|
- |
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user