PyPI and npm Repositories¶
Python packages publish to Shared Nexus (
nexus.shared.cwiq.io) using twine. npm packages install from Dev Nexus (nexus.dev.cwiq.io). All operations use port 443 (standard HTTPS).
PyPI Repositories¶
The Python package workflow uses the Shared Nexus instance. cwiq-common is the primary internal package.
Repository Structure¶
| Repository | Type | Purpose |
|---|---|---|
pypi-hosted |
Hosted | Internal packages — cwiq-common publishes here |
pypi-proxy |
Proxy | Cache of pypi.org |
pypi-group |
Group | Combined endpoint — install target for all pipelines |
PyPI URLs¶
| Operation | URL |
|---|---|
| Publish (twine) | https://nexus.shared.cwiq.io/repository/pypi-hosted/ |
| Install (pip) | https://nexus.shared.cwiq.io/repository/pypi-group/simple/ |
The group repository combines hosted and proxy — a pip install resolves both internal packages and public packages from the cached pypi.org mirror through a single endpoint.
Publishing a Package (CI)¶
# Publish cwiq-common to Nexus PyPI
twine upload \
--repository-url https://nexus.shared.cwiq.io/repository/pypi-hosted/ \
--username "${NEXUS_USER}" \
--password "${NEXUS_PASSWORD}" \
dist/*
Installing from Nexus PyPI¶
# Install cwiq-common from Nexus group
pip install cwiq-common \
--index-url https://nexus.shared.cwiq.io/repository/pypi-group/simple/ \
--trusted-host nexus.shared.cwiq.io
# Install with extra-index for public packages
pip install fastapi \
--extra-index-url https://nexus.shared.cwiq.io/repository/pypi-group/simple/
pip.conf (Developer Workstations)¶
Configure pip to always use Nexus as the primary index:
[global]
index-url = https://nexus.shared.cwiq.io/repository/pypi-group/simple/
trusted-host = nexus.shared.cwiq.io
Place this at ~/.pip/pip.conf (Linux/macOS) or %APPDATA%\pip\pip.ini (Windows).
pyproject.toml (Package Publishing)¶
[tool.poetry.source]
name = "nexus"
url = "https://nexus.shared.cwiq.io/repository/pypi-group/simple/"
priority = "primary"
CI/CD Variables (cwiq-common Pipeline)¶
# platform/cwiq-common/.gitlab-ci.yml
variables:
NEXUS_HOST: nexus.shared.cwiq.io
NEXUS_PYPI_PUSH_URL: "https://${NEXUS_HOST}/repository/pypi-hosted/"
NEXUS_PYPI_PULL_URL: "https://${NEXUS_HOST}/repository/pypi-group/simple/"
cwiq-common Package Reference¶
| Field | Value |
|---|---|
| Package name | cwiq-common |
| Current version | 0.2.0 |
| GitLab project | orchestrator/cwiq-common (ID 29) |
| Import as | cwiq_common |
| Publish repository | pypi-hosted |
| Install repository | pypi-group (group, includes proxy cache) |
Install in any platform service:
Publishing Workflow¶
The cwiq-common pipeline publishes on version tag push (v*):
- Build:
python -m buildcreatesdist/with.whland.tar.gz - Auth: Vault JWT →
secret/nexus/svc-orchestrator→ NEXUS_USER / NEXUS_PASSWORD - Publish:
twine upload --repository-url ${NEXUS_PYPI_PUSH_URL} - Version is immutable once pushed to
pypi-hosted(ALLOW_ONCE not enforced for PyPI, but treat releases as immutable by convention)
npm Repositories¶
npm repositories live on the Dev Nexus instance (nexus.dev.cwiq.io). This is the only Nexus artifact type that uses Dev rather than Shared — the npm workflow predates the Shared npm setup and no internal npm packages currently exist in production use.
Repository Structure¶
| Repository | Type | Purpose |
|---|---|---|
npm-hosted |
Hosted | Internal npm packages |
npm-proxy |
Proxy | Cache of npmjs.org |
npm-group |
Group | Combined endpoint — install target |
npm URLs¶
| Operation | URL |
|---|---|
| Install (npm) | https://nexus.dev.cwiq.io/repository/npm-group/ |
| Publish | https://nexus.dev.cwiq.io/repository/npm-hosted/ |
Configuring npm to Use Nexus¶
# Set Nexus as the npm registry
npm config set registry https://nexus.dev.cwiq.io/repository/npm-group/
# Or per-project (.npmrc in project root)
echo "registry=https://nexus.dev.cwiq.io/repository/npm-group/" > .npmrc
CI/CD Usage (UI Pipeline)¶
The UI pipeline installs npm packages through Nexus to avoid npmjs.org rate limits and ensure reproducible builds:
# platform/ui/.gitlab-ci.yml
before_script:
- npm config set registry https://nexus.dev.cwiq.io/repository/npm-group/
install:
script:
- npm ci
Publishing an npm Package¶
# Authenticate to Nexus npm hosted
npm login \
--registry https://nexus.dev.cwiq.io/repository/npm-hosted/ \
--username "${NEXUS_USER}" \
--password "${NEXUS_PASSWORD}" \
--email dev@cwiq.io
# Publish
npm publish --registry https://nexus.dev.cwiq.io/repository/npm-hosted/
Authentication¶
Both PyPI and npm operations use Vault JWT auth — the same pattern as Docker and RPM:
# In .gitlab-ci.yml — fetch credentials from Vault before publish/install
get_nexus_creds:
id_tokens:
VAULT_ID_TOKEN:
aud: https://gitlab.shared.cwiq.io
script:
- |
VAULT_TOKEN=$(curl -s -X POST "${VAULT_ADDR}/v1/auth/jwt/login" \
-d "{\"jwt\":\"${VAULT_ID_TOKEN}\",\"role\":\"nexus-ci\"}" \
| jq -r .auth.client_token)
NEXUS_USER=$(curl -s -H "X-Vault-Token: ${VAULT_TOKEN}" \
"${VAULT_ADDR}/v1/secret/data/nexus/svc-orchestrator" | jq -r .data.data.username)
NEXUS_PASSWORD=$(curl -s -H "X-Vault-Token: ${VAULT_TOKEN}" \
"${VAULT_ADDR}/v1/secret/data/nexus/svc-orchestrator" | jq -r .data.data.password)
See Service Accounts for the full Vault JWT auth flow.
Related Documentation¶
- Overview — Port architecture and repository types
- Service Accounts — Vault JWT authentication
- Artifact Naming — Package naming conventions