diff --git a/src/artifacts-helper/NOTES.md b/src/artifacts-helper/NOTES.md index 347318b..8c92d6d 100644 --- a/src/artifacts-helper/NOTES.md +++ b/src/artifacts-helper/NOTES.md @@ -1,5 +1,5 @@ This installs [Azure Artifacts Credential Provider](https://github.com/microsoft/artifacts-credprovider) -and optionally configures an alias for `dotnet`, `nuget`, `npm`, `yarn`, and `rush` that dynamically sets an authentication token +and optionally configures functions which shadow `dotnet`, `nuget`, `npm`, `yarn`, and `rush` which dynamically sets an authentication token for pulling artifacts from a feed before running the command. For `npm`, `yarn`, and `rush` this requires that your `~/.npmrc` file is configured to use the ${ARTIFACTS_ACCESSTOKEN} @@ -41,3 +41,27 @@ to download the package. ## OS Support This feature is tested to work on Debian/Ubuntu and Mariner CBL 2.0 + +## Changing where functions are configured + +By default, the functions are defined in `/etc/bash.bashrc` and `/etc/zsh/zshrc` if the container user is `root`, otherwise `~/.bashrc` and `~/.zshrc`. +This default configuration ensures that the functions are always available for any interactive shells. + +In some cases it can be useful to have the functions written to a non-default location. For example: +- the configuration file of a shell other than `bash` and `zsh` +- a custom file which is not a shell configuration script (so that it can be `source`d in non-interactive shells and scripts) + +To do this, set the `targetFiles` option to the path script path where the functions should be written. Note that the default paths WILL NOT be used +if the `targetFiles` option is provided, so you may want to include them in the overridden value, or add `source` the custom script in those configurations: + +```bash +# .devcontainer/devcontainer.json +{ + // ... + "targetFiles": "/custom/path/to/auth-helper.sh" +} + +# ~/.bashrc + +source /custom/path/to/auth-helper.sh +``` \ No newline at end of file diff --git a/src/artifacts-helper/README.md b/src/artifacts-helper/README.md index 12edbcf..ca10de1 100644 --- a/src/artifacts-helper/README.md +++ b/src/artifacts-helper/README.md @@ -24,6 +24,7 @@ Configures Codespace to authenticate with Azure Artifact feeds | npxAlias | Create alias for npx | boolean | true | | rushAlias | Create alias for rush | boolean | true | | python | Install Python keyring helper for pip | boolean | false | +| targetFiles | Comma-separated list of files to write aliases to | string | DEFAULT (`/etc/bash.bashrc,/etc/zsh/zshrc` for `root`, otherwise `~/.bashrc,~/.zshrc`) | ## Customizations @@ -32,7 +33,7 @@ Configures Codespace to authenticate with Azure Artifact feeds - `ms-codespaces-tools.ado-codespaces-auth` This installs [Azure Artifacts Credential Provider](https://github.com/microsoft/artifacts-credprovider) -and optionally configures an alias for `dotnet`, `nuget`, `npm`, `yarn`, and `rush` that dynamically sets an authentication token +and optionally configures functions which shadow `dotnet`, `nuget`, `npm`, `yarn`, and `rush` which dynamically sets an authentication token for pulling artifacts from a feed before running the command. For `npm`, `yarn`, and `rush` this requires that your `~/.npmrc` file is configured to use the ${ARTIFACTS_ACCESSTOKEN} diff --git a/src/artifacts-helper/devcontainer-feature.json b/src/artifacts-helper/devcontainer-feature.json index 09879f2..8740655 100644 --- a/src/artifacts-helper/devcontainer-feature.json +++ b/src/artifacts-helper/devcontainer-feature.json @@ -1,7 +1,7 @@ { "name": "Azure Artifacts Credential Helper", "id": "artifacts-helper", - "version": "1.0.9", + "version": "2.0.0", "description": "Configures Codespace to authenticate with Azure Artifact feeds", "options": { "nugetURIPrefixes": { @@ -44,11 +44,16 @@ "default": true, "description": "Create alias for rush" }, + "targetFiles": { + "type": "string", + "default": "DEFAULT", + "description": "Comma separated list of files to write to. Default is '/etc/bash.bashrc,/etc/zsh/zshrc' for root and '~/.bashrc,~/.zshrc' for non-root" + }, "python": { "type": "boolean", "default": false, "description": "Install Python keyring helper for pip" - } + } }, "installsAfter": [ "ghcr.io/devcontainers/features/common-utils", @@ -61,4 +66,4 @@ ] } } -} +} \ No newline at end of file diff --git a/src/artifacts-helper/install.sh b/src/artifacts-helper/install.sh index 99bfe7d..0ab4398 100755 --- a/src/artifacts-helper/install.sh +++ b/src/artifacts-helper/install.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e @@ -11,6 +11,29 @@ ALIAS_YARN="${YARNALIAS:-"true"}" ALIAS_NPX="${NPXALIAS:-"true"}" ALIAS_RUSH="${RUSHALIAS:-"true"}" INSTALL_PIP_HELPER="${PYTHON:-"false"}" +COMMA_SEP_TARGET_FILES="${TARGETFILES:-"DEFAULT"}" + +ALIASES_ARR=() + +if [ "${ALIAS_DOTNET}" = "true" ]; then + ALIASES_ARR+=('dotnet') +fi +if [ "${ALIAS_NUGET}" = "true" ]; then + ALIASES_ARR+=('nuget') +fi +if [ "${ALIAS_NPM}" = "true" ]; then + ALIASES_ARR+=('npm') +fi +if [ "${ALIAS_YARN}" = "true" ]; then + ALIASES_ARR+=('yarn') +fi +if [ "${ALIAS_NPX}" = "true" ]; then + ALIASES_ARR+=('npx') +fi +if [ "${ALIAS_RUSH}" = "true" ]; then + ALIASES_ARR+=('rush') + ALIASES_ARR+=('rush-pnpm') +fi # Source /etc/os-release to get OS info . /etc/os-release @@ -20,8 +43,7 @@ if [ "$(id -u)" -ne 0 ]; then exit 1 fi -apt_get_update() -{ +apt_get_update() { if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then echo "Running apt-get update..." apt-get update -y @@ -72,80 +94,43 @@ chmod +rx /usr/local/bin/run-rush.sh cp ./scripts/run-rush-pnpm.sh /usr/local/bin/run-rush-pnpm.sh chmod +rx /usr/local/bin/run-rush-pnpm.sh - if [ "${INSTALL_PIP_HELPER}" = "true" ]; then USER="${_REMOTE_USER}" /tmp/install-python-keyring.sh rm /tmp/install-python-keyring.sh fi +INSTALL_WITH_SUDO="false" if command -v sudo >/dev/null 2>&1; then if [ "root" != "$_REMOTE_USER" ]; then - if [ "${ALIAS_DOTNET}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias dotnet=/usr/local/bin/run-dotnet.sh' >> ~/.bashrc" - sudo -u ${_REMOTE_USER} bash -c "echo 'alias dotnet=/usr/local/bin/run-dotnet.sh' >> ~/.zshrc" - fi - if [ "${ALIAS_NUGET}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias nuget=/usr/local/bin/run-nuget.sh' >> ~/.bashrc" - sudo -u ${_REMOTE_USER} bash -c "echo 'alias nuget=/usr/local/bin/run-nuget.sh' >> ~/.zshrc" - fi - if [ "${ALIAS_NPM}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npm=/usr/local/bin/run-npm.sh' >> ~/.bashrc" - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npm=/usr/local/bin/run-npm.sh' >> ~/.zshrc" - fi - if [ "${ALIAS_YARN}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias yarn=/usr/local/bin/run-yarn.sh' >> ~/.bashrc" - sudo -u ${_REMOTE_USER} bash -c "echo 'alias yarn=/usr/local/bin/run-yarn.sh' >> ~/.zshrc" - fi - if [ "${ALIAS_NPX}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npx=/usr/local/bin/run-npx.sh' >> ~/.bashrc" - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npx=/usr/local/bin/run-npx.sh' >> ~/.zshrc" - fi - if [ "${ALIAS_RUSH}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush=/usr/local/bin/run-rush.sh' >> ~/.bashrc" - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush=/usr/local/bin/run-rush.sh' >> ~/.zshrc" - - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush-pnpm=/usr/local/bin/run-rush-pnpm.sh' >> ~/.bashrc" - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush-pnpm=/usr/local/bin/run-rush-pnpm.sh' >> ~/.zshrc" - fi - sudo -u ${_REMOTE_USER} bash -c "/tmp/install-provider.sh ${USENET6}" - rm /tmp/install-provider.sh - exit 0 + INSTALL_WITH_SUDO="true" fi fi -if [ "${ALIAS_DOTNET}" = "true" ]; then - echo "alias dotnet='/usr/local/bin/run-dotnet.sh'" >> /etc/bash.bashrc || true - echo "alias dotnet='/usr/local/bin/run-dotnet.sh'" >> /etc/zsh/zshrc || true -fi - -if [ "${ALIAS_NUGET}" = "true" ]; then - echo "alias nuget='/usr/local/bin/run-nuget.sh'" >> /etc/bash.bashrc || true - echo "alias nuget='/usr/local/bin/run-nuget.sh'" >> /etc/zsh/zshrc || true -fi - -if [ "${ALIAS_NPM}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npm=/usr/local/bin/run-npm.sh' >> /etc/bash.bashrc || true - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npm=/usr/local/bin/run-npm.sh' >> /etc/zsh/zshrc || true +if [ "${COMMA_SEP_TARGET_FILES}" = "DEFAULT" ]; then + if [ "${INSTALL_WITH_SUDO}" = "true" ]; then + COMMA_SEP_TARGET_FILES="~/.bashrc,~/.zshrc" + else + COMMA_SEP_TARGET_FILES="/etc/bash.bashrc,/etc/zsh/zshrc" + fi fi -if [ "${ALIAS_YARN}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias yarn=/usr/local/bin/run-yarn.sh' >> /etc/bash.bashrc || true - sudo -u ${_REMOTE_USER} bash -c "echo 'alias yarn=/usr/local/bin/run-yarn.sh' >> /etc/zsh/zshrc || true -fi +IFS=',' read -r -a TARGET_FILES_ARR <<< "$COMMA_SEP_TARGET_FILES" -if [ "${ALIAS_NPX}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npx=/usr/local/bin/run-npx.sh' >> /etc/bash.bashrc || true - sudo -u ${_REMOTE_USER} bash -c "echo 'alias npx=/usr/local/bin/run-npx.sh' >> /etc/zsh/zshrc || true -fi +for ALIAS in "${ALIASES_ARR[@]}"; do + for TARGET_FILE in "${TARGET_FILES_ARR[@]}"; do + CMD="$ALIAS() { /usr/local/bin/run-$ALIAS.sh; }" -if [ "${ALIAS_RUSH}" = "true" ]; then - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush=/usr/local/bin/run-rush.sh' >> /etc/bash.bashrc || true - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush=/usr/local/bin/run-rush.sh' >> /etc/zsh/zshrc || true + if [ "${INSTALL_WITH_SUDO}" = "true" ]; then + sudo -u ${_REMOTE_USER} bash -c "echo '$CMD' >> $TARGET_FILE" + else + echo $CMD >> $TARGET_FILE || true + fi + done +done - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush-pnpm=/usr/local/bin/run-rush-pnpm.sh' >> /etc/bash.bashrc || true - sudo -u ${_REMOTE_USER} bash -c "echo 'alias rush-pnpm=/usr/local/bin/run-rush-pnpm.sh' >> /etc/zsh/zshrc || true +if [ "${INSTALL_WITH_SUDO}" = "true" ]; then + sudo -u ${_REMOTE_USER} bash -c "/tmp/install-provider.sh ${USENET6}" fi - rm /tmp/install-provider.sh exit 0 \ No newline at end of file