Open renoirb opened 5 years ago
(Related conversation on Gitter.)
Did you try using the --npm-auth-token
parameter for rush publish
, like in common/config/azure-pipelines/templates/buildAndPublish.yaml?
Generally we wouldn't want to store a sensitive publishing token in a file on disk such as ~/.npmrc
. Instead it gets passed via an environment variable.
If there's specific issues that aren't covered well in the Publishing packages docs, let me know and we can try to improve them. From the issue description, it wasn't completely clear to me which part you are having trouble with.
@deanbot appeared to have a related issue. In his case, the problem was that rush.json's repository.url
did not exactly match the git remote get-url origin
strings.
To address that part of this problem, I think we should do a quick PR that:
normalizedRemoteUrl
) to be a looser match, andrepository.url
to better explain how you're supposed to specify this URL@deanbot 's repro involved URLs of the form:
https://my-tenant.visualstudio.com/my-project/_git/my-repo
vs
my-tenant@vs-ssh.visualstudio.com:v3/my-tenant/my-project/my-repo
According to the Git docs, [user@]server:project.git
is a shorthand for ssh://[user@]server/project.git
Maybe we can use the normalize-git-url package to sort this out.
Yes, I tried with the --npm-auth-token. I'll document better everything I've tried when I get back to ny workstation. But errors came up because of trying to get history using git. Because it's not over ssh, with a different port.
Update:
rush version --version-policy libraries --bump
works, now that common/config/rush/version-policies.json
has versions matching each packages. Notice thought that I have to commit and tag manually. See rush publish ...
is still not working. I mean, it worked once. Can't tell when. And cannot re-publish anything anymore.Nexus registry is ONLY through TLS (https://nexus.foo.example.org:50043/repository/npm-hosted/
). We can't work with opening non TLS port.
Here are a few error logs I've got
export NEXUS_AUTH_TOKEN=secrettokenstring
rush publish \
--publish \
--apply\
--publish \
--version-policy libraries \
--include-all \
--set-access-level public \
--npm-auth-token ${NEXUS_AUTH_TOKEN} \
-r 'https://nexus.foo.example.org:50043/repository/npm-hosted/'
0 info it worked if it ends with ok
1 verbose cli [ '/usr/bin/node',
1 verbose cli '/usr/bin/npm',
1 verbose cli 'publish',
1 verbose cli '--registry https://nexus.foo.example.org:50043/repository/npm-hosted/:_authToken=secrettokenstring',
1 verbose cli '--access',
1 verbose cli 'public' ]
2 info using npm@6.9.0
3 info using node@v10.16.3
4 verbose npm-session bd3f917a6ad23924
5 verbose publish [ '.' ]
6 info lifecycle @frontend-bindings/data-model@1.0.1~prepublish: @frontend-bindings/data-model@1.0.1
7 info lifecycle @frontend-bindings/data-model@1.0.1~prepare: @frontend-bindings/data-model@1.0.1
8 info lifecycle @frontend-bindings/data-model@1.0.1~prepublishOnly: @frontend-bindings/data-model@1.0.1
9 verbose lifecycle @frontend-bindings/data-model@1.0.1~prepublishOnly: unsafe-perm in lifecycle true
10 verbose lifecycle @frontend-bindings/data-model@1.0.1~prepublishOnly: PATH: /usr/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/data/projects/frontend-bindings/frontend-bindings/packages/data-model/node_modules/.bin:/data/projects/frontend-bindings/frontend-bindings/packages/data-model/node_modules/.bin:/usr/bin:/data/projects/frontend-bindings/frontend-bindings/common/temp/node_modules/.bin:/data/projects/frontend-bindings/frontend-bindings/node_modules/.bin:/data/.npm/bin:/home/vagrant/bin:/home/vagrant/node_modules/.bin:/data/.npm/bin:/home/vagrant/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
11 verbose lifecycle @frontend-bindings/data-model@1.0.1~prepublishOnly: CWD: .
12 silly lifecycle @frontend-bindings/data-model@1.0.1~prepublishOnly: Args: [ '-c', 'rushx build' ]
13 silly lifecycle @frontend-bindings/data-model@1.0.1~prepublishOnly: Returned: code: 0 signal: null
14 info lifecycle @frontend-bindings/data-model@1.0.1~prepack: @frontend-bindings/data-model@1.0.1
15 info lifecycle @frontend-bindings/data-model@1.0.1~postpack: @frontend-bindings/data-model@1.0.1
16 notice
17 notice 📦 @frontend-bindings/data-model@1.0.1
18 notice === Tarball Contents ===
19 notice 2.4kB package.json
19 notice 1.3kB CHANGELOG.json
19 notice 268B CHANGELOG.md
19 notice 36.3kB dist/browser.cjs.js
...
20 notice === Tarball Details ===
21 notice name: @frontend-bindings/data-model
21 notice version: 1.0.1
21 notice package size: 18.5 kB
21 notice unpacked size: 100.7 kB
21 notice shasum: ...
21 notice integrity: ...
21 notice total files: 24
22 notice
23 http fetch PUT 401 https://nexus.foo.example.org:50043/repository/npm-hosted/@frontend-bindings%2fdata-model 355ms
24 verbose stack Error: Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager"
24 verbose stack at res.buffer.catch.then.body (/usr/lib/node_modules/npm/node_modules/npm-registry-fetch/check-response.js:94:17)
24 verbose stack at process._tickCallback (internal/process/next_tick.js:68:7)
25 verbose statusCode 401
26 verbose pkgid @frontend-bindings/data-model@1.0.1
27 verbose cwd /data/projects/frontend-bindings/frontend-bindings/packages/data-model
28 verbose Linux 4.15.0-62-generic
29 verbose argv "/usr/bin/node" "/usr/bin/npm" "publish" "--registry https://nexus.foo.example.org:50043/repository/npm-hosted/:_authToken=secrettokenstring" "--access" "public"
30 verbose node v10.16.3
31 verbose npm v6.9.0
32 error code E401
33 error Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager"
34 verbose exit [ 1, true ]
Rush seems to be doing npm view "@frontend-bindings/data-model" time --json --//nexus.foo.example.org:50043/repository/npm-hosted/:authToken=secrettokenstring
Which seem to break, but when I do manually, it works;
npm view "@frontend-bindings/data-model@1.0.0" time --json --registry https://nexus.foo.example.org:50043/repository/npm-hosted/
{
"created": "2019-02-09T17:37:51.903Z",
"modified": "2019-06-04T02:58:49.995Z",
"1.0.0-alpha.2": "2019-02-09T17:37:51.903Z",
"1.0.0-alpha.3": "2019-02-09T17:58:41.785Z",
"1.0.0": "2019-06-04T02:58:49.995Z"
}
I'm assuming it's related to figuring out which registry to use when doing publish
rush publish \
--npm-auth-token ${NEXUS_AUTH_TOKEN} \
-r 'https://nexus.foo.example.org:50043/repository/npm-hosted/'
My guess, is that any time i happen to do npm login --regsitry=...
manually (for other packages), I might just break that publish command with Rush. See PublishAction#_addSharedNpmConfig()
. I've convigured PNPM in rush.json, and that's npm doing publishing. It's confusing.
About common/config/rush/.npmrc
, I'm unsure WHAT to put, exactly.
Use-case:
/repository/js-group/
, so anything is backed up/repository/npm-hosted/
_authToken
in common/config/rush/.npmrc; file: common/config/rush/.npmrc
registry=//nexus.foo.example.org:50043/repository/js-group/
@frontend-bindings:registry=//nexus.foo.example.org:50043/repository/npm-hosted/
registry=//nexus.foo.example.org:50043/repository/npm-hosted/
I might be stuck using, as per Nexus docs
registry = https://nexus.foo.example.org:50043/repository/npm-hosted/
email=renoirb@example.org
always-auth=true
_auth=$NPM_TOKEN
// hopefully this can be written and superseeded by env var
Well, it seems that if somewhere in the path for .npmrc
(e.g. ~/.npmrc
) with credentials for Nexus like comment above
; File ~/.npmrc
; Assuming you publish to Nexus anything under namespace @renoirb; Nexus requires, when using such configuration TO ALWAYS have always-auth=true set, with email
@renoirb:registry=https://nexus.foo.example.org:50043/repository/npm-hosted/
email=renoirb@example.org
always-auth=true
_auth=$NPM_TOKEN
; This above hasn't been tried out yet.
And rush
; File common/config/rush/.npmrc
registry=https://nexus.foo.example.org:50043/repository/js-group/
@renoirb:registry=https://nexus.foo.example.org:50043/repository/npm-hosted/
cat common/config/rush/version-policies.json
[
{
"policyName": "tooling",
"definitionName": "lockStepVersion",
"version": "1.0.1",
"nextBump": "patch"
}
]
In rush.json
{
"project": [
{
"packageName": "@renoirb/conventions-use-bili",
"projectFolder": "conventions/use-bili",
"versionPolicyName": "tooling",
"reviewCategory": "conventions"
}
]
}
Assuming you've bumped version
rush version --version-policy tooling --bump
Commit affected packages, tag in some way, etc.
To publish packages (i.e. build all matching tools
version policy):
rush publish --publish --version-policy tooling --include-all --set-access-level public -r https://nexus.foo.example.org:50043/repository/npm-hosted/
Updated example and full use-case is now published npmjs.com/search?q=@renoirb and up-to-date.
conventions/use-bili
All works well, let's see what we can improve in the documentation.
What would be nice, but I couldn't figure out yet:
Thanks @renoirb !
1 . How to create git tag for each package
I believe Rush does this automatically during publishing.
2 . Now that I can run manually, as maintainer, from his workstation, how does people make this work from CI? What am I missing
This is what we do in common/config/azure-pipelines/templates/buildAndPublish.yaml (the CI job that gets run by Azure DevOps):
- script: 'node common\scripts\install-run-rush.js version --bump --version-policy $(VersionPolicy) --target-branch $(Build.SourceBranchName)'
displayName: 'Rush Version'
- script: 'node common\scripts\install-run-rush.js publish --apply --publish --include-all --target-branch $(Build.SourceBranchName) --npm-auth-token $(npmToken) --add-commit-details --set-access-level public'
displayName: 'Rush Publish'
I don't understand the --target-branch
, if I'm already on master? Or is it expected we MUST ALWAYS bump version from another branch, AND that IT WILL merge into master THEN create git tag, and so on?
Hi, here's my bash based build script I've just come up with.
#!/usr/bin/env bash
#
# MonoRepo helper utility to manage code releases
#
# Author: Renoir Boulanger <hello@renoirboulanger.com>
#
# Some other cool bash patterns in
# https://gist.github.com/renoirb/361e4e2817341db4be03b8f667338d47
#
# For the release process, refer to this ticket:
# https://github.com/microsoft/web-build-tools/issues/1522
#
# TIP:
# Before commiting changes in this file, make sure you run shellcheck and no messages are shown
#
# > shellcheck bin/monorepo
#
# For publishing, we have to do this from the maintainer's workstation, not GitLab.
#
# To push packages to Nexus, you need to give your Authentication token to Rush.
# The Authentication token is a base64 string of your Nexus registry account credentials.
# Its a semi-column separated values for username:password. Plug in your Nexus username and password.
# Paste the value in ~/.npmrc at `_auth`
#
# > echo -n 'renoir.boulanger:password' | openssl base64
#
# For a successful publish, make sure you have ~/.npmrc with the following lines:
#
# > @frontend-bindings:registry=https://nexus.foo.example.org:50043/repository/npm-hosted/
# > email=renoir.boulanger@example.org
# > always-auth=true
# > _auth=...
#
# Then:
# > bin/monorepo info
# > export VERSION_POLICY=libraries
# > bin/monorepo version
# > bin/monorepo publish
#
# To get a directory with archives:
# > bin/monorepo pack
#
set -e
################################################################################
# Functions. That could be distributed and re-used.
function must_command_exist()
{
command -v "${1}" >/dev/null 2>&1 || { echo >&2 "Command ${1} must exist."; exit 1; }
}
# https://stackoverflow.com/questions/11362250/in-bash-how-do-i-test-if-a-variable-is-defined-in-u-mode#answer-19874099
function is_var_defined()
{
if [ $# -ne 1 ]
then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1
fi
# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value
# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the
# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to
# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this
# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.
# Example: $1="var"
# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"
# Code execute: [ ! -z ${var:-} ]
eval "[ ! -z \${$1:-} ]"
return $? # Pedantic.
}
function must_var_defined()
{
is_var_defined "$1" || { echo >&2 "Variable ${1} is not defined and must exist. Aborting."; exit 1; }
}
function error { printf "Error: %s \n " "$@" >&2; exit 1; }
function policy_names () {
npx strip-json-comments-cli common/config/rush/version-policies.json | jq .[].policyName
}
function list_versions () {
node common/scripts/install-run-rush.js list --version
}
function action_version () {
must_var_defined VERSION_POLICY
node common/scripts/install-run-rush.js version --bump --version-policy "${VERSION_POLICY}" --target-branch "${TARGET_BRANCH=master}"
}
function action_publish () {
must_var_defined VERSION_POLICY
must_var_defined REGISTRY
node common/scripts/install-run-rush.js publish --publish --apply --include-all --target-branch "${TARGET_BRANCH=master}" --version-policy "${VERSION_POLICY}" --set-access-level public -r "${REGISTRY}"
# ... yeah. Something, in some order. Applying works if I have --target-branch=master, whereas elsewhere it's a space.
node common/scripts/install-run-rush.js publish --publish --pack --include-all --release-folder dist --apply-git-tags-on-pack --apply --target-branch=master
}
function action_pack () {
node common/scripts/install-run-rush.js clean
node common/scripts/install-run-rush.js rebuild
node common/scripts/install-run-rush.js publish --publish --pack --include-all --release-folder dist
}
function action_info () {
printf "\n\nAvailable packages:\n"
list_versions
printf "\n\nAvailable version policies:\n"
policy_names
printf "\n\n"
}
function display_usage() {
echo -e "\n"
echo "MonoRepo helper utility to manage code releases."
echo -e "\nUsage:\n ${0} <ACTION>\n\n"
echo -e "<ACTION> being one of:"
printf " * %s\n" "${switchValidActions[@]}"
echo -e "\n"
echo -e "Examples:"
echo -e " ${0}"
echo -e " ${0} pack"
echo -e "\n"
}
################################################################################
# Sanity checks before executing anything else.
must_command_exist git
must_command_exist jq
must_command_exist node
must_command_exist npx
################################################################################
# VALIDATION LOGIC DATA
switchValidActions=(info version publish pack)
REGISTRY="${MONOREPO_REGISTRY=https://nexus.foo.example.org:50043/repository/npm-hosted/}"
################################################################################
# PRE EXECUTION
if [ $# -ne 1 ]; then
display_usage
exit
fi
if [[ ! "${switchValidActions[*]}" =~ ${1} ]]; then
error "Invalid action \"${1}\". It must be one of: ${switchValidActions[*]}"
fi
ACTION="${1^^}"
################################################################################
# EXECUTION
if [[ $ACTION == "INFO" ]]; then
action_info
fi
if [[ $ACTION == "VERSION" ]]; then
action_version
fi
if [[ $ACTION == "PUBLISH" ]]; then
action_publish
fi
if [[ $ACTION == "PACK" ]]; then
action_pack
fi
This worked for adding branch
node common/scripts/install-run-rush.js publish --publish --pack --include-all --release-folder dist --apply-git-tags-on-pack --apply --target-branch=master
But I can't make this to TAG only on changed packages. Unless I make bash NOT die on errors in publish function
Question is now more: What is the order we should do things when publishing a package.
Assuming:
My understanding is the following (written on top of my head, not exact commands):
rush update
rush clean
rush build
rush test
rush change --target-branch v1.0.0-branch
# rinse repeat above steps, until we want to release
rush version --bump --version-policy foo
rush publish --publish --apply --version-policy foo --target-branch v1.0.0-branch -r https://nexus.foo.example.org:54330/registry/npm-hosted/
rush publish --pack --apply-git-tags-on-pack --include-all --version-policy foo
What confuse me is the use of publish --publish and publish --pack --publish ... to do two things. I'm never sure WHICH ones is about publishing to gitlab, which one DO create tags.
When I succeed creating tags, its only without version policy, and then errors because not all packages changed versions and git errors for existing tag.
What I didn't understand this far was the goal of rush change. I now see that it can be done more than once. But rather after many commits as a way to describe a change spanning multiple package. So it's to help making changelog and link dependents and their impact
Hi @renoirb - Did you ever get the tagging process to work from the CI? i.e. not having the mainter manually do this from his/hers workstation?
What i am trying todo is have the whole release process automated. i.e. when I tag my master
branch on gitlab the CI automatically bumps versions, generates changelogs and publishes to nexus.
Documentation is lacking. (Bug?)
In a corporate setting, we have our own self-hosted Sonatype Nexus registry and our own self-hosted GitLab. Here are the settings I can use (anonymized, of course)
https://nexus.foo.bar.example.org:50043/repository/npm-hosted
https://git.foo.bar.example.org:50043/orgName/project-name.git
With Yarn/npm i could publish with an
~/.npmrc
that looks like this;My project's
common/config/rush/.npmrc
Would contain only the registry lines, nothing about authentication.What should I put in rush.json for my situation?
git+https://...
? Docs are too vague in the version bump, pack, publish flow.The docs is unclear about the appropriate steps, assuming on master branch (of course). Tests, my fallback place to learn about things, has only irrelevant strings. I'm assuming it's all normal npm,pnpm,yarn process automated by rush.
I'm aware as maintainer, when I release, I should run commands manually.
Scenario:
(Recommendations for doing this CI side, assuming CI can push to Nexus. I can help document if I can make it work).
On related note. Here is my GitLab CI YAML. My project is a fork from this public experiment. https://github.com/renoirb/experiments-201908-rush-typescript-just-bili-monorepo/blob/master/.gitlab-ci.yml