|
| 1 | +#!/usr/bin/env bash |
| 2 | +#------------------------------------------------------------------------------------------------------------- |
| 3 | +# Copyright (c) Microsoft Corporation. All rights reserved. |
| 4 | +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. |
| 5 | +#------------------------------------------------------------------------------------------------------------- |
| 6 | +# |
| 7 | +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/github.md |
| 8 | +# Maintainer: The VS Code and Codespaces Teams |
| 9 | +# |
| 10 | +# Syntax: ./github-debian.sh [version] |
| 11 | + |
| 12 | +CLI_VERSION=${1:-"latest"} |
| 13 | + |
| 14 | +GITHUB_CLI_ARCHIVE_GPG_KEY=C99B11DEB97541F0 |
| 15 | +GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80 |
| 16 | +keyserver hkps://keys.openpgp.org |
| 17 | +keyserver hkp://keyserver.pgp.com" |
| 18 | + |
| 19 | +set -e |
| 20 | + |
| 21 | +if [ "$(id -u)" -ne 0 ]; then |
| 22 | + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' |
| 23 | + exit 1 |
| 24 | +fi |
| 25 | + |
| 26 | +# Get central common setting |
| 27 | +get_common_setting() { |
| 28 | + if [ "${common_settings_file_loaded}" != "true" ]; then |
| 29 | + curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping." |
| 30 | + common_settings_file_loaded=true |
| 31 | + fi |
| 32 | + if [ -f "/tmp/vsdc-settings.env" ]; then |
| 33 | + local multi_line="" |
| 34 | + if [ "$2" = "true" ]; then multi_line="-z"; fi |
| 35 | + local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')" |
| 36 | + if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi |
| 37 | + fi |
| 38 | + echo "$1=${!1}" |
| 39 | +} |
| 40 | + |
| 41 | +# Import the specified key in a variable name passed in as |
| 42 | +receive_gpg_keys() { |
| 43 | + get_common_setting $1 |
| 44 | + local keys=${!1} |
| 45 | + get_common_setting GPG_KEY_SERVERS true |
| 46 | + |
| 47 | + # Use a temporary location for gpg keys to avoid polluting image |
| 48 | + export GNUPGHOME="/tmp/tmp-gnupg" |
| 49 | + mkdir -p ${GNUPGHOME} |
| 50 | + chmod 700 ${GNUPGHOME} |
| 51 | + echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf |
| 52 | + # GPG key download sometimes fails for some reason and retrying fixes it. |
| 53 | + local retry_count=0 |
| 54 | + local gpg_ok="false" |
| 55 | + set +e |
| 56 | + until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ]; |
| 57 | + do |
| 58 | + echo "(*) Downloading GPG key..." |
| 59 | + ( echo "${keys}" | xargs -n 1 gpg --recv-keys) 2>&1 && gpg_ok="true" |
| 60 | + if [ "${gpg_ok}" != "true" ]; then |
| 61 | + echo "(*) Failed getting key, retring in 10s..." |
| 62 | + (( retry_count++ )) |
| 63 | + sleep 10s |
| 64 | + fi |
| 65 | + done |
| 66 | + set -e |
| 67 | + if [ "${gpg_ok}" = "false" ]; then |
| 68 | + echo "(!) Failed to get gpg key." |
| 69 | + exit 1 |
| 70 | + fi |
| 71 | +} |
| 72 | + |
| 73 | +# Figure out correct version of a three part version number is not passed |
| 74 | +find_version_from_git_tags() { |
| 75 | + local variable_name=$1 |
| 76 | + local requested_version=${!variable_name} |
| 77 | + if [ "${requested_version}" = "none" ]; then return; fi |
| 78 | + local repository=$2 |
| 79 | + local prefix=${3:-"tags/v"} |
| 80 | + local separator=${4:-"."} |
| 81 | + local last_part_optional=${5:-"false"} |
| 82 | + if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then |
| 83 | + local escaped_separator=${separator//./\\.} |
| 84 | + local last_part |
| 85 | + if [ "${last_part_optional}" = "true" ]; then |
| 86 | + last_part="(${escaped_separator}[0-9]+)?" |
| 87 | + else |
| 88 | + last_part="${escaped_separator}[0-9]+" |
| 89 | + fi |
| 90 | + local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$" |
| 91 | + local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)" |
| 92 | + if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then |
| 93 | + declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)" |
| 94 | + else |
| 95 | + set +e |
| 96 | + declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")" |
| 97 | + set -e |
| 98 | + fi |
| 99 | + fi |
| 100 | + if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then |
| 101 | + echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2 |
| 102 | + exit 1 |
| 103 | + fi |
| 104 | + echo "${variable_name}=${!variable_name}" |
| 105 | +} |
| 106 | + |
| 107 | +# Import the specified key in a variable name passed in as |
| 108 | +receive_gpg_keys() { |
| 109 | + get_common_setting $1 |
| 110 | + local keys=${!1} |
| 111 | + get_common_setting GPG_KEY_SERVERS true |
| 112 | + local keyring_args="" |
| 113 | + if [ ! -z "$2" ]; then |
| 114 | + keyring_args="--no-default-keyring --keyring $2" |
| 115 | + fi |
| 116 | + |
| 117 | + # Use a temporary location for gpg keys to avoid polluting image |
| 118 | + export GNUPGHOME="/tmp/tmp-gnupg" |
| 119 | + mkdir -p ${GNUPGHOME} |
| 120 | + chmod 700 ${GNUPGHOME} |
| 121 | + echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf |
| 122 | + # GPG key download sometimes fails for some reason and retrying fixes it. |
| 123 | + local retry_count=0 |
| 124 | + local gpg_ok="false" |
| 125 | + set +e |
| 126 | + until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ]; |
| 127 | + do |
| 128 | + echo "(*) Downloading GPG key..." |
| 129 | + ( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true" |
| 130 | + if [ "${gpg_ok}" != "true" ]; then |
| 131 | + echo "(*) Failed getting key, retring in 10s..." |
| 132 | + (( retry_count++ )) |
| 133 | + sleep 10s |
| 134 | + fi |
| 135 | + done |
| 136 | + set -e |
| 137 | + if [ "${gpg_ok}" = "false" ]; then |
| 138 | + echo "(!) Failed to get gpg key." |
| 139 | + exit 1 |
| 140 | + fi |
| 141 | +} |
| 142 | + |
| 143 | +# Function to run apt-get if needed |
| 144 | +apt_get_update_if_needed() |
| 145 | +{ |
| 146 | + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then |
| 147 | + echo "Running apt-get update..." |
| 148 | + apt-get update |
| 149 | + else |
| 150 | + echo "Skipping apt-get update." |
| 151 | + fi |
| 152 | +} |
| 153 | + |
| 154 | +# Checks if packages are installed and installs them if not |
| 155 | +check_packages() { |
| 156 | + if ! dpkg -s "$@" > /dev/null 2>&1; then |
| 157 | + apt_get_update_if_needed |
| 158 | + apt-get -y install --no-install-recommends "$@" |
| 159 | + fi |
| 160 | +} |
| 161 | + |
| 162 | +export DEBIAN_FRONTEND=noninteractive |
| 163 | + |
| 164 | +# Install curl, apt-transport-https, curl, gpg, or dirmngr, git if missing |
| 165 | +check_packages curl ca-certificates apt-transport-https dirmngr gnupg2 |
| 166 | +if ! type git > /dev/null 2>&1; then |
| 167 | + apt_get_update_if_needed |
| 168 | + apt-get -y install --no-install-recommends git |
| 169 | +fi |
| 170 | + |
| 171 | +# Soft version matching |
| 172 | +if [ "${CLI_VERSION}" != "latest" ] && [ "${CLI_VERSION}" != "lts" ] && [ "${CLI_VERSION}" != "stable" ]; then |
| 173 | + find_version_from_git_tags CLI_VERSION "https://github.com/cli/cli" |
| 174 | + version_suffix="=${CLI_VERSION}" |
| 175 | +else |
| 176 | + version_suffix="" |
| 177 | +fi |
| 178 | + |
| 179 | +# Install the GitHub CLI |
| 180 | +echo "Downloading GitHub CLI..." |
| 181 | +# Import key safely (new method rather than deprecated apt-key approach) and install |
| 182 | +. /etc/os-release |
| 183 | +receive_gpg_keys GITHUB_CLI_ARCHIVE_GPG_KEY /usr/share/keyrings/githubcli-archive-keyring.gpg |
| 184 | +echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/github-cli.list |
| 185 | +apt-get update |
| 186 | +apt-get -y install "gh${version_suffix}" |
| 187 | +rm -rf "/tmp/gh/gnupg" |
| 188 | +echo "Done!" |
0 commit comments