From 4a15fabff4cd4feb238a5ebe7208f13a6ab9ee65 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 19 Sep 2023 16:46:31 -0700 Subject: [PATCH 01/42] Convert docker action to typescript --- .github/workflows/run-validation.yml | 6 +- .gitignore | 2 + action.yml | 554 +-- azurecontainerapps.ts | 522 +++ dist/index.js | 6061 ++++++++++++++++++++++++++ dist/licenses.txt | 97 + package-lock.json | 491 +++ package.json | 29 + src/CommandHelper.ts | 89 + src/ContainerAppHelper.ts | 439 ++ src/ContainerRegistryHelper.ts | 55 + src/TelemetryHelper.ts | 108 + src/Utility.ts | 58 + tsconfig.json | 9 + 14 files changed, 7968 insertions(+), 552 deletions(-) create mode 100644 .gitignore create mode 100644 azurecontainerapps.ts create mode 100644 dist/index.js create mode 100644 dist/licenses.txt create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/CommandHelper.ts create mode 100644 src/ContainerAppHelper.ts create mode 100644 src/ContainerRegistryHelper.ts create mode 100644 src/TelemetryHelper.ts create mode 100644 src/Utility.ts create mode 100644 tsconfig.json diff --git a/.github/workflows/run-validation.yml b/.github/workflows/run-validation.yml index efb5b534..9495df46 100644 --- a/.github/workflows/run-validation.yml +++ b/.github/workflows/run-validation.yml @@ -1,6 +1,7 @@ name: Run validation on action on: + workflow_dispatch: push: branches: - main @@ -270,11 +271,6 @@ jobs: WORKSPACE_NAME=$(az monitor log-analytics workspace list -g ${{ vars.TEST_RESOURCE_GROUP_NAME }} --query '[?customerId == `${{ env.CUSTOMER_ID }}`].name | [0]') echo "WORKSPACE_NAME=${WORKSPACE_NAME}" >> $GITHUB_ENV - - name: Delete created Azure Container App environment - if: ${{ always() }} - shell: bash - run: az containerapp env delete -g ${{ vars.TEST_RESOURCE_GROUP_NAME }} -n ${{ env.TEST_NEW_CONTAINER_APP_ENV }} -y - - name: Delete created workspace if: ${{ always() }} shell: bash diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..187c09f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# .gitignore +node_modules/ \ No newline at end of file diff --git a/action.yml b/action.yml index 472c5ef7..6897a644 100644 --- a/action.yml +++ b/action.yml @@ -22,13 +22,13 @@ inputs: access token will be generated via "az acr login" and provided to "docker login" to authenticate the requests.' required: false registryUrl: - description: 'The base URL of the Container Registry that the runnable application image will be pushed to.' + description: 'The base URL of the Container Registry that the runnable application image will be pushed to.' required: false - registryUsername: - description: 'The username used to authenticate push requests to the provided Container Registry using the "docker login" action.' + registryUsername: + description: 'The username used to authenticate push requests to the provided Container Registry using the "docker login" action.' required: false - registryPassword: - description: 'The password used to authenticate push requests to the provided Container Registry using the "docker login" action.' + registryPassword: + description: 'The password used to authenticate push requests to the provided Container Registry using the "docker login" action.' required: false azureCredentials: description: | @@ -126,545 +126,5 @@ inputs: default: false runs: - using: "composite" - steps: - - name: Start timer to track action execution length, in milliseconds - if: ${{ always() && inputs.disableTelemetry == 'false' }} - shell: bash - run: | - CA_GH_ACTION_START_MILLISECONDS=$(date +%s%N | cut -b1-13) - echo "CA_GH_ACTION_START_MILLISECONDS=${CA_GH_ACTION_START_MILLISECONDS}" >> $GITHUB_ENV - CA_GH_ACTION_RESULT_ARG="--property 'result=failed'" - echo "CA_GH_ACTION_RESULT_ARG=${CA_GH_ACTION_RESULT_ARG}" >> $GITHUB_ENV - - - name: Check that an ACR name and a registry URL are not provided together - if: ${{ inputs.acrName != '' && inputs.registryUrl != '' }} - shell: bash - run: | - echo "Both 'acrName' and 'registryUrl' arguments cannot be provided together." - exit 1 - - - name: Check for ACR name or any other registry url provided with application source path - if: ${{ inputs.appSourcePath != '' && inputs.acrName == '' && inputs.registryUrl == '' }} - shell: bash - run: | - echo "The 'acrName' argument or the 'registryUrl' argument must also be provided if the 'appSourcePath' argument is provided." - exit 1 - - - name: Check for application source path, a previously built image or a YAML configuration file - if: ${{ inputs.appSourcePath == '' && inputs.imageToDeploy == '' && inputs.yamlConfigPath == '' }} - shell: bash - run: | - echo "One of the following arguments must be provided: appSourcePath, imageToDeploy, yamlConfigPath" - exit 1 - - - name: Check if the YAML configuration file is provided - if: ${{ inputs.yamlConfigPath != '' }} - shell: bash - run: | - CA_GH_ACTION_YAML_PROVIDED=true - echo "CA_GH_ACTION_YAML_PROVIDED=${CA_GH_ACTION_YAML_PROVIDED}" >> $GITHUB_ENV - - - name: Check if only the YAML configuration file is being used - if: ${{ inputs.appSourcePath == '' && inputs.imageToDeploy == '' && inputs.yamlConfigPath != '' }} - shell: bash - run: | - CA_GH_ACTION_ONLY_YAML=true - echo "CA_GH_ACTION_ONLY_YAML=${CA_GH_ACTION_ONLY_YAML}" >> $GITHUB_ENV - - - name: Set Azure CLI to dynamically install missing extensions - shell: bash - run: az config set extension.use_dynamic_install=yes_without_prompt - - - name: Log in to Azure - if: ${{ inputs.azureCredentials != '' }} - uses: azure/login@v1 - with: - creds: ${{ inputs.azureCredentials }} - - - name: Log in to Azure Container Registry - uses: docker/login-action@v2.2.0 - if: ${{ inputs.acrName != '' && inputs.acrUsername != '' && inputs.acrPassword != '' }} - with: - registry: ${{ inputs.acrName }}.azurecr.io - username: ${{ inputs.acrUsername }} - password: ${{ inputs.acrPassword }} - - - name: Log in to Container Registry - uses: docker/login-action@v2.2.0 - if: ${{ inputs.registryUrl != '' && inputs.registryUsername != '' && inputs.registryPassword != '' }} - with: - registry: ${{ inputs.registryUrl }} - username: ${{ inputs.registryUsername }} - password: ${{ inputs.registryPassword }} - - - name: Export Container Registry information to environment variable - if: ${{ inputs.registryUrl != '' && inputs.registryUsername != '' && inputs.registryPassword != '' && env.CA_GH_ACTION_ONLY_YAML != 'true' }} - shell: bash - run: | - CA_GH_ACTION_REGISTRY_LOGIN_ARG="--registry-server ${{ inputs.registryUrl }} --registry-username ${{ inputs.registryUsername }} --registry-password ${{ inputs.registryPassword }}" - CA_GH_ACTION_REGISTRY_URL=${{ inputs.registryUrl }} - CA_GH_ACTION_REGISTRY_USERNAME=${{ inputs.registryUsername }} - CA_GH_ACTION_REGISTRY_PASSWORD=${{ inputs.registryPassword }} - echo "CA_GH_ACTION_REGISTRY_LOGIN_ARG=${CA_GH_ACTION_REGISTRY_LOGIN_ARG}" >> $GITHUB_ENV - echo "CA_GH_ACTION_REGISTRY_URL=${CA_GH_ACTION_REGISTRY_URL}" >> $GITHUB_ENV - echo "CA_GH_ACTION_REGISTRY_USERNAME=${CA_GH_ACTION_REGISTRY_USERNAME}" >> $GITHUB_ENV - echo "CA_GH_ACTION_REGISTRY_PASSWORD=${CA_GH_ACTION_REGISTRY_PASSWORD}" >> $GITHUB_ENV - - - name: Export Azure Container Registry information to environment variable for Azure CLI command - if: ${{ inputs.acrName != '' && inputs.acrUsername != '' && inputs.acrPassword != '' && env.CA_GH_ACTION_ONLY_YAML != 'true' }} - shell: bash - run: | - CA_GH_ACTION_REGISTRY_LOGIN_ARG="--registry-server ${{ inputs.acrName }}.azurecr.io --registry-username ${{ inputs.acrUsername }} --registry-password ${{ inputs.acrPassword }}" - CA_GH_ACTION_REGISTRY_URL=${{ inputs.acrName }}.azurecr.io - CA_GH_ACTION_REGISTRY_USERNAME=${{ inputs.acrUsername }} - CA_GH_ACTION_REGISTRY_PASSWORD=${{ inputs.acrPassword }} - echo "CA_GH_ACTION_REGISTRY_LOGIN_ARG=${CA_GH_ACTION_REGISTRY_LOGIN_ARG}" >> $GITHUB_ENV - echo "CA_GH_ACTION_REGISTRY_URL=${CA_GH_ACTION_REGISTRY_URL}" >> $GITHUB_ENV - echo "CA_GH_ACTION_REGISTRY_USERNAME=${CA_GH_ACTION_REGISTRY_USERNAME}" >> $GITHUB_ENV - echo "CA_GH_ACTION_REGISTRY_PASSWORD=${CA_GH_ACTION_REGISTRY_PASSWORD}" >> $GITHUB_ENV - - - name: Get access token to log in to Azure Container Registry - if: ${{ inputs.acrName != '' && (inputs.acrUsername == '' || inputs.acrPassword == '') }} - shell: bash - run: | - CA_GH_ACTION_ACR_ACCESS_TOKEN=$(az acr login --name ${{ inputs.acrName }} --output json --expose-token | jq -r '.accessToken') - echo "CA_GH_ACTION_ACR_ACCESS_TOKEN=${CA_GH_ACTION_ACR_ACCESS_TOKEN}" >> $GITHUB_ENV - docker login ${{ inputs.acrName }}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_GH_ACTION_ACR_ACCESS_TOKEN - CA_GH_ACTION_REGISTRY_URL=${{ inputs.acrName }}.azurecr.io - echo "CA_GH_ACTION_REGISTRY_URL=${CA_GH_ACTION_REGISTRY_URL}" >> $GITHUB_ENV - - - name: Export Dockerfile path to environment variable - if: ${{ inputs.appSourcePath != '' && inputs.dockerfilePath != '' }} - shell: bash - run: | - CA_GH_ACTION_DOCKERFILE_PATH="${{ inputs.appSourcePath }}/${{ inputs.dockerfilePath }}" - echo "CA_GH_ACTION_DOCKERFILE_PATH=${CA_GH_ACTION_DOCKERFILE_PATH}" >> $GITHUB_ENV - - - name: Check for existing Dockerfile in application source - if: ${{ inputs.appSourcePath != '' && inputs.dockerfilePath == '' }} - shell: bash - run: | - dockerfilePath=${{ inputs.appSourcePath }}/Dockerfile - if [ -f "$dockerfilePath" ]; then echo "CA_GH_ACTION_DOCKERFILE_PATH=${dockerfilePath}" >> $GITHUB_ENV; fi - - - name: Export name of image to build to environment variable - if: ${{ inputs.imageToBuild != '' && env.CA_GH_ACTION_ONLY_YAML != 'true' }} - shell: bash - run: | - CA_GH_ACTION_IMAGE_TO_BUILD="${{ inputs.imageToBuild }}" - echo "CA_GH_ACTION_IMAGE_TO_BUILD=${CA_GH_ACTION_IMAGE_TO_BUILD}" >> $GITHUB_ENV - - - name: Determine name of image to build if not provided - if: ${{ env.CA_GH_ACTION_REGISTRY_URL != '' && inputs.imageToBuild == '' && env.CA_GH_ACTION_ONLY_YAML != 'true' }} - shell: bash - run: | - CA_GH_ACTION_IMAGE_TO_BUILD="${{ env.CA_GH_ACTION_REGISTRY_URL }}/github-action/container-app:${{ github.run_id }}.${{ github.run_attempt }}" - echo "CA_GH_ACTION_IMAGE_TO_BUILD=${CA_GH_ACTION_IMAGE_TO_BUILD}" >> $GITHUB_ENV - - - name: Export name of image to deploy to environment variable - if: ${{ inputs.imageToDeploy != '' }} - shell: bash - run: | - CA_GH_ACTION_IMAGE_TO_DEPLOY="${{ inputs.imageToDeploy }}" - echo "CA_GH_ACTION_IMAGE_TO_DEPLOY=${CA_GH_ACTION_IMAGE_TO_DEPLOY}" >> $GITHUB_ENV - - - name: Update name of image to deploy if not provided - if: ${{ inputs.imageToDeploy == '' && env.CA_GH_ACTION_ONLY_YAML != 'true' }} - shell: bash - run: | - CA_GH_ACTION_IMAGE_TO_DEPLOY="${{ env.CA_GH_ACTION_IMAGE_TO_BUILD }}" - echo "CA_GH_ACTION_IMAGE_TO_DEPLOY=${CA_GH_ACTION_IMAGE_TO_DEPLOY}" >> $GITHUB_ENV - - - name: Export resource group to environment variable - if: ${{ inputs.resourceGroup != '' }} - shell: bash - run: | - CA_GH_ACTION_RESOURCE_GROUP="${{ inputs.resourceGroup }}" - echo "CA_GH_ACTION_RESOURCE_GROUP=${CA_GH_ACTION_RESOURCE_GROUP}" >> $GITHUB_ENV - - - name: Determine resource group if not provided - if: ${{ inputs.resourceGroup == '' }} - shell: bash - run: | - CA_GH_ACTION_RESOURCE_GROUP="${{ inputs.containerAppName }}-rg" - echo "CA_GH_ACTION_RESOURCE_GROUP=${CA_GH_ACTION_RESOURCE_GROUP}" >> $GITHUB_ENV - - - name: Check if the previously generated resource group exists - if: ${{ inputs.resourceGroup == '' }} - shell: bash - run: | - az group show \ - -n ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -o none && CA_GH_ACTION_RG_EXISTS=true || CA_GH_ACTION_RG_EXISTS=false - echo "CA_GH_ACTION_RG_EXISTS=${CA_GH_ACTION_RG_EXISTS}" >> $GITHUB_ENV - - - name: Get default location for Container Apps to use if resource group doesn't exist and location wasn't provided - if: ${{ env.CA_GH_ACTION_RG_EXISTS == 'false' && inputs.location == '' }} - shell: bash - run: | - CA_GH_ACTION_DEFAULT_LOCATION=$(az provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]") - CA_GH_ACTION_DEFAULT_LOCATION=$(echo $CA_GH_ACTION_DEFAULT_LOCATION | sed 's/[ !()]//g') - CA_GH_ACTION_DEFAULT_LOCATION=${CA_GH_ACTION_DEFAULT_LOCATION,,} - echo "CA_GH_ACTION_DEFAULT_LOCATION=${CA_GH_ACTION_DEFAULT_LOCATION}" >> $GITHUB_ENV - - - name: Set default location for Container Apps if location was provided - if: ${{ env.CA_GH_ACTION_RG_EXISTS == 'false' && inputs.location != '' }} - shell: bash - run: | - CA_GH_ACTION_DEFAULT_LOCATION="${{ inputs.location }}" - echo "CA_GH_ACTION_DEFAULT_LOCATION=${CA_GH_ACTION_DEFAULT_LOCATION}" >> $GITHUB_ENV - - - name: Create resource group if it doesn't exist - if: ${{ env.CA_GH_ACTION_RG_EXISTS == 'false' }} - shell: bash - run: | - az group create \ - -n ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -l ${{ env.CA_GH_ACTION_DEFAULT_LOCATION }} - - - name: Export location argument to environment variable - if: ${{ inputs.location != '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_CONTAINER_APP_LOCATION_ARG="--location ${{ inputs.location }}" - echo "CA_GH_ACTION_CONTAINER_APP_LOCATION_ARG=${CA_GH_ACTION_CONTAINER_APP_LOCATION_ARG}" >> $GITHUB_ENV - - - name: Check if the Container App already exists in the resource group - shell: bash - run: | - az containerapp show \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} \ - -o none && CA_GH_ACTION_RESOURCE_EXISTS=true || CA_GH_ACTION_RESOURCE_EXISTS=false - echo "CA_GH_ACTION_RESOURCE_EXISTS=${CA_GH_ACTION_RESOURCE_EXISTS}" >> $GITHUB_ENV - - - name: Export environment to environment variable - if: ${{ inputs.containerAppEnvironment != '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT="${{ inputs.containerAppEnvironment }}" - echo "CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT=${CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT}" >> $GITHUB_ENV - - - name: Determine environment name if not provided - if: ${{ inputs.containerAppEnvironment == '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT="${{ inputs.containerAppName }}-env" - echo "CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT=${CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT}" >> $GITHUB_ENV - - - name: Check if Container App environment already exists with the provided/determined name - if: ${{ env.CA_GH_ACTION_RESOURCE_EXISTS == 'false' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - az containerapp env show \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ env.CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT }} \ - -o none && CA_GH_ACTION_ENVIRONMENT_EXISTS=true || CA_GH_ACTION_ENVIRONMENT_EXISTS=false - echo "CA_GH_ACTION_ENVIRONMENT_EXISTS=${CA_GH_ACTION_ENVIRONMENT_EXISTS}" >> $GITHUB_ENV - - - name: Reuse an existing Container App environment if found in the resource group - if: ${{ env.CA_GH_ACTION_ENVIRONMENT_EXISTS == 'false' && inputs.containerAppEnvironment == '' && env.CA_CH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_TEMP_ENV_NAME=$(az containerapp env list -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} --query '[0].name') - if [[ $CA_GH_ACTION_TEMP_ENV_NAME != '' ]]; then \ - echo "CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT=${CA_GH_ACTION_TEMP_ENV_NAME}" >> $GITHUB_ENV; \ - echo "CA_GH_ACTION_ENVIRONMENT_EXISTS=true" >> $GITHUB_ENV; \ - fi - - - name: Create Container App environment if the Container App environment doesn't exist - if: ${{ env.CA_GH_ACTION_ENVIRONMENT_EXISTS == 'false' }} - shell: bash - run: | - az containerapp env create \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ env.CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT }} \ - ${{ env.CA_GH_ACTION_CONTAINER_APP_LOCATION_ARG }} - - - name: Export runtime stack to environment variable - if: ${{ inputs.runtimeStack != '' && env.CA_GH_ACTION_ONLY_YAML != 'true' }} - shell: bash - run: | - CA_GH_ACTION_RUNTIME_STACK="${{ inputs.runtimeStack }}" - echo "CA_GH_ACTION_RUNTIME_STACK=${CA_GH_ACTION_RUNTIME_STACK}" >> $GITHUB_ENV - - - name: Determine runtime stack if not provided - if: ${{ inputs.appSourcePath != '' && inputs.runtimeStack == '' }} - shell: bash - run: | - docker run \ - --rm \ - -v ${{ inputs.appSourcePath }}:/app \ - mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1 \ - /bin/bash \ - -c "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt" - CA_GH_ACTION_RUNTIME_STACK=$(head -n 1 ${{ inputs.appSourcePath }}/oryx-runtime.txt) - echo "CA_GH_ACTION_RUNTIME_STACK=${CA_GH_ACTION_RUNTIME_STACK}" >> $GITHUB_ENV - rm ${{ inputs.appSourcePath }}/oryx-runtime.txt - - - name: Export disabled ingress value to environment variable - if: ${{ inputs.ingress == 'disabled' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_INGRESS_ENABLED="false" - echo "CA_GH_ACTION_INGRESS_ENABLED=${CA_GH_ACTION_INGRESS_ENABLED}" >> $GITHUB_ENV - - - name: Set default value of ingress to 'external' if not provided - if: ${{ inputs.ingress == '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_INGRESS_ENABLED="true" - echo "CA_GH_ACTION_INGRESS_ENABLED=${CA_GH_ACTION_INGRESS_ENABLED}" >> $GITHUB_ENV - CA_GH_ACTION_INGRESS_ARG="--ingress external" - echo "CA_GH_ACTION_INGRESS_ARG=${CA_GH_ACTION_INGRESS_ARG}" >> $GITHUB_ENV - - - name: Export ingress value to environment variable - if: ${{ inputs.ingress != '' && inputs.ingress != 'disabled' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_INGRESS_ENABLED="true" - echo "CA_GH_ACTION_INGRESS_ENABLED=${CA_GH_ACTION_INGRESS_ENABLED}" >> $GITHUB_ENV - CA_GH_ACTION_INGRESS_ARG="--ingress ${{ inputs.ingress }}" - echo "CA_GH_ACTION_INGRESS_ARG=${CA_GH_ACTION_INGRESS_ARG}" >> $GITHUB_ENV - - - name: Export target port to environment variable - if: ${{ env.CA_GH_ACTION_INGRESS_ENABLED == 'true' && inputs.targetPort != '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_TARGET_PORT="${{ inputs.targetPort }}" - echo "CA_GH_ACTION_TARGET_PORT=${CA_GH_ACTION_TARGET_PORT}" >> $GITHUB_ENV - - - name: Determine default target port if not provided and no Dockerfile provided/found - if: ${{ env.CA_GH_ACTION_INGRESS_ENABLED == 'true' && inputs.targetPort == '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' && inputs.appSourcePath != '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - if [[ "${{ env.CA_GH_ACTION_RUNTIME_STACK }}" == "python:"* ]]; then echo "CA_GH_ACTION_TARGET_PORT=80" >> $GITHUB_ENV; else echo "CA_GH_ACTION_TARGET_PORT=8080" >> $GITHUB_ENV; fi - - - name: Default to target port 80 if one wasn't provided or found, and ingress is enabled, and the Container App doesn't exist (prevent overriding) - if: ${{ env.CA_GH_ACTION_INGRESS_ENABLED == 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'false' && env.CA_GH_ACTION_TARGET_PORT == '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_TARGET_PORT="80" - echo "CA_GH_ACTION_TARGET_PORT=${CA_GH_ACTION_TARGET_PORT}" >> $GITHUB_ENV - - - name: Export target port information to environment variable for Azure CLI command - if: ${{ env.CA_GH_ACTION_INGRESS_ENABLED == 'true' && env.CA_GH_ACTION_TARGET_PORT != '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_TARGET_PORT_ARG="--target-port ${{ env.CA_GH_ACTION_TARGET_PORT }}" - echo "CA_GH_ACTION_TARGET_PORT_ARG=${CA_GH_ACTION_TARGET_PORT_ARG}" >> $GITHUB_ENV - - - name: Export environment variables argument to environment variable if the Container App does not exist - if: ${{ inputs.environmentVariables != '' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'false' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG="--env-vars ${{ inputs.environmentVariables }}" - echo "CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG=${CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG}" >> $GITHUB_ENV - - - name: Export environment variables argument to environment variable if the Container App does exist - if: ${{ inputs.environmentVariables != '' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'true' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG="--replace-env-vars ${{ inputs.environmentVariables }}" - echo "CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG=${CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG}" >> $GITHUB_ENV - - - name: Install pack CLI on non-Windows runner - if: ${{ runner.os != 'Windows' && inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' }} - shell: bash - run: (curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${{ runner.os }}.tgz" | sudo tar -C /usr/local/bin/ --no-same-owner -xzv pack) - - - name: Install pack CLI on Windows runner - if: ${{ runner.os == 'Windows' && inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' }} - shell: bash - run: | - mkdir -p $PWD/pack && cd $PWD/pack - curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip" -o "pack-windows.zip" - 7z x pack-windows.zip > /dev/null 2>&1 - rm pack-windows.zip && echo "$PWD" >> $GITHUB_PATH - - - name: Set Oryx++ Builder as default builder - if: ${{ inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' }} - shell: bash - run: pack config default-builder mcr.microsoft.com/oryx/builder:20230208.1 - - - name: Set telemetry for Oryx++ Builder - if: ${{ inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' && inputs.disableTelemetry == 'false' }} - shell: bash - run: | - CA_GH_ACTION_ORYX_BUILDER_TELEMETRY_ARG='--env "CALLER_ID=github-actions-v1"' - echo "CA_GH_ACTION_ORYX_BUILDER_TELEMETRY_ARG=${CA_GH_ACTION_ORYX_BUILDER_TELEMETRY_ARG}" >> $GITHUB_ENV - - - name: Disable telemetry for Oryx++ Builder - if: ${{ inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' && inputs.disableTelemetry == 'true' }} - shell: bash - run: | - CA_GH_ACTION_ORYX_BUILDER_TELEMETRY_ARG='--env "ORYX_DISABLE_TELEMETRY=true"' - echo "CA_GH_ACTION_ORYX_BUILDER_TELEMETRY_ARG=${CA_GH_ACTION_ORYX_BUILDER_TELEMETRY_ARG}" >> $GITHUB_ENV - - - name: Create runnable application image using Oryx++ Builder - if: ${{ inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' }} - shell: bash - run: | - pack build \ - ${{ env.CA_GH_ACTION_IMAGE_TO_DEPLOY }} \ - --path ${{ inputs.appSourcePath }} \ - --builder mcr.microsoft.com/oryx/builder:20230208.1 \ - --run-image mcr.microsoft.com/oryx/${{ env.CA_GH_ACTION_RUNTIME_STACK }} \ - ${{ env.CA_GH_ACTION_ORYX_BUILDER_TELEMETRY_ARG }} - - - name: Create runnable application image using provided Dockerfile - if: ${{ inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH != '' }} - shell: bash - run: | - docker build \ - --tag ${{ env.CA_GH_ACTION_IMAGE_TO_DEPLOY }} \ - --file ${{ env.CA_GH_ACTION_DOCKERFILE_PATH }} \ - ${{ inputs.appSourcePath }} - - - name: Push image to Container Registry - if: ${{ inputs.appSourcePath != '' }} - shell: bash - run: docker push ${{ env.CA_GH_ACTION_IMAGE_TO_DEPLOY }} - - - name: Create the Container App from a YAML configuration file - if: ${{ env.CA_GH_ACTION_YAML_PROVIDED == 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'false' }} - shell: bash - run: | - az containerapp create \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} \ - --yaml ${{ inputs.yamlConfigPath }} - - - name: Create the Container App from provided arguments - if: ${{ env.CA_GH_ACTION_YAML_PROVIDED != 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'false' }} - shell: bash - run: | - az containerapp create \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} \ - -i ${{ env.CA_GH_ACTION_IMAGE_TO_DEPLOY }} \ - --environment ${{ env.CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT }} \ - ${{ env.CA_GH_ACTION_INGRESS_ARG }} \ - ${{ env.CA_GH_ACTION_TARGET_PORT_ARG }} \ - ${{ env.CA_GH_ACTION_REGISTRY_LOGIN_ARG }} \ - ${{ env.CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG }} - - - name: Update the existing Container App from a YAML configuration file - if: ${{ env.CA_GH_ACTION_YAML_PROVIDED == 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'true' }} - shell: bash - run: | - az containerapp update \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} \ - --yaml ${{ inputs.yamlConfigPath }} - - - name: Determine whether or not 'update' or 'up' should be used - if: ${{ env.CA_GH_ACTION_YAML_PROVIDED != 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'true' && (inputs.targetPort != '' || inputs.ingress != '') }} - shell: bash - run: | - CA_GH_ACTION_USE_UP="true" - echo "CA_GH_ACTION_USE_UP=${CA_GH_ACTION_USE_UP}" >> $GITHUB_ENV - - - name: Update the Container Registry details on the existing Container App - if: ${{ env.CA_GH_ACTION_REGISTRY_LOGIN_ARG != '' && env.CA_GH_ACTION_USE_UP != 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'true' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - az containerapp registry set \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} \ - --server ${{ env.CA_GH_ACTION_REGISTRY_URL }} \ - --username ${{ env.CA_GH_ACTION_REGISTRY_USERNAME }} \ - --password ${{ env.CA_GH_ACTION_REGISTRY_PASSWORD }} - - - name: Update the existing Container App from provided arguments via 'update' (no ingress values provided) - if: ${{ env.CA_GH_ACTION_USE_UP != 'true' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'true' }} - shell: bash - run: | - az containerapp update \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} \ - -i ${{ env.CA_GH_ACTION_IMAGE_TO_DEPLOY }} \ - ${{ env.CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG }} - - - name: Reset the ingress argument environment variable if it wasn't provided (use default ingress value) - if: ${{ inputs.ingress == '' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' && env.CA_GH_ACTION_RESOURCE_EXISTS == 'true' }} - shell: bash - run: | - CA_GH_ACTION_INGRESS_ARG="" - echo "CA_GH_ACTION_INGRESS_ARG=${CA_GH_ACTION_INGRESS_ARG}" >> $GITHUB_ENV - - - name: Reset the environment variables argument environment variable for the 'up' command - if: ${{ env.CA_GH_ACTION_USE_UP == 'true' && inputs.environmentVariables != '' }} - shell: bash - run: | - CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG="--env-vars ${{ inputs.environmentVariables }}" - echo "CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG=${CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG}" >> $GITHUB_ENV - - - name: Update the existing Container App from provided arguments via 'up' (ingress values provided) - if: ${{ env.CA_GH_ACTION_USE_UP == 'true' }} - shell: bash - run: | - az containerapp up \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} \ - -i ${{ env.CA_GH_ACTION_IMAGE_TO_DEPLOY }} \ - ${{ env.CA_GH_ACTION_TARGET_PORT_ARG }} \ - ${{ env.CA_GH_ACTION_INGRESS_ARG }} \ - ${{ env.CA_GH_ACTION_CONTAINER_APP_ENVIRONMENT_VARIABLES_ARG }} \ - ${{ env.CA_GH_ACTION_REGISTRY_LOGIN_ARG }} - - - name: Disable ingress on the existing Container App - if: ${{ env.CA_GH_ACTION_RESOURCE_EXISTS == 'true' && inputs.ingress == 'disabled' && env.CA_GH_ACTION_YAML_PROVIDED != 'true' }} - shell: bash - run: | - az containerapp ingress disable \ - -g ${{ env.CA_GH_ACTION_RESOURCE_GROUP }} \ - -n ${{ inputs.containerAppName }} - - - name: Mark action as 'succeeded' for telemetry - if: ${{ inputs.disableTelemetry == 'false' }} - shell: bash - run: | - CA_GH_ACTION_RESULT_ARG="--property 'result=succeeded'" - echo "CA_GH_ACTION_RESULT_ARG=${CA_GH_ACTION_RESULT_ARG}" >> $GITHUB_ENV - - - name: End timer that's tracking action execution length, in milliseconds - if: ${{ always() && inputs.disableTelemetry == 'false' }} - shell: bash - run: | - CA_GH_ACTION_END_MILLISECONDS=$(date +%s%N | cut -b1-13) - CA_GH_ACTION_START_MILLISECONDS=${{ env.CA_GH_ACTION_START_MILLISECONDS }} - CA_GH_ACTION_LENGTH_MILLISECONDS_ARG="--processing-time '$((CA_GH_ACTION_END_MILLISECONDS-CA_GH_ACTION_START_MILLISECONDS))'" - echo "CA_GH_ACTION_LENGTH_MILLISECONDS_ARG=${CA_GH_ACTION_LENGTH_MILLISECONDS_ARG}" >> $GITHUB_ENV - - - name: Set telemetry for previously built image scenario - if: ${{ inputs.disableTelemetry == 'false' && inputs.appSourcePath == '' }} - shell: bash - run: | - CA_GH_ACTION_SCENARIO_ARG="--property 'scenario=used-image'" - echo "CA_GH_ACTION_SCENARIO_ARG=${CA_GH_ACTION_SCENARIO_ARG}" >> $GITHUB_ENV - - - name: Set telemetry for built Dockerfile scenario - if: ${{ inputs.disableTelemetry == 'false' && env.CA_GH_ACTION_DOCKERFILE_PATH != '' }} - shell: bash - run: | - CA_GH_ACTION_SCENARIO_ARG="--property 'scenario=used-dockerfile'" - echo "CA_GH_ACTION_SCENARIO_ARG=${CA_GH_ACTION_SCENARIO_ARG}" >> $GITHUB_ENV - - - name: Set telemetry for no Dockerfile scenario - if: ${{ inputs.disableTelemetry == 'false' && inputs.appSourcePath != '' && env.CA_GH_ACTION_DOCKERFILE_PATH == '' }} - shell: bash - run: | - CA_GH_ACTION_SCENARIO_ARG="--property 'scenario=used-builder'" - echo "CA_GH_ACTION_SCENARIO_ARG=${CA_GH_ACTION_SCENARIO_ARG}" >> $GITHUB_ENV - - - name: Log telemetry for action - if: ${{ always() && inputs.disableTelemetry == 'false' }} - shell: bash - run: | - docker run \ - --rm \ - mcr.microsoft.com/oryx/cli:debian-buster-20230207.2 \ - /bin/bash \ - -c "oryx telemetry --event-name 'ContainerAppsGitHubAction' ${{ env.CA_GH_ACTION_LENGTH_MILLISECONDS_ARG }} ${{ env.CA_GH_ACTION_SCENARIO_ARG }} ${{ env.CA_GH_ACTION_RESULT_ARG }}" + using: 'node16' + main: 'dist/index.js' \ No newline at end of file diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts new file mode 100644 index 00000000..ba92c6eb --- /dev/null +++ b/azurecontainerapps.ts @@ -0,0 +1,522 @@ +import * as core from '@actions/core'; +import * as fs from 'fs'; +import * as path from 'path'; +import { ContainerAppHelper } from './src/ContainerAppHelper'; +import { ContainerRegistryHelper } from './src/ContainerRegistryHelper'; +import { TelemetryHelper } from './src/TelemetryHelper'; +import { Utility } from './src/Utility'; + +const util = new Utility(); + +export class azurecontainerapps { + + public static async runMain(): Promise { + let disableTelemetry = core.getInput('disableTelemetry').toLowerCase() === 'true'; + this.initializeHelpers(disableTelemetry); + + try { + // Validate that the arguments provided can be used for one of the supported scenarios + this.validateSupportedScenarioArguments(); + + // Set up the Azure CLI to be used for this task + this.setupAzureCli(); + + // Set up the resources required to deploy a Container App + await this.setupResources(); + + // If an Azure Container Registry name was provided, try to authenticate against it + if (!util.isNullOrEmpty(this.acrName)) { + await this.authenticateAzureContainerRegistryAsync(); + } + + // If the application source was provided, build a runnable application image from it + if (!util.isNullOrEmpty(this.appSourcePath)) { + await this.buildAndPushImageAsync(); + } + + // If no application source was provided, set up the scenario for deploying an existing image + if (util.isNullOrEmpty(this.appSourcePath)) { + this.setupExistingImageScenario(); + } + + // If no YAML configuration file was provided, set up the Container App properties + if (util.isNullOrEmpty(this.yamlConfigPath)) { + this.setupContainerAppProperties(); + } + + // Create/update the Container App + await this.createOrUpdateContainerApp(); + + // If telemetry is enabled, log that the task completed successfully + this.telemetryHelper.setSuccessfulResult(); + } catch (err) { + core.setFailed(err.message); + this.telemetryHelper.setFailedResult(err.message); + } finally { + // Logout of Azure if logged in during this task session + // this.authHelper.logoutAzure(); + + // If telemetry is enabled, will log metadata for this task run + await this.telemetryHelper.sendLogs(); + } + } + + // Azure DevOps build properties + private static buildId: string = process.env.GITHUB_RUN_ID; + private static buildNumber = process.env.GITHUB_RUN_NUMBER; + + // Supported scenario properties + private static appSourcePath: string; + private static acrName: string; + private static imageToDeploy: string; + private static yamlConfigPath: string; + + // Resource properties + private static containerAppName: string; + private static containerAppExists: boolean; + private static location: string; + private static resourceGroup: string; + private static containerAppEnvironment: string; + private static ingressEnabled: boolean; + + // ACR properties + private static acrUsername: string; + private static acrPassword: string; + + // Command line arguments + private static commandLineArgs: string[]; + + // Helper properties + private static telemetryHelper: TelemetryHelper; + //private static authHelper: AzureAuthenticationHelper; + private static appHelper: ContainerAppHelper; + private static registryHelper: ContainerRegistryHelper; + + // Miscellaneous properties + private static imageToBuild: string; + private static runtimeStack: string; + private static ingress: string; + private static targetPort: string; + private static shouldUseUpdateCommand: boolean; + + /** + * Initializes the helpers used by this task. + * @param disableTelemetry - Whether or not to disable telemetry for this task. + */ + private static initializeHelpers(disableTelemetry: boolean) { + // Set up TelemetryHelper for managing telemetry calls + this.telemetryHelper = new TelemetryHelper(disableTelemetry); + + // Set up AzureAuthenticationHelper for managing logging in and out of Azure CLI using provided service connection + // this.authHelper = new AzureAuthenticationHelper(); + + // Set up ContainerAppHelper for managing calls around the Container App + this.appHelper = new ContainerAppHelper(disableTelemetry); + + // Set up ContainerRegistryHelper for managing calls around ACR + this.registryHelper = new ContainerRegistryHelper(); + } + + /** + * Validates the arguments provided to the task for supported scenarios. + * @throws Error if a valid combination of the support scenario arguments is not provided. + */ + private static validateSupportedScenarioArguments() { + + // Get the path to the application source to build and run, if provided + this.appSourcePath = core.getInput('appSourcePath', {required: false}); + + // Get the name of the ACR instance to push images to, if provided + this.acrName = core.getInput('acrName', {required: false}); + + // Get the previously built image to deploy, if provided + this.imageToDeploy = core.getInput('imageToDeploy', {required: false}); + + // Get the YAML configuration file, if provided + this.yamlConfigPath = core.getInput('yamlConfigPath', {required: false}); + + // Ensure that acrName is also provided if appSourcePath is provided + if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { + core.error(`The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`); + throw Error(`The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`); + } + + // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided + if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { + core.error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); + } + } + + /** + * Sets up the Azure CLI to be used for this task by logging in to Azure with the provided service connection and + * setting the Azure CLI to dynamically install missing extensions. + */ + private static async setupAzureCli() { + // Set the Azure CLI to dynamically install missing extensions + await util.setAzureCliDynamicInstall(); + } + + /** + * Sets up the resources required to deploy a Container App. This includes the following: + * - Getting or generating the Container App name + * - Getting or discovering the location to deploy resources to + * - Getting or creating the resource group + * - Getting or creating the Container App Environment + */ + private static async setupResources() { + // Get the Container App name if it was provided, or generate it from build variables + this.containerAppName = this.getContainerAppName(); + + // Get the location to deploy resources to, if provided, or use the default location + this.location = await this.getLocation(); + + // Get the resource group to deploy to if it was provided, or generate it from the Container App name + this.resourceGroup = await this.getOrCreateResourceGroup(this.containerAppName, this.location); + + // Determine if the Container App currently exists + this.containerAppExists = await this.appHelper.doesContainerAppExist(this.containerAppName, this.resourceGroup); + + // If the Container App doesn't exist, get/create the Container App Environment to use for the Container App + if (!this.containerAppExists) { + this.containerAppEnvironment = await this.getOrCreateContainerAppEnvironment(this.containerAppName, this.resourceGroup, this.location); + } + } + + /** + * Gets the name of the Container App to use for the task. If the 'containerAppName' argument is not provided, + * then a default name will be generated in the form 'ado-task-app--'. + * @returns The name of the Container App to use for the task. + */ + private static getContainerAppName(): string { + let containerAppName: string = core.getInput('containerAppName', {required: false}); + if (util.isNullOrEmpty(containerAppName)) { + containerAppName = `app-${this.buildId}-${this.buildNumber}`; + + // Replace all '.' characters with '-' characters in the Container App name + containerAppName = containerAppName.replace(/\./gi, "-"); + core.info(`Default Container App name: ${containerAppName}`); + } + + return containerAppName; + } + + /** + * Gets the location to deploy resources to. If the 'location' argument is not provided, then the default location + * for the Container App service will be used. + * @returns The location to deploy resources to. + */ + private static async getLocation(): Promise { + // Set deployment location, if provided + let location: string = core.getInput('location', {required: false}); + + // If no location was provided, use the default location for the Container App service + if (util.isNullOrEmpty(location)) { + location = await this.appHelper.getDefaultContainerAppLocation(); + } + + return location; + } + + /** + * Gets the name of the resource group to use for the task. If the 'resourceGroup' argument is not provided, + * then a default name will be generated in the form '-rg'. If the generated resource group does + * not exist, it will be created. + * @param containerAppName - The name of the Container App to use for the task. + * @param location - The location to deploy resources to. + * @returns The name of the resource group to use for the task. + */ + private static async getOrCreateResourceGroup(containerAppName: string, location: string): Promise { + // Get the resource group to deploy to if it was provided, or generate it from the Container App name + let resourceGroup: string = core.getInput('resourceGroup', {required: false}); + if (util.isNullOrEmpty(resourceGroup)) { + resourceGroup = `${containerAppName}-rg`; + core.info(`Default resource group name: ${resourceGroup}`); + + // Ensure that the resource group that the Container App will be created in exists + const resourceGroupExists = await this.appHelper.doesResourceGroupExist(resourceGroup); + if (!resourceGroupExists) { + await this.appHelper.createResourceGroup(resourceGroup, location); + } + } + + return resourceGroup; + } + + /** + * Gets the name of the Container App Environment to use for the task. If the 'containerAppEnvironment' argument + * is not provided, then the task will attempt to discover an existing Container App Environment in the resource + * group. If no existing Container App Environment is found, then a default name will be generated in the form + * '-env'. If the Container App Environment does not exist, it will be created. + * @param containerAppName - The name of the Container App to use for the task. + * @param resourceGroup - The name of the resource group to use for the task. + * @param location - The location to deploy resources to. + * @returns The name of the Container App Environment to use for the task. + */ + private static async getOrCreateContainerAppEnvironment( + containerAppName: string, + resourceGroup: string, + location: string): Promise { + // Get the Container App environment if it was provided + let containerAppEnvironment: string = core.getInput('containerAppEnvironment', {required: false}); + + // See if we can reuse an existing Container App environment found in the resource group + if (util.isNullOrEmpty(containerAppEnvironment)) { + const existingContainerAppEnvironment: string = await this.appHelper.getExistingContainerAppEnvironment(resourceGroup); + if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { + core.info(`Existing Container App environment found in resource group: ${existingContainerAppEnvironment}`); + return existingContainerAppEnvironment + } + } + + // Generate the Container App environment name if it was not provided + if (util.isNullOrEmpty(containerAppEnvironment)) { + containerAppEnvironment = `${containerAppName}-env`; + core.info(`Default Container App environment name: ${containerAppEnvironment}`); + } + + // Determine if the Container App environment currently exists and create one if it doesn't + const containerAppEnvironmentExists: boolean = await this.appHelper.doesContainerAppEnvironmentExist(containerAppEnvironment, resourceGroup); + if (!containerAppEnvironmentExists) { + await this.appHelper.createContainerAppEnvironment(containerAppEnvironment, resourceGroup, location); + } + + return containerAppEnvironment; + } + + /** + * Authenticates calls to the provided Azure Container Registry. + */ + private static async authenticateAzureContainerRegistryAsync() { + this.acrUsername = core.getInput('acrUsername', {required: false}); + this.acrPassword = core.getInput('acrPassword', {required: false}); + + // Login to ACR if credentials were provided + if (!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword)) { + core.info(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); + await this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword); + } else { + core.info(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); + await this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName); + } + } + + /** + * Sets up the scenario where an existing image is used for the Container App. + */ + private static setupExistingImageScenario() { + // If telemetry is enabled, log that the previously built image scenario was targeted for this task + this.telemetryHelper.setImageScenario(); + } + + /** + * Builds a runnable application image using a Dockerfile or the builder and pushes it to ACR. + */ + private static async buildAndPushImageAsync() { + // Get the name of the image to build if it was provided, or generate it from build variables + this.imageToBuild = core.getInput('imageToBuild', {required: false}); + if (util.isNullOrEmpty(this.imageToBuild)) { + this.imageToBuild = `${this.acrName}.azurecr.io/ado-task/container-app:${this.buildId}.${this.buildNumber}`; + core.info(`Default image to build: ${this.imageToBuild}`); + } + + // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' + if (util.isNullOrEmpty(this.imageToDeploy)) { + this.imageToDeploy = this.imageToBuild; + core.info(`Default image to deploy: ${this.imageToDeploy}`); + } + + // Get Dockerfile to build, if provided, or check if one exists at the root of the provided application + let dockerfilePath: string = core.getInput('dockerfilePath', {required: false}); + if (util.isNullOrEmpty(dockerfilePath)) { + core.info(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); + const rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); + if (fs.existsSync(rootDockerfilePath)) { + core.info(`Dockerfile found at root of application source.`) + dockerfilePath = rootDockerfilePath; + } else { + // No Dockerfile found or provided, build the image using the builder + await this.buildImageFromBuilderAsync(this.appSourcePath, this.imageToBuild); + } + } else { + dockerfilePath = path.join(this.appSourcePath, dockerfilePath); + } + + if (!util.isNullOrEmpty(dockerfilePath)) { + // Build the image from the provided/discovered Dockerfile + await this.builderImageFromDockerfile(this.appSourcePath, dockerfilePath, this.imageToBuild); + } + + // Push the image to ACR + await this.registryHelper.pushImageToAcr(this.imageToBuild); + } + + /** + * Builds a runnable application image using the builder. + * @param appSourcePath - The path to the application source code. + * @param imageToBuild - The name of the image to build. + */ + private static async buildImageFromBuilderAsync(appSourcePath: string, imageToBuild: string) { + // Install the pack CLI + await this.appHelper.installPackCliAsync(); + core.info(`Successfully installed the pack CLI.`) + + // Get the runtime stack if provided, or determine it using Oryx + this.runtimeStack = core.getInput('runtimeStack', {required: false}); + if (util.isNullOrEmpty(this.runtimeStack)) { + this.runtimeStack = await this.appHelper.determineRuntimeStackAsync(appSourcePath); + core.info(`Runtime stack determined to be: ${this.runtimeStack}`); + } + + core.info(`Building image "${imageToBuild}" using the Oryx++ Builder`); + + // Set the Oryx++ Builder as the default builder locally + await this.appHelper.setDefaultBuilder(); + + // Create a runnable application image + await this.appHelper.createRunnableAppImage(imageToBuild, appSourcePath, this.runtimeStack); + + // If telemetry is enabled, log that the builder scenario was targeted for this task + this.telemetryHelper.setBuilderScenario(); + } + + /** + * Builds a runnable application image using a provided or discovered Dockerfile. + * @param appSourcePath - The path to the application source code. + * @param dockerfilePath - The path to the Dockerfile to build. + * @param imageToBuild - The name of the image to build. + */ + private static async builderImageFromDockerfile(appSourcePath: string, dockerfilePath: string, imageToBuild: string) { + core.info(`Building image "${imageToBuild}" using the provided Dockerfile`); + await this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath); + + // If telemetry is enabled, log that the Dockerfile scenario was targeted for this task + this.telemetryHelper.setDockerfileScenario(); + } + + /** + * Sets up the Container App properties that will be passed through to the Azure CLI when a YAML configuration + * file is not provided. + */ + private static setupContainerAppProperties() { + this.commandLineArgs = []; + + // Get the ingress inputs + this.ingress = core.getInput('ingress', {required: false}); + this.targetPort = core.getInput('targetPort', {required: false}); + + // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, + // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. + this.shouldUseUpdateCommand = this.containerAppExists && + util.isNullOrEmpty(this.targetPort) && + (util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); + + // Pass the ACR credentials when creating a Container App or updating a Container App via the 'up' command + if (!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword) && + (!this.containerAppExists || (this.containerAppExists && !this.shouldUseUpdateCommand))) { + this.commandLineArgs.push( + `--registry-server ${this.acrName}.azurecr.io`, + `--registry-username ${this.acrUsername}`, + `--registry-password ${this.acrPassword}`); + } + + // Determine default values only for the 'create' scenario to avoid overriding existing values for the 'update' scenario + if (!this.containerAppExists) { + this.ingressEnabled = true; + + // Set the ingress value to 'external' if it was not provided + if (util.isNullOrEmpty(this.ingress)) { + this.ingress = 'external'; + core.info(`Default ingress value: ${this.ingress}`); + } + + // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' + if (this.ingress == 'disabled') { + this.ingressEnabled = false; + core.info(`Ingress is disabled for this Container App.`); + } + + // Handle setup for ingress values when enabled + if (this.ingressEnabled) { + // Get the target port if provided, or determine it based on the application type + this.targetPort = core.getInput('targetPort', {required: false}); + if (util.isNullOrEmpty(this.targetPort)) { + if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { + this.targetPort = '80'; + } else { + this.targetPort = '8080'; + } + + core.info(`Default target port: ${this.targetPort}`); + } + + // Set the target port to 80 if it was not provided or determined + if (util.isNullOrEmpty(this.targetPort)) { + this.targetPort = '80'; + core.info(`Default target port: ${this.targetPort}`); + } + + // Add the ingress value and target port to the optional arguments array + // Note: this step should be skipped if we're updating an existing Container App (ingress is enabled via a separate command) + this.commandLineArgs.push(`--ingress ${this.ingress}`); + this.commandLineArgs.push(`--target-port ${this.targetPort}`); + } + } + + const environmentVariables: string = core.getInput('environmentVariables', {required: false}); + + // Add user-specified environment variables + if (!util.isNullOrEmpty(environmentVariables)) { + // The --replace-env-vars flag is only used for the 'update' command, + // otherwise --env-vars is used for 'create' and 'up' + if (this.shouldUseUpdateCommand) { + this.commandLineArgs.push(`--replace-env-vars ${environmentVariables}`); + } else { + this.commandLineArgs.push(`--env-vars ${environmentVariables}`); + } + } + } + + /** + * Creates or updates the Container App. + */ + private static async createOrUpdateContainerApp() { + if (!this.containerAppExists) { + if (!util.isNullOrEmpty(this.yamlConfigPath)) { + // Create the Container App from the YAML configuration file + await this.appHelper.createContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath); + } else { + // Create the Container App from command line arguments + await this.appHelper.createContainerApp(this.containerAppName, this.resourceGroup, this.containerAppEnvironment, this.imageToDeploy, this.commandLineArgs); + } + + return; + } + + if (!util.isNullOrEmpty(this.yamlConfigPath)) { + // Update the Container App from the YAML configuration file + await this.appHelper.updateContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath); + + return; + } + + if (this.shouldUseUpdateCommand) { + // Update the ACR details on the existing Container App, if provided as an input + if (!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword)) { + await this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.acrName, this.acrUsername, this.acrPassword); + } + + // Update the Container App using the 'update' command + await this.appHelper.updateContainerApp(this.containerAppName, this.resourceGroup, this.imageToDeploy, this.commandLineArgs); + } else { + // Update the Container App using the 'up' command + await this.appHelper.updateContainerAppWithUp(this.containerAppName, this.resourceGroup, this.imageToDeploy, this.commandLineArgs, this.ingress, this.targetPort); + } + + // Disable ingress on the existing Container App, if provided as an input + if (this.ingress == 'disabled') { + await this.appHelper.disableContainerAppIngress(this.containerAppName, this.resourceGroup); + } + } +} + +azurecontainerapps.runMain(); \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 00000000..6c495437 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,6061 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 3238: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.azurecontainerapps = void 0; +var core = __nccwpck_require__(3195); +var fs = __nccwpck_require__(7147); +var path = __nccwpck_require__(1017); +var ContainerAppHelper_1 = __nccwpck_require__(2929); +var ContainerRegistryHelper_1 = __nccwpck_require__(4769); +var TelemetryHelper_1 = __nccwpck_require__(7166); +var Utility_1 = __nccwpck_require__(2135); +var util = new Utility_1.Utility(); +var azurecontainerapps = /** @class */ (function () { + function azurecontainerapps() { + } + azurecontainerapps.runMain = function () { + return __awaiter(this, void 0, void 0, function () { + var disableTelemetry, err_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + disableTelemetry = core.getInput('disableTelemetry').toLowerCase() === 'true'; + this.initializeHelpers(disableTelemetry); + _a.label = 1; + case 1: + _a.trys.push([1, 8, 9, 11]); + // Validate that the arguments provided can be used for one of the supported scenarios + this.validateSupportedScenarioArguments(); + // Set up the Azure CLI to be used for this task + this.setupAzureCli(); + // Set up the resources required to deploy a Container App + return [4 /*yield*/, this.setupResources()]; + case 2: + // Set up the resources required to deploy a Container App + _a.sent(); + if (!!util.isNullOrEmpty(this.acrName)) return [3 /*break*/, 4]; + return [4 /*yield*/, this.authenticateAzureContainerRegistryAsync()]; + case 3: + _a.sent(); + _a.label = 4; + case 4: + if (!!util.isNullOrEmpty(this.appSourcePath)) return [3 /*break*/, 6]; + return [4 /*yield*/, this.buildAndPushImageAsync()]; + case 5: + _a.sent(); + _a.label = 6; + case 6: + // If no application source was provided, set up the scenario for deploying an existing image + if (util.isNullOrEmpty(this.appSourcePath)) { + this.setupExistingImageScenario(); + } + // If no YAML configuration file was provided, set up the Container App properties + if (util.isNullOrEmpty(this.yamlConfigPath)) { + this.setupContainerAppProperties(); + } + // Create/update the Container App + return [4 /*yield*/, this.createOrUpdateContainerApp()]; + case 7: + // Create/update the Container App + _a.sent(); + // If telemetry is enabled, log that the task completed successfully + this.telemetryHelper.setSuccessfulResult(); + return [3 /*break*/, 11]; + case 8: + err_1 = _a.sent(); + core.setFailed(err_1.message); + this.telemetryHelper.setFailedResult(err_1.message); + return [3 /*break*/, 11]; + case 9: + // Logout of Azure if logged in during this task session + // this.authHelper.logoutAzure(); + // If telemetry is enabled, will log metadata for this task run + return [4 /*yield*/, this.telemetryHelper.sendLogs()]; + case 10: + // Logout of Azure if logged in during this task session + // this.authHelper.logoutAzure(); + // If telemetry is enabled, will log metadata for this task run + _a.sent(); + return [7 /*endfinally*/]; + case 11: return [2 /*return*/]; + } + }); + }); + }; + /** + * Initializes the helpers used by this task. + * @param disableTelemetry - Whether or not to disable telemetry for this task. + */ + azurecontainerapps.initializeHelpers = function (disableTelemetry) { + // Set up TelemetryHelper for managing telemetry calls + this.telemetryHelper = new TelemetryHelper_1.TelemetryHelper(disableTelemetry); + // Set up AzureAuthenticationHelper for managing logging in and out of Azure CLI using provided service connection + // this.authHelper = new AzureAuthenticationHelper(); + // Set up ContainerAppHelper for managing calls around the Container App + this.appHelper = new ContainerAppHelper_1.ContainerAppHelper(disableTelemetry); + // Set up ContainerRegistryHelper for managing calls around ACR + this.registryHelper = new ContainerRegistryHelper_1.ContainerRegistryHelper(); + }; + /** + * Validates the arguments provided to the task for supported scenarios. + * @throws Error if a valid combination of the support scenario arguments is not provided. + */ + azurecontainerapps.validateSupportedScenarioArguments = function () { + // Get the path to the application source to build and run, if provided + this.appSourcePath = core.getInput('appSourcePath', { required: false }); + // Get the name of the ACR instance to push images to, if provided + this.acrName = core.getInput('acrName', { required: false }); + // Get the previously built image to deploy, if provided + this.imageToDeploy = core.getInput('imageToDeploy', { required: false }); + // Get the YAML configuration file, if provided + this.yamlConfigPath = core.getInput('yamlConfigPath', { required: false }); + // Ensure that acrName is also provided if appSourcePath is provided + if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { + core.error("The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."); + throw Error("The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."); + } + // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided + if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { + core.error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); + } + }; + /** + * Sets up the Azure CLI to be used for this task by logging in to Azure with the provided service connection and + * setting the Azure CLI to dynamically install missing extensions. + */ + azurecontainerapps.setupAzureCli = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + // Set the Azure CLI to dynamically install missing extensions + return [4 /*yield*/, util.setAzureCliDynamicInstall()]; + case 1: + // Set the Azure CLI to dynamically install missing extensions + _a.sent(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Sets up the resources required to deploy a Container App. This includes the following: + * - Getting or generating the Container App name + * - Getting or discovering the location to deploy resources to + * - Getting or creating the resource group + * - Getting or creating the Container App Environment + */ + azurecontainerapps.setupResources = function () { + return __awaiter(this, void 0, void 0, function () { + var _a, _b, _c, _d; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + // Get the Container App name if it was provided, or generate it from build variables + this.containerAppName = this.getContainerAppName(); + // Get the location to deploy resources to, if provided, or use the default location + _a = this; + return [4 /*yield*/, this.getLocation()]; + case 1: + // Get the location to deploy resources to, if provided, or use the default location + _a.location = _e.sent(); + // Get the resource group to deploy to if it was provided, or generate it from the Container App name + _b = this; + return [4 /*yield*/, this.getOrCreateResourceGroup(this.containerAppName, this.location)]; + case 2: + // Get the resource group to deploy to if it was provided, or generate it from the Container App name + _b.resourceGroup = _e.sent(); + // Determine if the Container App currently exists + _c = this; + return [4 /*yield*/, this.appHelper.doesContainerAppExist(this.containerAppName, this.resourceGroup)]; + case 3: + // Determine if the Container App currently exists + _c.containerAppExists = _e.sent(); + if (!!this.containerAppExists) return [3 /*break*/, 5]; + _d = this; + return [4 /*yield*/, this.getOrCreateContainerAppEnvironment(this.containerAppName, this.resourceGroup, this.location)]; + case 4: + _d.containerAppEnvironment = _e.sent(); + _e.label = 5; + case 5: return [2 /*return*/]; + } + }); + }); + }; + /** + * Gets the name of the Container App to use for the task. If the 'containerAppName' argument is not provided, + * then a default name will be generated in the form 'ado-task-app--'. + * @returns The name of the Container App to use for the task. + */ + azurecontainerapps.getContainerAppName = function () { + var containerAppName = core.getInput('containerAppName', { required: false }); + if (util.isNullOrEmpty(containerAppName)) { + containerAppName = "app-" + this.buildId + "-" + this.buildNumber; + // Replace all '.' characters with '-' characters in the Container App name + containerAppName = containerAppName.replace(/\./gi, "-"); + core.info("Default Container App name: " + containerAppName); + } + return containerAppName; + }; + /** + * Gets the location to deploy resources to. If the 'location' argument is not provided, then the default location + * for the Container App service will be used. + * @returns The location to deploy resources to. + */ + azurecontainerapps.getLocation = function () { + return __awaiter(this, void 0, void 0, function () { + var location; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + location = core.getInput('location', { required: false }); + if (!util.isNullOrEmpty(location)) return [3 /*break*/, 2]; + return [4 /*yield*/, this.appHelper.getDefaultContainerAppLocation()]; + case 1: + location = _a.sent(); + _a.label = 2; + case 2: return [2 /*return*/, location]; + } + }); + }); + }; + /** + * Gets the name of the resource group to use for the task. If the 'resourceGroup' argument is not provided, + * then a default name will be generated in the form '-rg'. If the generated resource group does + * not exist, it will be created. + * @param containerAppName - The name of the Container App to use for the task. + * @param location - The location to deploy resources to. + * @returns The name of the resource group to use for the task. + */ + azurecontainerapps.getOrCreateResourceGroup = function (containerAppName, location) { + return __awaiter(this, void 0, void 0, function () { + var resourceGroup, resourceGroupExists; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + resourceGroup = core.getInput('resourceGroup', { required: false }); + if (!util.isNullOrEmpty(resourceGroup)) return [3 /*break*/, 3]; + resourceGroup = containerAppName + "-rg"; + core.info("Default resource group name: " + resourceGroup); + return [4 /*yield*/, this.appHelper.doesResourceGroupExist(resourceGroup)]; + case 1: + resourceGroupExists = _a.sent(); + if (!!resourceGroupExists) return [3 /*break*/, 3]; + return [4 /*yield*/, this.appHelper.createResourceGroup(resourceGroup, location)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: return [2 /*return*/, resourceGroup]; + } + }); + }); + }; + /** + * Gets the name of the Container App Environment to use for the task. If the 'containerAppEnvironment' argument + * is not provided, then the task will attempt to discover an existing Container App Environment in the resource + * group. If no existing Container App Environment is found, then a default name will be generated in the form + * '-env'. If the Container App Environment does not exist, it will be created. + * @param containerAppName - The name of the Container App to use for the task. + * @param resourceGroup - The name of the resource group to use for the task. + * @param location - The location to deploy resources to. + * @returns The name of the Container App Environment to use for the task. + */ + azurecontainerapps.getOrCreateContainerAppEnvironment = function (containerAppName, resourceGroup, location) { + return __awaiter(this, void 0, void 0, function () { + var containerAppEnvironment, existingContainerAppEnvironment, containerAppEnvironmentExists; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + containerAppEnvironment = core.getInput('containerAppEnvironment', { required: false }); + if (!util.isNullOrEmpty(containerAppEnvironment)) return [3 /*break*/, 2]; + return [4 /*yield*/, this.appHelper.getExistingContainerAppEnvironment(resourceGroup)]; + case 1: + existingContainerAppEnvironment = _a.sent(); + if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { + core.info("Existing Container App environment found in resource group: " + existingContainerAppEnvironment); + return [2 /*return*/, existingContainerAppEnvironment]; + } + _a.label = 2; + case 2: + // Generate the Container App environment name if it was not provided + if (util.isNullOrEmpty(containerAppEnvironment)) { + containerAppEnvironment = containerAppName + "-env"; + core.info("Default Container App environment name: " + containerAppEnvironment); + } + return [4 /*yield*/, this.appHelper.doesContainerAppEnvironmentExist(containerAppEnvironment, resourceGroup)]; + case 3: + containerAppEnvironmentExists = _a.sent(); + if (!!containerAppEnvironmentExists) return [3 /*break*/, 5]; + return [4 /*yield*/, this.appHelper.createContainerAppEnvironment(containerAppEnvironment, resourceGroup, location)]; + case 4: + _a.sent(); + _a.label = 5; + case 5: return [2 /*return*/, containerAppEnvironment]; + } + }); + }); + }; + /** + * Authenticates calls to the provided Azure Container Registry. + */ + azurecontainerapps.authenticateAzureContainerRegistryAsync = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.acrUsername = core.getInput('acrUsername', { required: false }); + this.acrPassword = core.getInput('acrPassword', { required: false }); + if (!(!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 2]; + core.info("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); + return [4 /*yield*/, this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword)]; + case 1: + _a.sent(); + return [3 /*break*/, 4]; + case 2: + core.info("No ACR credentials provided; attempting to log in to ACR instance \"" + this.acrName + "\" with access token"); + return [4 /*yield*/, this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName)]; + case 3: + _a.sent(); + _a.label = 4; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Sets up the scenario where an existing image is used for the Container App. + */ + azurecontainerapps.setupExistingImageScenario = function () { + // If telemetry is enabled, log that the previously built image scenario was targeted for this task + this.telemetryHelper.setImageScenario(); + }; + /** + * Builds a runnable application image using a Dockerfile or the builder and pushes it to ACR. + */ + azurecontainerapps.buildAndPushImageAsync = function () { + return __awaiter(this, void 0, void 0, function () { + var dockerfilePath, rootDockerfilePath; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + // Get the name of the image to build if it was provided, or generate it from build variables + this.imageToBuild = core.getInput('imageToBuild', { required: false }); + if (util.isNullOrEmpty(this.imageToBuild)) { + this.imageToBuild = this.acrName + ".azurecr.io/ado-task/container-app:" + this.buildId + "." + this.buildNumber; + core.info("Default image to build: " + this.imageToBuild); + } + // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' + if (util.isNullOrEmpty(this.imageToDeploy)) { + this.imageToDeploy = this.imageToBuild; + core.info("Default image to deploy: " + this.imageToDeploy); + } + dockerfilePath = core.getInput('dockerfilePath', { required: false }); + if (!util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 4]; + core.info("No Dockerfile path provided; checking for Dockerfile at root of application source."); + rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); + if (!fs.existsSync(rootDockerfilePath)) return [3 /*break*/, 1]; + core.info("Dockerfile found at root of application source."); + dockerfilePath = rootDockerfilePath; + return [3 /*break*/, 3]; + case 1: + // No Dockerfile found or provided, build the image using the builder + return [4 /*yield*/, this.buildImageFromBuilderAsync(this.appSourcePath, this.imageToBuild)]; + case 2: + // No Dockerfile found or provided, build the image using the builder + _a.sent(); + _a.label = 3; + case 3: return [3 /*break*/, 5]; + case 4: + dockerfilePath = path.join(this.appSourcePath, dockerfilePath); + _a.label = 5; + case 5: + if (!!util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 7]; + // Build the image from the provided/discovered Dockerfile + return [4 /*yield*/, this.builderImageFromDockerfile(this.appSourcePath, dockerfilePath, this.imageToBuild)]; + case 6: + // Build the image from the provided/discovered Dockerfile + _a.sent(); + _a.label = 7; + case 7: + // Push the image to ACR + return [4 /*yield*/, this.registryHelper.pushImageToAcr(this.imageToBuild)]; + case 8: + // Push the image to ACR + _a.sent(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Builds a runnable application image using the builder. + * @param appSourcePath - The path to the application source code. + * @param imageToBuild - The name of the image to build. + */ + azurecontainerapps.buildImageFromBuilderAsync = function (appSourcePath, imageToBuild) { + return __awaiter(this, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + // Install the pack CLI + return [4 /*yield*/, this.appHelper.installPackCliAsync()]; + case 1: + // Install the pack CLI + _b.sent(); + core.info("Successfully installed the pack CLI."); + // Get the runtime stack if provided, or determine it using Oryx + this.runtimeStack = core.getInput('runtimeStack', { required: false }); + if (!util.isNullOrEmpty(this.runtimeStack)) return [3 /*break*/, 3]; + _a = this; + return [4 /*yield*/, this.appHelper.determineRuntimeStackAsync(appSourcePath)]; + case 2: + _a.runtimeStack = _b.sent(); + core.info("Runtime stack determined to be: " + this.runtimeStack); + _b.label = 3; + case 3: + core.info("Building image \"" + imageToBuild + "\" using the Oryx++ Builder"); + // Set the Oryx++ Builder as the default builder locally + return [4 /*yield*/, this.appHelper.setDefaultBuilder()]; + case 4: + // Set the Oryx++ Builder as the default builder locally + _b.sent(); + // Create a runnable application image + return [4 /*yield*/, this.appHelper.createRunnableAppImage(imageToBuild, appSourcePath, this.runtimeStack)]; + case 5: + // Create a runnable application image + _b.sent(); + // If telemetry is enabled, log that the builder scenario was targeted for this task + this.telemetryHelper.setBuilderScenario(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Builds a runnable application image using a provided or discovered Dockerfile. + * @param appSourcePath - The path to the application source code. + * @param dockerfilePath - The path to the Dockerfile to build. + * @param imageToBuild - The name of the image to build. + */ + azurecontainerapps.builderImageFromDockerfile = function (appSourcePath, dockerfilePath, imageToBuild) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.info("Building image \"" + imageToBuild + "\" using the provided Dockerfile"); + return [4 /*yield*/, this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath)]; + case 1: + _a.sent(); + // If telemetry is enabled, log that the Dockerfile scenario was targeted for this task + this.telemetryHelper.setDockerfileScenario(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Sets up the Container App properties that will be passed through to the Azure CLI when a YAML configuration + * file is not provided. + */ + azurecontainerapps.setupContainerAppProperties = function () { + this.commandLineArgs = []; + // Get the ingress inputs + this.ingress = core.getInput('ingress', { required: false }); + this.targetPort = core.getInput('targetPort', { required: false }); + // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, + // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. + this.shouldUseUpdateCommand = this.containerAppExists && + util.isNullOrEmpty(this.targetPort) && + (util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); + // Pass the ACR credentials when creating a Container App or updating a Container App via the 'up' command + if (!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword) && + (!this.containerAppExists || (this.containerAppExists && !this.shouldUseUpdateCommand))) { + this.commandLineArgs.push("--registry-server " + this.acrName + ".azurecr.io", "--registry-username " + this.acrUsername, "--registry-password " + this.acrPassword); + } + // Determine default values only for the 'create' scenario to avoid overriding existing values for the 'update' scenario + if (!this.containerAppExists) { + this.ingressEnabled = true; + // Set the ingress value to 'external' if it was not provided + if (util.isNullOrEmpty(this.ingress)) { + this.ingress = 'external'; + core.info("Default ingress value: " + this.ingress); + } + // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' + if (this.ingress == 'disabled') { + this.ingressEnabled = false; + core.info("Ingress is disabled for this Container App."); + } + // Handle setup for ingress values when enabled + if (this.ingressEnabled) { + // Get the target port if provided, or determine it based on the application type + this.targetPort = core.getInput('targetPort', { required: false }); + if (util.isNullOrEmpty(this.targetPort)) { + if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { + this.targetPort = '80'; + } + else { + this.targetPort = '8080'; + } + core.info("Default target port: " + this.targetPort); + } + // Set the target port to 80 if it was not provided or determined + if (util.isNullOrEmpty(this.targetPort)) { + this.targetPort = '80'; + core.info("Default target port: " + this.targetPort); + } + // Add the ingress value and target port to the optional arguments array + // Note: this step should be skipped if we're updating an existing Container App (ingress is enabled via a separate command) + this.commandLineArgs.push("--ingress " + this.ingress); + this.commandLineArgs.push("--target-port " + this.targetPort); + } + } + var environmentVariables = core.getInput('environmentVariables', { required: false }); + // Add user-specified environment variables + if (!util.isNullOrEmpty(environmentVariables)) { + // The --replace-env-vars flag is only used for the 'update' command, + // otherwise --env-vars is used for 'create' and 'up' + if (this.shouldUseUpdateCommand) { + this.commandLineArgs.push("--replace-env-vars " + environmentVariables); + } + else { + this.commandLineArgs.push("--env-vars " + environmentVariables); + } + } + }; + /** + * Creates or updates the Container App. + */ + azurecontainerapps.createOrUpdateContainerApp = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!!this.containerAppExists) return [3 /*break*/, 5]; + if (!!util.isNullOrEmpty(this.yamlConfigPath)) return [3 /*break*/, 2]; + // Create the Container App from the YAML configuration file + return [4 /*yield*/, this.appHelper.createContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath)]; + case 1: + // Create the Container App from the YAML configuration file + _a.sent(); + return [3 /*break*/, 4]; + case 2: + // Create the Container App from command line arguments + return [4 /*yield*/, this.appHelper.createContainerApp(this.containerAppName, this.resourceGroup, this.containerAppEnvironment, this.imageToDeploy, this.commandLineArgs)]; + case 3: + // Create the Container App from command line arguments + _a.sent(); + _a.label = 4; + case 4: return [2 /*return*/]; + case 5: + if (!!util.isNullOrEmpty(this.yamlConfigPath)) return [3 /*break*/, 7]; + // Update the Container App from the YAML configuration file + return [4 /*yield*/, this.appHelper.updateContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath)]; + case 6: + // Update the Container App from the YAML configuration file + _a.sent(); + return [2 /*return*/]; + case 7: + if (!this.shouldUseUpdateCommand) return [3 /*break*/, 11]; + if (!(!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 9]; + return [4 /*yield*/, this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.acrName, this.acrUsername, this.acrPassword)]; + case 8: + _a.sent(); + _a.label = 9; + case 9: + // Update the Container App using the 'update' command + return [4 /*yield*/, this.appHelper.updateContainerApp(this.containerAppName, this.resourceGroup, this.imageToDeploy, this.commandLineArgs)]; + case 10: + // Update the Container App using the 'update' command + _a.sent(); + return [3 /*break*/, 13]; + case 11: + // Update the Container App using the 'up' command + return [4 /*yield*/, this.appHelper.updateContainerAppWithUp(this.containerAppName, this.resourceGroup, this.imageToDeploy, this.commandLineArgs, this.ingress, this.targetPort)]; + case 12: + // Update the Container App using the 'up' command + _a.sent(); + _a.label = 13; + case 13: + if (!(this.ingress == 'disabled')) return [3 /*break*/, 15]; + return [4 /*yield*/, this.appHelper.disableContainerAppIngress(this.containerAppName, this.resourceGroup)]; + case 14: + _a.sent(); + _a.label = 15; + case 15: return [2 /*return*/]; + } + }); + }); + }; + // Azure DevOps build properties + azurecontainerapps.buildId = process.env.GITHUB_RUN_ID; + azurecontainerapps.buildNumber = process.env.GITHUB_RUN_NUMBER; + return azurecontainerapps; +}()); +exports.azurecontainerapps = azurecontainerapps; +azurecontainerapps.runMain(); + + +/***/ }), + +/***/ 5688: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.issue = exports.issueCommand = void 0; +const os = __importStar(__nccwpck_require__(2037)); +const utils_1 = __nccwpck_require__(869); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 3195: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; +const command_1 = __nccwpck_require__(5688); +const file_command_1 = __nccwpck_require__(3930); +const utils_1 = __nccwpck_require__(869); +const os = __importStar(__nccwpck_require__(2037)); +const path = __importStar(__nccwpck_require__(1017)); +const oidc_utils_1 = __nccwpck_require__(1755); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = utils_1.toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); + } + command_1.issueCommand('set-env', { name }, convertedVal); +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + command_1.issueCommand('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + file_command_1.issueFileCommand('PATH', inputPath); + } + else { + command_1.issueCommand('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); +} +exports.getMultilineInput = getMultilineInput; +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +exports.getBooleanInput = getBooleanInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } + process.stdout.write(os.EOL); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + command_1.issue('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + command_1.issueCommand('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function error(message, properties = {}) { + command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds a warning issue + * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function warning(message, properties = {}) { + command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + command_1.issue('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + command_1.issue('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); +} +exports.getIDToken = getIDToken; +/** + * Summary exports + */ +var summary_1 = __nccwpck_require__(8606); +Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); +/** + * @deprecated use core.summary + */ +var summary_2 = __nccwpck_require__(8606); +Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); +/** + * Path exports + */ +var path_utils_1 = __nccwpck_require__(397); +Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); +Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); +Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 3930: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// For internal use, subject to change. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +const fs = __importStar(__nccwpck_require__(7147)); +const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5814); +const utils_1 = __nccwpck_require__(869); +function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { + encoding: 'utf8' + }); +} +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; +//# sourceMappingURL=file-command.js.map + +/***/ }), + +/***/ 1755: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OidcClient = void 0; +const http_client_1 = __nccwpck_require__(9780); +const auth_1 = __nccwpck_require__(8833); +const core_1 = __nccwpck_require__(3195); +class OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + core_1.debug(`ID token url is ${id_token_url}`); + const id_token = yield OidcClient.getCall(id_token_url); + core_1.setSecret(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +exports.OidcClient = OidcClient; +//# sourceMappingURL=oidc-utils.js.map + +/***/ }), + +/***/ 397: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; +const path = __importStar(__nccwpck_require__(1017)); +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +exports.toPosixPath = toPosixPath; +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +exports.toWin32Path = toWin32Path; +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +exports.toPlatformPath = toPlatformPath; +//# sourceMappingURL=path-utils.js.map + +/***/ }), + +/***/ 8606: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __nccwpck_require__(2037); +const fs_1 = __nccwpck_require__(7147); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +exports.markdownSummary = _summary; +exports.summary = _summary; +//# sourceMappingURL=summary.js.map + +/***/ }), + +/***/ 869: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toCommandProperties = exports.toCommandValue = void 0; +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 9714: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getExecOutput = exports.exec = void 0; +const string_decoder_1 = __nccwpck_require__(1576); +const tr = __importStar(__nccwpck_require__(5315)); +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code + */ +function exec(commandLine, args, options) { + return __awaiter(this, void 0, void 0, function* () { + const commandArgs = tr.argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + // Path to tool to execute should be first arg + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new tr.ToolRunner(toolPath, args, options); + return runner.exec(); + }); +} +exports.exec = exec; +/** + * Exec a command and get the output. + * Output will be streamed to the live console. + * Returns promise with the exit code and collected stdout and stderr + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code, stdout, and stderr + */ +function getExecOutput(commandLine, args, options) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + let stdout = ''; + let stderr = ''; + //Using string decoder covers the case where a mult-byte character is split + const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); + const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + //flush any remaining characters + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); +} +exports.getExecOutput = getExecOutput; +//# sourceMappingURL=exec.js.map + +/***/ }), + +/***/ 5315: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.argStringToArray = exports.ToolRunner = void 0; +const os = __importStar(__nccwpck_require__(2037)); +const events = __importStar(__nccwpck_require__(2361)); +const child = __importStar(__nccwpck_require__(2081)); +const path = __importStar(__nccwpck_require__(1017)); +const io = __importStar(__nccwpck_require__(9529)); +const ioUtil = __importStar(__nccwpck_require__(7821)); +const timers_1 = __nccwpck_require__(9512); +/* eslint-disable @typescript-eslint/unbound-method */ +const IS_WINDOWS = process.platform === 'win32'; +/* + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. + */ +class ToolRunner extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; + } + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } + } + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool + if (IS_WINDOWS) { + // Windows + cmd file + if (this._isCmdFile()) { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows + verbatim + else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows (regular) + else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } + } + } + else { + // OSX/Linux - this can likely be improved with some form of quoting. + // creating processes on Unix is fundamentally different than Windows. + // on Unix, execvp() takes an arg array. + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + return cmd; + } + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n = s.indexOf(os.EOL); + while (n > -1) { + const line = s.substring(0, n); + onLine(line); + // the rest of the string ... + s = s.substring(n + os.EOL.length); + n = s.indexOf(os.EOL); + } + return s; + } + catch (err) { + // streaming lines to console is best effort. Don't fail a build. + this._debug(`error processing line. Failed with error ${err}`); + return ''; + } + } + _getSpawnFileName() { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + return process.env['COMSPEC'] || 'cmd.exe'; + } + } + return this.toolPath; + } + _getSpawnArgs(options) { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += ' '; + argline += options.windowsVerbatimArguments + ? a + : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; + } + } + return this.args; + } + _endsWith(str, end) { + return str.endsWith(end); + } + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return (this._endsWith(upperToolPath, '.CMD') || + this._endsWith(upperToolPath, '.BAT')); + } + _windowsQuoteCmdArg(arg) { + // for .exe, apply the normal quoting rules that libuv applies + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + // otherwise apply quoting rules specific to the cmd.exe command line parser. + // the libuv rules are generic and are not designed specifically for cmd.exe + // command line parser. + // + // for a detailed description of the cmd.exe command line parser, refer to + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 + // need quotes for empty arg + if (!arg) { + return '""'; + } + // determine whether the arg needs to be quoted + const cmdSpecialChars = [ + ' ', + '\t', + '&', + '(', + ')', + '[', + ']', + '{', + '}', + '^', + '=', + ';', + '!', + "'", + '+', + ',', + '`', + '~', + '|', + '<', + '>', + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some(x => x === char)) { + needsQuotes = true; + break; + } + } + // short-circuit if quotes not needed + if (!needsQuotes) { + return arg; + } + // the following quoting rules are very similar to the rules that by libuv applies. + // + // 1) wrap the string in quotes + // + // 2) double-up quotes - i.e. " => "" + // + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately + // doesn't work well with a cmd.exe command line. + // + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. + // for example, the command line: + // foo.exe "myarg:""my val""" + // is parsed by a .NET console app into an arg array: + // [ "myarg:\"my val\"" ] + // which is the same end result when applying libuv quoting rules. although the actual + // command line from libuv quoting rules would look like: + // foo.exe "myarg:\"my val\"" + // + // 3) double-up slashes that precede a quote, + // e.g. hello \world => "hello \world" + // hello\"world => "hello\\""world" + // hello\\"world => "hello\\\\""world" + // hello world\ => "hello world\\" + // + // technically this is not required for a cmd.exe command line, or the batch argument parser. + // the reasons for including this as a .cmd quoting rule are: + // + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. + // + // b) it's what we've been doing previously (by deferring to node default behavior) and we + // haven't heard any complaints about that aspect. + // + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be + // escaped when used on the command line directly - even though within a .cmd file % can be escaped + // by using %%. + // + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. + // + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args + // to an external program. + // + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. + // % can be escaped within a .cmd file. + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; // double the slash + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; // double the quote + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _uvQuoteCmdArg(arg) { + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments + // is used. + // + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), + // pasting copyright notice from Node within this function: + // + // Copyright Joyent, Inc. and other Node contributors. All rights reserved. + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to + // deal in the Software without restriction, including without limitation the + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + // sell copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + // IN THE SOFTWARE. + if (!arg) { + // Need double quotation for empty argument + return '""'; + } + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { + // No quotation needed + return arg; + } + if (!arg.includes('"') && !arg.includes('\\')) { + // No embedded double quotes or backslashes, so I can just wrap + // quote marks around the whole thing. + return `"${arg}"`; + } + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" - note the comment in libuv actually reads "hello world\" + // but it appears the comment is wrong, it should be "hello world\\" + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '\\'; + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 10000 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result['windowsVerbatimArguments'] = + options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; + } + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return __awaiter(this, void 0, void 0, function* () { + // root the tool path if it is unrooted and contains relative pathing + if (!ioUtil.isRooted(this.toolPath) && + (this.toolPath.includes('/') || + (IS_WINDOWS && this.toolPath.includes('\\')))) { + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted + this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + // if the tool is only a file name, then resolve it from the PATH + // otherwise verify it exists (add extension on Windows if necessary) + this.toolPath = yield io.which(this.toolPath, true); + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug('arguments:'); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ''; + if (cp.stdout) { + cp.stdout.on('data', (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ''; + if (cp.stderr) { + cp.stderr.on('data', (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && + optionsNonNull.errStream && + optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr + ? optionsNonNull.errStream + : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on('error', (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on('exit', (code) => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on('close', (code) => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on('done', (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit('stdline', stdbuffer); + } + if (errbuffer.length > 0) { + this.emit('errline', errbuffer); + } + cp.removeAllListeners(); + if (error) { + reject(error); + } + else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error('child process missing stdin'); + } + cp.stdin.end(this.options.input); + } + })); + }); + } +} +exports.ToolRunner = ToolRunner; +/** + * Convert an arg string to an array of args. Handles escaping + * + * @param argString string of arguments + * @returns string[] array of arguments + */ +function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ''; + function append(c) { + // we only escape double quotes. + if (escaped && c !== '"') { + arg += '\\'; + } + arg += c; + escaped = false; + } + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } + else { + append(c); + } + continue; + } + if (c === '\\' && escaped) { + append(c); + continue; + } + if (c === '\\' && inQuotes) { + escaped = true; + continue; + } + if (c === ' ' && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ''; + } + continue; + } + append(c); + } + if (arg.length > 0) { + args.push(arg.trim()); + } + return args; +} +exports.argStringToArray = argStringToArray; +class ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; // tracks whether the process has exited and stdio is closed + this.processError = ''; + this.processExitCode = 0; + this.processExited = false; // tracks whether the process has exited + this.processStderr = false; // tracks whether stderr was written to + this.delay = 10000; // 10 seconds + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error('toolPath must not be empty'); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } + else if (this.processExited) { + this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit('debug', message); + } + _setResult() { + // determine whether there is an error + let error; + if (this.processExited) { + if (this.processError) { + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } + else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } + else if (this.processStderr && this.options.failOnStdErr) { + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + // clear the timeout + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit('done', error, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / + 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); + } +} +//# sourceMappingURL=toolrunner.js.map + +/***/ }), + +/***/ 8833: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BasicCredentialHandler = BasicCredentialHandler; +class BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BearerCredentialHandler = BearerCredentialHandler; +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; +//# sourceMappingURL=auth.js.map + +/***/ }), + +/***/ 9780: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; +const http = __importStar(__nccwpck_require__(3685)); +const https = __importStar(__nccwpck_require__(5687)); +const pm = __importStar(__nccwpck_require__(4492)); +const tunnel = __importStar(__nccwpck_require__(9041)); +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers = exports.Headers || (exports.Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } +} +exports.HttpClientError = HttpClientError; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } + readBodyBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + const chunks = []; + this.message.on('data', (chunk) => { + chunks.push(chunk); + }); + this.message.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + })); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (this._keepAlive && !useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if reusing agent across request and tunneling agent isn't assigned create a new agent + if (this._keepAlive && !agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + // if not using private agent and tunnel agent isn't setup then use global agent + if (!agent) { + agent = usingSsl ? https.globalAgent : http.globalAgent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +exports.HttpClient = HttpClient; +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 4492: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkBypass = exports.getProxyUrl = void 0; +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + try { + return new URL(proxyVar); + } + catch (_a) { + if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://')) + return new URL(`http://${proxyVar}`); + } + } + else { + return undefined; + } +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperNoProxyItem === '*' || + upperReqHosts.some(x => x === upperNoProxyItem || + x.endsWith(`.${upperNoProxyItem}`) || + (upperNoProxyItem.startsWith('.') && + x.endsWith(`${upperNoProxyItem}`)))) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; +function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return (hostLower === 'localhost' || + hostLower.startsWith('127.') || + hostLower.startsWith('[::1]') || + hostLower.startsWith('[0:0:0:0:0:0:0:1]')); +} +//# sourceMappingURL=proxy.js.map + +/***/ }), + +/***/ 7821: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; +const fs = __importStar(__nccwpck_require__(7147)); +const path = __importStar(__nccwpck_require__(1017)); +_a = fs.promises +// export const {open} = 'fs' +, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; +// export const {open} = 'fs' +exports.IS_WINDOWS = process.platform === 'win32'; +// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 +exports.UV_FS_O_EXLOCK = 0x10000000; +exports.READONLY = fs.constants.O_RDONLY; +function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exports.stat(fsPath); + } + catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } + return true; + }); +} +exports.exists = exists; +function isDirectory(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); + return stats.isDirectory(); + }); +} +exports.isDirectory = isDirectory; +/** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (exports.IS_WINDOWS) { + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); +} +exports.isRooted = isRooted; +/** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ +function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { + // test file exists + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // on Windows, test for valid extension + const upperExt = path.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = undefined; + try { + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = path.dirname(filePath); + const upperName = path.basename(filePath).toUpperCase(); + for (const actualName of yield exports.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path.join(directory, actualName); + break; + } + } + } + catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ''; + }); +} +exports.tryGetExecutablePath = tryGetExecutablePath; +function normalizeSeparators(p) { + p = p || ''; + if (exports.IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); + } + // remove redundant slashes + return p.replace(/\/\/+/g, '/'); +} +// on Mac/Linux, test the execute bit +// R W X R W X R W X +// 256 128 64 32 16 8 4 2 1 +function isUnixExecutable(stats) { + return ((stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && stats.uid === process.getuid())); +} +// Get the path of cmd.exe in windows +function getCmdPath() { + var _a; + return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; +} +exports.getCmdPath = getCmdPath; +//# sourceMappingURL=io-util.js.map + +/***/ }), + +/***/ 9529: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; +const assert_1 = __nccwpck_require__(9491); +const path = __importStar(__nccwpck_require__(1017)); +const ioUtil = __importStar(__nccwpck_require__(7821)); +/** + * Copies a file or folder. + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +function cp(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + const { force, recursive, copySourceDirectory } = readCopyOptions(options); + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; + // Dest is an existing file, but not forcing + if (destStat && destStat.isFile() && !force) { + return; + } + // If dest is an existing directory, should copy inside. + const newDest = destStat && destStat.isDirectory() && copySourceDirectory + ? path.join(dest, path.basename(source)) + : dest; + if (!(yield ioUtil.exists(source))) { + throw new Error(`no such file or directory: ${source}`); + } + const sourceStat = yield ioUtil.stat(source); + if (sourceStat.isDirectory()) { + if (!recursive) { + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } + else { + yield cpDirRecursive(source, newDest, 0, force); + } + } + else { + if (path.relative(source, newDest) === '') { + // a file cannot be copied to itself + throw new Error(`'${newDest}' and '${source}' are the same file`); + } + yield copyFile(source, newDest, force); + } + }); +} +exports.cp = cp; +/** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See MoveOptions. + */ +function mv(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (yield ioUtil.exists(dest)) { + let destExists = true; + if (yield ioUtil.isDirectory(dest)) { + // If dest is directory copy src into dest + dest = path.join(dest, path.basename(source)); + destExists = yield ioUtil.exists(dest); + } + if (destExists) { + if (options.force == null || options.force) { + yield rmRF(dest); + } + else { + throw new Error('Destination already exists'); + } + } + } + yield mkdirP(path.dirname(dest)); + yield ioUtil.rename(source, dest); + }); +} +exports.mv = mv; +/** + * Remove a path recursively with force + * + * @param inputPath path to remove + */ +function rmRF(inputPath) { + return __awaiter(this, void 0, void 0, function* () { + if (ioUtil.IS_WINDOWS) { + // Check for invalid characters + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + if (/[*"<>|]/.test(inputPath)) { + throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); + } + } + try { + // note if path does not exist, error is silent + yield ioUtil.rm(inputPath, { + force: true, + maxRetries: 3, + recursive: true, + retryDelay: 300 + }); + } + catch (err) { + throw new Error(`File was unable to be removed ${err}`); + } + }); +} +exports.rmRF = rmRF; +/** + * Make a directory. Creates the full path with folders in between + * Will throw if it fails + * + * @param fsPath path to create + * @returns Promise + */ +function mkdirP(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, 'a path argument must be provided'); + yield ioUtil.mkdir(fsPath, { recursive: true }); + }); +} +exports.mkdirP = mkdirP; +/** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * If you check and the tool does not exist, it will throw. + * + * @param tool name of the tool + * @param check whether to check if tool exists + * @returns Promise path to tool + */ +function which(tool, check) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // recursive when check=true + if (check) { + const result = yield which(tool, false); + if (!result) { + if (ioUtil.IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } + else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ''; + }); +} +exports.which = which; +/** + * Returns a list of all occurrences of the given tool on the system path. + * + * @returns Promise the paths of the tool + */ +function findInPath(tool) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // build the list of extensions to try + const extensions = []; + if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { + for (const extension of process.env['PATHEXT'].split(path.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + // if it's rooted, return it if exists. otherwise return empty. + if (ioUtil.isRooted(tool)) { + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + // if any path separators, return empty + if (tool.includes(path.sep)) { + return []; + } + // build the list of directories + // + // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, + // it feels like we should not do this. Checking the current directory seems like more of a use + // case of a shell, and the which() function exposed by the toolkit should strive for consistency + // across platforms. + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(path.delimiter)) { + if (p) { + directories.push(p); + } + } + } + // find all matches + const matches = []; + for (const directory of directories) { + const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); +} +exports.findInPath = findInPath; +function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + const copySourceDirectory = options.copySourceDirectory == null + ? true + : Boolean(options.copySourceDirectory); + return { force, recursive, copySourceDirectory }; +} +function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return __awaiter(this, void 0, void 0, function* () { + // Ensure there is not a run away recursive copy + if (currentDepth >= 255) + return; + currentDepth++; + yield mkdirP(destDir); + const files = yield ioUtil.readdir(sourceDir); + for (const fileName of files) { + const srcFile = `${sourceDir}/${fileName}`; + const destFile = `${destDir}/${fileName}`; + const srcFileStat = yield ioUtil.lstat(srcFile); + if (srcFileStat.isDirectory()) { + // Recurse + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } + else { + yield copyFile(srcFile, destFile, force); + } + } + // Change the mode for the newly created directory + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); + }); +} +// Buffered file copy +function copyFile(srcFile, destFile, force) { + return __awaiter(this, void 0, void 0, function* () { + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { + // unlink/re-link it + try { + yield ioUtil.lstat(destFile); + yield ioUtil.unlink(destFile); + } + catch (e) { + // Try to override file permission + if (e.code === 'EPERM') { + yield ioUtil.chmod(destFile, '0666'); + yield ioUtil.unlink(destFile); + } + // other errors = it doesn't exist, no work to do + } + // Copy over symlink + const symlinkFull = yield ioUtil.readlink(srcFile); + yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); + } + else if (!(yield ioUtil.exists(destFile)) || force) { + yield ioUtil.copyFile(srcFile, destFile); + } + }); +} +//# sourceMappingURL=io.js.map + +/***/ }), + +/***/ 9041: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(7111); + + +/***/ }), + +/***/ 7111: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +var net = __nccwpck_require__(1808); +var tls = __nccwpck_require__(4404); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var events = __nccwpck_require__(2361); +var assert = __nccwpck_require__(9491); +var util = __nccwpck_require__(3837); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + + +/***/ }), + +/***/ 5814: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(6471)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(3384)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(5940)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(9193)); + +var _nil = _interopRequireDefault(__nccwpck_require__(8654)); + +var _version = _interopRequireDefault(__nccwpck_require__(2362)); + +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); + +var _parse = _interopRequireDefault(__nccwpck_require__(5108)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 9313: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 8654: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 5108: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 1629: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 9271: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 2017: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 5183: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function stringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 6471: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(9271)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.default)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 3384: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(5717)); + +var _md = _interopRequireDefault(__nccwpck_require__(9313)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 5717: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = _default; +exports.URL = exports.DNS = void 0; + +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); + +var _parse = _interopRequireDefault(__nccwpck_require__(5108)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (namespace.length !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 5940: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(9271)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.default)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 9193: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(5717)); + +var _sha = _interopRequireDefault(__nccwpck_require__(2017)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 9815: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(1629)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 2362: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.substr(14, 1), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 1988: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.CommandHelper = void 0; +var os = __nccwpck_require__(2037); +var core = __nccwpck_require__(3195); +var exec = __nccwpck_require__(9714); +var CommandHelper = /** @class */ (function () { + function CommandHelper() { + } + /** + * Runs a command based on the OS of the agent running this task. + * @param command - the command to execute + * @returns the string output from the command + */ + CommandHelper.prototype.execCommandAsync = function (command) { + return __awaiter(this, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + if (!(os.platform() == 'win32')) return [3 /*break*/, 2]; + return [4 /*yield*/, this.execPwshCommandAsync(command)]; + case 1: + _a = _b.sent(); + return [3 /*break*/, 4]; + case 2: return [4 /*yield*/, this.execBashCommandAsync(command)]; + case 3: + _a = _b.sent(); + _b.label = 4; + case 4: return [2 /*return*/, _a]; + } + }); + }); + }; + /** + * @param command - the command to execute in Bash + * @returns the string output from the command + */ + CommandHelper.prototype.execBashCommandAsync = function (command) { + return __awaiter(this, void 0, void 0, function () { + var bashOutput, errorStream, options, exitCode, err_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + bashOutput = ''; + errorStream = ''; + options = { + listeners: { + stdout: function (data) { + bashOutput += data.toString(); + core.info(data.toString()); + }, + stderr: function (data) { + errorStream += data.toString(); + core.error(data.toString()); + } + }, + failOnStdErr: true, + ignoreReturnCode: false, + errStream: process.stderr, + outStream: process.stdout + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, exec.exec('bash', ['-c', command], options)]; + case 2: + exitCode = _a.sent(); + if (exitCode !== 0) { + throw new Error("Command failed with exit code " + exitCode + ". Error stream: " + errorStream); + } + return [2 /*return*/, bashOutput.trim()]; + case 3: + err_1 = _a.sent(); + core.setFailed(err_1.message); + throw err_1; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Executes a given command using the pwsh executable. + * @param command - the command to execute in PowerShell + * @returns the string output from the command + */ + CommandHelper.prototype.execPwshCommandAsync = function (command) { + return __awaiter(this, void 0, void 0, function () { + var pwshOutput, errorStream, options, exitCode, err_2; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + pwshOutput = ''; + errorStream = ''; + options = { + listeners: { + stdout: function (data) { + pwshOutput += data.toString(); + core.info(data.toString()); + }, + stderr: function (data) { + errorStream += data.toString(); + core.error(data.toString()); + } + }, + failOnStdErr: true, + ignoreReturnCode: false, + errStream: process.stderr, + outStream: process.stdout + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, exec.exec('pwsh', [command], options)]; + case 2: + exitCode = _a.sent(); + if (exitCode !== 0) { + throw new Error("Command failed with exit code " + exitCode + ". Error stream: " + errorStream); + } + return [2 /*return*/, pwshOutput.trim()]; + case 3: + err_2 = _a.sent(); + core.setFailed(err_2.message); + throw err_2; + case 4: return [2 /*return*/]; + } + }); + }); + }; + return CommandHelper; +}()); +exports.CommandHelper = CommandHelper; + + +/***/ }), + +/***/ 2929: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.ContainerAppHelper = void 0; +var core = __nccwpck_require__(3195); +var io = __nccwpck_require__(9529); +var path = __nccwpck_require__(1017); +var os = __nccwpck_require__(2037); +var CommandHelper_1 = __nccwpck_require__(1988); +var Utility_1 = __nccwpck_require__(2135); +var util = __nccwpck_require__(3837); +var cpExec = util.promisify((__nccwpck_require__(2081).exec)); +var ORYX_CLI_IMAGE = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; +var ORYX_BUILDER_IMAGE = 'mcr.microsoft.com/oryx/builder:20230208.1'; +var IS_WINDOWS_AGENT = os.platform() == 'win32'; +var PACK_CMD = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; +var ContainerAppHelper = /** @class */ (function () { + function ContainerAppHelper(disableTelemetry) { + this.disableTelemetry = false; + this.disableTelemetry = disableTelemetry; + } + /** + * Creates an Azure Container App based from an image that was previously built. + * @param containerAppName - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @param environment - the Container App Environment that will be associated with the Container App + * @param imageToDeploy - the name of the runnable application image that the Container App will be based from + * @param optionalCmdArgs - a set of optional command line arguments + */ + ContainerAppHelper.prototype.createContainerApp = function (containerAppName, resourceGroup, environment, imageToDeploy, optionalCmdArgs) { + return __awaiter(this, void 0, void 0, function () { + var command_1, err_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command_1 = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; + optionalCmdArgs.forEach(function (val) { + command_1 += " " + val; + }); + return [4 /*yield*/, cpExec("" + command_1)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_1 = _a.sent(); + core.error(err_1.message); + throw err_1; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Creates an Azure Container App based from a YAML configuration file. + * @param containerAppName - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @param yamlConfigPath - the path to the YAML configuration file that the Container App properties will be based from + */ + ContainerAppHelper.prototype.createContainerAppFromYaml = function (containerAppName, resourceGroup, yamlConfigPath) { + return __awaiter(this, void 0, void 0, function () { + var command, err_2; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_2 = _a.sent(); + core.error(err_2.message); + throw err_2; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Updates an existing Azure Container App based from an image that was previously built. + * @param containerAppName - the name of the existing Container App + * @param resourceGroup - the resource group that the existing Container App is found in + * @param imageToDeploy - the name of the runnable application image that the Container App will be based from + * @param optionalCmdArgs - a set of optional command line arguments + */ + ContainerAppHelper.prototype.updateContainerApp = function (containerAppName, resourceGroup, imageToDeploy, optionalCmdArgs) { + return __awaiter(this, void 0, void 0, function () { + var command_2, err_3; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command_2 = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; + optionalCmdArgs.forEach(function (val) { + command_2 += " " + val; + }); + return [4 /*yield*/, cpExec("" + command_2)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_3 = _a.sent(); + core.error(err_3.message); + throw err_3; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Updates an existing Azure Container App using the 'az containerapp up' command. + * @param containerAppName - the name of the existing Container App + * @param resourceGroup - the resource group that the existing Container App is found in + * @param imageToDeploy - the name of the runnable application image that the Container App will be based from + * @param optionalCmdArgs - a set of optional command line arguments + * @param ingress - the ingress that the Container App will be exposed on + * @param targetPort - the target port that the Container App will be exposed on + */ + ContainerAppHelper.prototype.updateContainerAppWithUp = function (containerAppName, resourceGroup, imageToDeploy, optionalCmdArgs, ingress, targetPort) { + return __awaiter(this, void 0, void 0, function () { + var util, command_3, err_4; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + util = new Utility_1.Utility(); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command_3 = "az containerapp up -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; + optionalCmdArgs.forEach(function (val) { + command_3 += " " + val; + }); + if (!util.isNullOrEmpty(ingress)) { + command_3 += " --ingress " + ingress; + } + if (!util.isNullOrEmpty(targetPort)) { + command_3 += " --target-port " + targetPort; + } + return [4 /*yield*/, cpExec("" + command_3)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_4 = _a.sent(); + core.error(err_4.message); + throw err_4; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Updates an existing Azure Container App based from a YAML configuration file. + * @param containerAppName - the name of the existing Container App + * @param resourceGroup - the resource group that the existing Container App is found in + * @param yamlConfigPath - the path to the YAML configuration file that the Container App properties will be based from + */ + ContainerAppHelper.prototype.updateContainerAppFromYaml = function (containerAppName, resourceGroup, yamlConfigPath) { + return __awaiter(this, void 0, void 0, function () { + var command, err_5; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_5 = _a.sent(); + core.error(err_5.message); + throw err_5; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Determines if the provided Container App exists in the provided resource group. + * @param containerAppName - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @returns true if the Container App exists, false otherwise + */ + ContainerAppHelper.prototype.doesContainerAppExist = function (containerAppName, resourceGroup) { + return __awaiter(this, void 0, void 0, function () { + var command, _a, stdout, stderr, err_6; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + core.debug("Attempting to determine if Container App with name \"" + containerAppName + "\" exists in resource group \"" + resourceGroup + "\""); + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + command = "az containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; + return [2 /*return*/, !stderr]; + case 3: + err_6 = _b.sent(); + core.warning(err_6.message); + return [2 /*return*/, false]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Determines if the provided Container App Environment exists in the provided resource group. + * @param containerAppEnvironment - the name of the Container App Environment + * @param resourceGroup - the resource group that the Container App Environment is found in + * @returns true if the Container App Environment exists, false otherwise + */ + ContainerAppHelper.prototype.doesContainerAppEnvironmentExist = function (containerAppEnvironment, resourceGroup) { + return __awaiter(this, void 0, void 0, function () { + var command, _a, stdout, stderr, err_7; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + core.debug("Attempting to determine if Container App Environment with name \"" + containerAppEnvironment + "\" exists in resource group \"" + resourceGroup + "\""); + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + command = "az containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; + return [2 /*return*/, !stderr]; + case 3: + err_7 = _b.sent(); + core.warning(err_7.message); + return [2 /*return*/, false]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Determines if the provided resource group exists. + * @param resourceGroup - the name of the resource group + * @returns true if the resource group exists, false otherwise + */ + ContainerAppHelper.prototype.doesResourceGroupExist = function (resourceGroup) { + return __awaiter(this, void 0, void 0, function () { + var command, _a, stdout, stderr, err_8; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + core.debug("Attempting to determine if resource group \"" + resourceGroup + "\" exists"); + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + command = "az group show -n " + resourceGroup + " -o none"; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; + return [2 /*return*/, !stderr]; + case 3: + err_8 = _b.sent(); + core.warning(err_8.message); + return [2 /*return*/, false]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Gets the default location for the Container App provider. + * @returns the default location if found, otherwise 'eastus2' + */ + ContainerAppHelper.prototype.getDefaultContainerAppLocation = function () { + return __awaiter(this, void 0, void 0, function () { + var command, _a, stdout, stderr, err_9; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + core.debug("Attempting to get the default location for the Container App service for the subscription."); + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + command = "az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; + // If successful, strip out double quotes, spaces and parentheses from the first location returned + return [2 /*return*/, !stderr ? stdout.toLowerCase().replace(/["() ]/g, "") : "eastus2"]; + case 3: + err_9 = _b.sent(); + core.warning(err_9.message); + return [2 /*return*/, "eastus2"]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Creates a new resource group in the provided location. + * @param name - the name of the resource group to create + * @param location - the location to create the resource group in + */ + ContainerAppHelper.prototype.createResourceGroup = function (name, location) { + return __awaiter(this, void 0, void 0, function () { + var command, err_10; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to create resource group \"" + name + "\" in location \"" + location + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = "az group create -n " + name + " -l " + location; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_10 = _a.sent(); + core.error(err_10.message); + throw err_10; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Gets the name of an existing Container App Environment in the provided resource group. + * @param resourceGroup - the resource group to check for an existing Container App Environment + * @returns the name of the existing Container App Environment, null if none exists + */ + ContainerAppHelper.prototype.getExistingContainerAppEnvironment = function (resourceGroup) { + return __awaiter(this, void 0, void 0, function () { + var command, _a, stdout, stderr, err_11; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + core.debug("Attempting to get the existing Container App Environment in resource group \"" + resourceGroup + "\""); + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + command = "az containerapp env list -g " + resourceGroup + " --query [0].name\""; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; + return [2 /*return*/, !stderr ? stdout : null]; + case 3: + err_11 = _b.sent(); + core.warning(err_11.message); + return [2 /*return*/, null]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Creates a new Azure Container App Environment in the provided resource group. + * @param name - the name of the Container App Environment + * @param resourceGroup - the resource group that the Container App Environment will be created in + * @param location - the location that the Container App Environment will be created in + */ + ContainerAppHelper.prototype.createContainerAppEnvironment = function (name, resourceGroup, location) { + return __awaiter(this, void 0, void 0, function () { + var util, command, err_12; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + util = new Utility_1.Utility(); + core.debug("Attempting to create Container App Environment with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = "az containerapp env create -n " + name + " -g " + resourceGroup; + if (!util.isNullOrEmpty(location)) { + command += " -l " + location; + } + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_12 = _a.sent(); + core.error(err_12.message); + throw err_12; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Disables ingress on an existing Container App. + * @param name - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + */ + ContainerAppHelper.prototype.disableContainerAppIngress = function (name, resourceGroup) { + return __awaiter(this, void 0, void 0, function () { + var command, err_13; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to disable ingress for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = "az containerapp ingress disable -n " + name + " -g " + resourceGroup; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_13 = _a.sent(); + core.error(err_13.message); + throw err_13; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Updates the ACR details on an existing Container App. + * @param name - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @param acrName - the name of the Azure Container Registry (without the .azurecr.io suffix) + * @param acrUsername - the username used to authenticate with the Azure Container Registry + * @param acrPassword - the password used to authenticate with the Azure Container Registry + */ + ContainerAppHelper.prototype.updateContainerAppRegistryDetails = function (name, resourceGroup, acrName, acrUsername, acrPassword) { + return __awaiter(this, void 0, void 0, function () { + var command, err_14; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to set the ACR details for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = "az containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; + return [4 /*yield*/, cpExec("" + command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_14 = _a.sent(); + core.error(err_14.message); + throw err_14; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Using the Oryx++ Builder, creates a runnable application image from the provided application source. + * @param imageToDeploy - the name of the runnable application image that is created and can be later deployed + * @param appSourcePath - the path to the application source on the machine + * @param runtimeStack - the runtime stack to use in the image layer that runs the application + */ + ContainerAppHelper.prototype.createRunnableAppImage = function (imageToDeploy, appSourcePath, runtimeStack) { + return __awaiter(this, void 0, void 0, function () { + var telemetryArg, err_15; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to create a runnable application image using the Oryx++ Builder with image name \"" + imageToDeploy + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + telemetryArg = "--env \"CALLER_ID=azure-pipelines-rc-v1\""; + if (this.disableTelemetry) { + telemetryArg = "--env \"ORYX_DISABLE_TELEMETRY=true\""; + } + return [4 /*yield*/, cpExec(PACK_CMD + " build " + imageToDeploy + " --path " + appSourcePath + " --builder " + ORYX_BUILDER_IMAGE + " --run-image mcr.microsoft.com/oryx/" + runtimeStack + " " + telemetryArg)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_15 = _a.sent(); + core.error(err_15.message); + throw err_15; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Using a Dockerfile that was provided or found at the root of the application source, + * creates a runable application image. + * @param imageToDeploy - the name of the runnable application image that is created and can be later deployed + * @param appSourcePath - the path to the application source on the machine + * @param dockerfilePath - the path to the Dockerfile to build and tag with the provided image name + */ + ContainerAppHelper.prototype.createRunnableAppImageFromDockerfile = function (imageToDeploy, appSourcePath, dockerfilePath) { + return __awaiter(this, void 0, void 0, function () { + var dockerTool, err_16; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to create a runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); + _a.label = 1; + case 1: + _a.trys.push([1, 4, , 5]); + return [4 /*yield*/, io.which("docker", true)]; + case 2: + dockerTool = _a.sent(); + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, ['build', '--file', "" + dockerfilePath, "" + appSourcePath, '--tag', "" + imageToDeploy])]; + case 3: + _a.sent(); + core.debug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); + return [3 /*break*/, 5]; + case 4: + err_16 = _a.sent(); + core.setFailed(err_16.message); + throw err_16; + case 5: return [2 /*return*/]; + } + }); + }); + }; + /** + * Determines the runtime stack to use for the runnable application image. + * @param appSourcePath - the path to the application source on the machine + * @returns a string representing the runtime stack that can be used for the Oryx MCR runtime images + */ + ContainerAppHelper.prototype.determineRuntimeStackAsync = function (appSourcePath) { + return __awaiter(this, void 0, void 0, function () { + var dockerTool, oryxRuntimeTxtPath, command, runtimeStack, err_17; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug('Attempting to determine the runtime stack needed for the provided application source'); + _a.label = 1; + case 1: + _a.trys.push([1, 6, , 7]); + return [4 /*yield*/, io.which("docker", true)]; + case 2: + dockerTool = _a.sent(); + // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, ['run', '--rm', '-v', appSourcePath + ":/app", "" + ORYX_CLI_IMAGE, '/bin/bash', '-c', "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"]) + // Read the temp file to get the runtime stack into a variable + ]; + case 3: + // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file + _a.sent(); + oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); + command = "head -n 1 " + oryxRuntimeTxtPath; + if (IS_WINDOWS_AGENT) { + command = "Get-Content -Path " + oryxRuntimeTxtPath + " -Head 1"; + } + return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; + case 4: + runtimeStack = _a.sent(); + // Delete the temp file + command = "rm " + oryxRuntimeTxtPath; + if (IS_WINDOWS_AGENT) { + command = "Remove-Item -Path " + oryxRuntimeTxtPath; + } + return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; + case 5: + _a.sent(); + return [2 /*return*/, runtimeStack]; + case 6: + err_17 = _a.sent(); + core.setFailed(err_17.message); + throw err_17; + case 7: return [2 /*return*/]; + } + }); + }); + }; + /** + * Sets the default builder on the machine to the Oryx++ Builder to prevent an exception from being thrown due + * to no default builder set. + */ + ContainerAppHelper.prototype.setDefaultBuilder = function () { + return __awaiter(this, void 0, void 0, function () { + var err_18; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, cpExec("pack config default-builder " + ORYX_BUILDER_IMAGE)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_18 = _a.sent(); + core.setFailed(err_18.message); + throw err_18; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Installs the pack CLI that will be used to build a runnable application image. + * For more information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ + */ + ContainerAppHelper.prototype.installPackCliAsync = function () { + return __awaiter(this, void 0, void 0, function () { + var command, packZipDownloadUri, packZipDownloadFilePath, tgzSuffix, err_19; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug('Attempting to install the pack CLI'); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = ''; + if (IS_WINDOWS_AGENT) { + packZipDownloadUri = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; + packZipDownloadFilePath = path.join(PACK_CMD, 'pack-windows.zip'); + command = "New-Item -ItemType Directory -Path " + PACK_CMD + " -Force | Out-Null;" + + ("Invoke-WebRequest -Uri " + packZipDownloadUri + " -OutFile " + packZipDownloadFilePath + "; ") + + ("Expand-Archive -LiteralPath " + packZipDownloadFilePath + " -DestinationPath " + PACK_CMD + "; ") + + ("Remove-Item -Path " + packZipDownloadFilePath); + } + else { + tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; + command = "(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; + } + return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_19 = _a.sent(); + core.error("Unable to install the pack CLI. Error: " + err_19.message); + core.setFailed(err_19.message); + throw err_19; + case 4: return [2 /*return*/]; + } + }); + }); + }; + return ContainerAppHelper; +}()); +exports.ContainerAppHelper = ContainerAppHelper; + + +/***/ }), + +/***/ 4769: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.ContainerRegistryHelper = void 0; +var core = __nccwpck_require__(3195); +var exec = __nccwpck_require__(9714); +var io = __nccwpck_require__(9529); +var CommandHelper_1 = __nccwpck_require__(1988); +var Utility_1 = __nccwpck_require__(2135); +var ContainerRegistryHelper = /** @class */ (function () { + function ContainerRegistryHelper() { + } + /** + * Authorizes Docker to make calls to the provided ACR instance using username and password. + * @param acrName - the name of the ACR instance to authenticate calls to + * @param acrUsername - the username for authentication + * @param acrPassword - the password for authentication + */ + ContainerRegistryHelper.prototype.loginAcrWithUsernamePassword = function (acrName, acrUsername, acrPassword) { + return __awaiter(this, void 0, void 0, function () { + var err_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, exec.exec('docker', ["login", "--password-stdin", "--username", "" + acrUsername, acrName + ".azurecr.io"], { input: Buffer.from(acrPassword) })]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_1 = _a.sent(); + core.error("Failed to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + throw err_1; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Authorizes Docker to make calls to the provided ACR instance using an access token that is generated via + * the 'az acr login --expose-token' command. + * @param acrName - the name of the ACR instance to authenticate calls to. + */ + ContainerRegistryHelper.prototype.loginAcrWithAccessTokenAsync = function (acrName) { + return __awaiter(this, void 0, void 0, function () { + var command, err_2; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to log in to ACR instance \"" + acrName + "\" with access token"); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + command = "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"; + return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_2 = _a.sent(); + core.error("Failed to log in to ACR instance \"" + acrName + "\" with access token"); + throw err_2; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Pushes an image to the ACR instance that was previously authenticated against. + * @param imageToPush - the name of the image to push to ACR + */ + ContainerRegistryHelper.prototype.pushImageToAcr = function (imageToPush) { + return __awaiter(this, void 0, void 0, function () { + var dockerTool, err_3; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + core.debug("Attempting to push image \"" + imageToPush + "\" to ACR"); + _a.label = 1; + case 1: + _a.trys.push([1, 4, , 5]); + return [4 /*yield*/, io.which("docker", true)]; + case 2: + dockerTool = _a.sent(); + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, ["push", "" + imageToPush])]; + case 3: + _a.sent(); + return [3 /*break*/, 5]; + case 4: + err_3 = _a.sent(); + core.error("Failed to push image \"" + imageToPush + "\" to ACR. Error: " + err_3.message); + core.setFailed(err_3.message); + throw err_3; + case 5: return [2 /*return*/]; + } + }); + }); + }; + return ContainerRegistryHelper; +}()); +exports.ContainerRegistryHelper = ContainerRegistryHelper; + + +/***/ }), + +/***/ 7166: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.TelemetryHelper = void 0; +var core = __nccwpck_require__(3195); +var Utility_1 = __nccwpck_require__(2135); +var io = __nccwpck_require__(9529); +var ORYX_CLI_IMAGE = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; +var SUCCESSFUL_RESULT = "succeeded"; +var FAILED_RESULT = "failed"; +var BUILDER_SCENARIO = "used-builder"; +var DOCKERFILE_SCENARIO = "used-dockerfile"; +var IMAGE_SCENARIO = "used-image"; +var util = new Utility_1.Utility(); +var TelemetryHelper = /** @class */ (function () { + function TelemetryHelper(disableTelemetry) { + this.disableTelemetry = disableTelemetry; + this.taskStartMilliseconds = Date.now(); + } + /** + * Marks that the task was successful in telemetry. + */ + TelemetryHelper.prototype.setSuccessfulResult = function () { + this.result = SUCCESSFUL_RESULT; + }; + /** + * Marks that the task failed in telemetry. + */ + TelemetryHelper.prototype.setFailedResult = function (errorMessage) { + this.result = FAILED_RESULT; + this.errorMessage = errorMessage; + }; + /** + * Marks that the task used the builder scenario. + */ + TelemetryHelper.prototype.setBuilderScenario = function () { + this.scenario = BUILDER_SCENARIO; + }; + /** + * Marks that the task used the Dockerfile scenario. + */ + TelemetryHelper.prototype.setDockerfileScenario = function () { + this.scenario = DOCKERFILE_SCENARIO; + }; + /** + * Marks that the task used the previously built image scenario. + */ + TelemetryHelper.prototype.setImageScenario = function () { + this.scenario = IMAGE_SCENARIO; + }; + /** + * If telemetry is enabled, uses the "oryx telemetry" command to log metadata about this task execution. + */ + TelemetryHelper.prototype.sendLogs = function () { + return __awaiter(this, void 0, void 0, function () { + var taskLengthMilliseconds, resultArg, scenarioArg, errorMessageArg, args, err_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + taskLengthMilliseconds = Date.now() - this.taskStartMilliseconds; + if (!!this.disableTelemetry) return [3 /*break*/, 4]; + core.info("Telemetry enabled; logging metadata about task result, length and scenario targeted."); + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + resultArg = ''; + if (!util.isNullOrEmpty(this.result)) { + resultArg = "--property 'result=" + this.result + "'"; + } + scenarioArg = ''; + if (!util.isNullOrEmpty(this.scenario)) { + scenarioArg = "--property 'scenario=" + this.scenario + "'"; + } + errorMessageArg = ''; + if (!util.isNullOrEmpty(this.errorMessage)) { + errorMessageArg = "--property 'errorMessage=" + this.errorMessage + "'"; + } + args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name 'ContainerAppsPipelinesTaskRCV1' " + ("--processing-time '" + taskLengthMilliseconds + "' " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; + // Don't use Utility's throwIfError() since it will still record an error in the pipeline logs, but won't fail the task + return [4 /*yield*/, executeDockerCommand(args, true)]; + case 2: + // Don't use Utility's throwIfError() since it will still record an error in the pipeline logs, but won't fail the task + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_1 = _a.sent(); + core.warning("Skipping telemetry logging due to the following exception: " + err_1.message); + return [3 /*break*/, 4]; + case 4: return [2 /*return*/]; + } + }); + }); + }; + return TelemetryHelper; +}()); +exports.TelemetryHelper = TelemetryHelper; +var executeDockerCommand = function (args, continueOnError) { + if (continueOnError === void 0) { continueOnError = false; } + return __awaiter(void 0, void 0, void 0, function () { + var dockerTool, err_2; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 3, , 4]); + return [4 /*yield*/, io.which("docker", true)]; + case 1: + dockerTool = _a.sent(); + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, args, continueOnError)]; + case 2: + _a.sent(); + return [3 /*break*/, 4]; + case 3: + err_2 = _a.sent(); + core.setFailed("Error: " + err_2.message); + throw err_2; // Re-throw the error + case 4: return [2 /*return*/]; + } + }); + }); +}; + + +/***/ }), + +/***/ 2135: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.Utility = void 0; +var core = __nccwpck_require__(3195); +var exec = __nccwpck_require__(9714); +var util = __nccwpck_require__(3837); +var cpExec = util.promisify((__nccwpck_require__(2081).exec)); +var Utility = /** @class */ (function () { + function Utility() { + } + /** + * @param commandLine - the command to execute + * @param args - the arguments to pass to the command + * @param continueOnError - whether or not to continue execution if the command fails + */ + Utility.prototype.executeAndthrowIfError = function (commandLine, args, continueOnError) { + if (continueOnError === void 0) { continueOnError = false; } + return __awaiter(this, void 0, void 0, function () { + var stdout_1, stderr_1, options, exitCode, error_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + stdout_1 = ''; + stderr_1 = ''; + options = { + listeners: { + stdout: function (data) { + stdout_1 += data.toString(); + core.info(data.toString()); + }, + stderr: function (data) { + stderr_1 += data.toString(); + core.error(data.toString()); + } + } + }; + return [4 /*yield*/, exec.exec(commandLine, args, options)]; + case 1: + exitCode = _a.sent(); + if (!continueOnError && exitCode !== 0) { + core.error("Command failed with exit code " + exitCode + ". Error stream: " + stderr_1); + throw new Error("Command failed with exit code " + exitCode + ". Error stream: " + stderr_1); + } + return [3 /*break*/, 3]; + case 2: + error_1 = _a.sent(); + core.setFailed("Error: " + error_1.message); + throw error_1; // Re-throw the error + case 3: return [2 /*return*/]; + } + }); + }); + }; + /** + * Sets the Azure CLI to dynamically install extensions that are missing. In this case, we care about the + * Azure Container Apps module being dynamically installed while it's still in preview. + */ + Utility.prototype.setAzureCliDynamicInstall = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, cpExec("az config set extension.use_dynamic_install=yes_without_prompt")]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Checks whether or not the provided string is null, undefined or empty. + * @param str - the string to validate + * @returns true if the string is null, undefined or empty, false otherwise + */ + Utility.prototype.isNullOrEmpty = function (str) { + return str === null || str === undefined || str === ""; + }; + return Utility; +}()); +exports.Utility = Utility; + + +/***/ }), + +/***/ 9491: +/***/ ((module) => { + +"use strict"; +module.exports = require("assert"); + +/***/ }), + +/***/ 2081: +/***/ ((module) => { + +"use strict"; +module.exports = require("child_process"); + +/***/ }), + +/***/ 6113: +/***/ ((module) => { + +"use strict"; +module.exports = require("crypto"); + +/***/ }), + +/***/ 2361: +/***/ ((module) => { + +"use strict"; +module.exports = require("events"); + +/***/ }), + +/***/ 7147: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs"); + +/***/ }), + +/***/ 3685: +/***/ ((module) => { + +"use strict"; +module.exports = require("http"); + +/***/ }), + +/***/ 5687: +/***/ ((module) => { + +"use strict"; +module.exports = require("https"); + +/***/ }), + +/***/ 1808: +/***/ ((module) => { + +"use strict"; +module.exports = require("net"); + +/***/ }), + +/***/ 2037: +/***/ ((module) => { + +"use strict"; +module.exports = require("os"); + +/***/ }), + +/***/ 1017: +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ 1576: +/***/ ((module) => { + +"use strict"; +module.exports = require("string_decoder"); + +/***/ }), + +/***/ 9512: +/***/ ((module) => { + +"use strict"; +module.exports = require("timers"); + +/***/ }), + +/***/ 4404: +/***/ ((module) => { + +"use strict"; +module.exports = require("tls"); + +/***/ }), + +/***/ 3837: +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __nccwpck_require__(3238); +/******/ module.exports = __webpack_exports__; +/******/ +/******/ })() +; \ No newline at end of file diff --git a/dist/licenses.txt b/dist/licenses.txt new file mode 100644 index 00000000..d7718469 --- /dev/null +++ b/dist/licenses.txt @@ -0,0 +1,97 @@ +@actions/core +MIT +The MIT License (MIT) + +Copyright 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@actions/exec +MIT +The MIT License (MIT) + +Copyright 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@actions/http-client +MIT +Actions Http Client for Node.js + +Copyright (c) GitHub, Inc. + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +@actions/io +MIT +The MIT License (MIT) + +Copyright 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +tunnel +MIT +The MIT License (MIT) + +Copyright (c) 2012 Koichi Kobayashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +uuid +MIT +The MIT License (MIT) + +Copyright (c) 2010-2020 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..32e76251 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,491 @@ +{ + "name": "container-apps-deploy-action", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "container-apps-deploy-action", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@actions/core": "^1.10.0", + "@actions/exec": "^1.1.1", + "@actions/github": "^5.1.1", + "typescript": "^5.2.2" + }, + "devDependencies": { + "@types/node": "^20.6.0" + } + }, + "node_modules/@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/github": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", + "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "@octokit/core": "^3.6.0", + "@octokit/plugin-paginate-rest": "^2.17.0", + "@octokit/plugin-rest-endpoint-methods": "^5.13.0" + } + }, + "node_modules/@actions/http-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.1.tgz", + "integrity": "sha512-qhrkRMB40bbbLo7gF+0vu+X+UawOvQQqNAA/5Unx774RS8poaOhThDOG6BGmxvAnxhQnDp2BG/ZUm65xZILTpw==", + "dependencies": { + "tunnel": "^0.0.6" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" + }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dependencies": { + "@octokit/types": "^6.40.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "dependencies": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dependencies": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "node_modules/@types/node": { + "version": "20.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz", + "integrity": "sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==", + "dev": true + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + }, + "dependencies": { + "@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "requires": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "requires": { + "@actions/io": "^1.0.1" + } + }, + "@actions/github": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", + "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", + "requires": { + "@actions/http-client": "^2.0.1", + "@octokit/core": "^3.6.0", + "@octokit/plugin-paginate-rest": "^2.17.0", + "@octokit/plugin-rest-endpoint-methods": "^5.13.0" + } + }, + "@actions/http-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.1.tgz", + "integrity": "sha512-qhrkRMB40bbbLo7gF+0vu+X+UawOvQQqNAA/5Unx774RS8poaOhThDOG6BGmxvAnxhQnDp2BG/ZUm65xZILTpw==", + "requires": { + "tunnel": "^0.0.6" + } + }, + "@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" + }, + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "requires": { + "@octokit/types": "^6.40.0" + } + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "requires": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "requires": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "@types/node": { + "version": "20.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz", + "integrity": "sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==", + "dev": true + }, + "before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==" + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..a80a3598 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "container-apps-deploy-action", + "version": "1.0.0", + "description": "This action allows users to easily deploy their application source to an\r [Azure Container App](https://azure.microsoft.com/en-us/services/container-apps/) in their GitHub workflow by either\r providing a previously built image, a Dockerfile that an image can be built from, or using a builder to create a\r runnable application image for the user.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Azure/container-apps-deploy-action.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/Azure/container-apps-deploy-action/issues" + }, + "homepage": "https://github.com/Azure/container-apps-deploy-action#readme", + "dependencies": { + "@actions/core": "^1.10.0", + "@actions/exec": "^1.1.1", + "@actions/github": "^5.1.1", + "typescript": "^5.2.2" + }, + "devDependencies": { + "@types/node": "^20.6.0" + } +} diff --git a/src/CommandHelper.ts b/src/CommandHelper.ts new file mode 100644 index 00000000..5b23649e --- /dev/null +++ b/src/CommandHelper.ts @@ -0,0 +1,89 @@ +import * as os from 'os' +import * as core from '@actions/core'; +import * as exec from '@actions/exec'; + +export class CommandHelper { + + /** + * Runs a command based on the OS of the agent running this task. + * @param command - the command to execute + * @returns the string output from the command + */ + public async execCommandAsync(command: string): Promise { + return os.platform() == 'win32' ? + await this.execPwshCommandAsync(command) : + await this.execBashCommandAsync(command); + } + + /** + * @param command - the command to execute in Bash + * @returns the string output from the command + */ + private async execBashCommandAsync(command: string): Promise { + var bashOutput: string = ''; + var errorStream: string = ''; + + const options: any = { + listeners: { + stdout: (data: Buffer) => { + bashOutput += data.toString(); + core.info(data.toString()); + }, + stderr: (data: Buffer) => { + errorStream += data.toString(); + core.error(data.toString()); + } + }, + failOnStdErr: true, + ignoreReturnCode: false, + errStream: process.stderr, + outStream: process.stdout, + } + try { + var exitCode = await exec.exec('bash', ['-c', command], options); + if (exitCode !== 0) { + throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${errorStream}`); + } + return bashOutput.trim(); + } catch (err) { + core.setFailed(err.message); + throw err; + } + } + + /** + * Executes a given command using the pwsh executable. + * @param command - the command to execute in PowerShell + * @returns the string output from the command + */ + private async execPwshCommandAsync(command: string): Promise { + var pwshOutput: string = ''; + var errorStream: string = ''; + const options: any = { + listeners: { + stdout: (data: Buffer) => { + pwshOutput += data.toString(); + core.info(data.toString()); + }, + stderr: (data: Buffer) => { + errorStream += data.toString(); + core.error(data.toString()); + } + }, + failOnStdErr: true, + ignoreReturnCode: false, + errStream: process.stderr, + outStream: process.stdout, + } + try { + var exitCode = await exec.exec('pwsh', [command], options); + if (exitCode !== 0) { + throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${errorStream}`); + } + return pwshOutput.trim(); + } catch (err) { + core.setFailed(err.message); + throw err; + } + } +} \ No newline at end of file diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts new file mode 100644 index 00000000..4a456b48 --- /dev/null +++ b/src/ContainerAppHelper.ts @@ -0,0 +1,439 @@ +import * as core from '@actions/core'; +import * as io from '@actions/io'; +import * as path from 'path'; +import * as os from 'os'; +import { CommandHelper } from './CommandHelper'; +import { Utility } from './Utility'; +import util = require('util'); +const cpExec = util.promisify(require('child_process').exec); + +const ORYX_CLI_IMAGE: string = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; +const ORYX_BUILDER_IMAGE: string = 'mcr.microsoft.com/oryx/builder:20230208.1'; +const IS_WINDOWS_AGENT: boolean = os.platform() == 'win32'; +const PACK_CMD: string = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; + +export class ContainerAppHelper { + readonly disableTelemetry: boolean = false; + + constructor(disableTelemetry: boolean) { + this.disableTelemetry = disableTelemetry; + } + + /** + * Creates an Azure Container App based from an image that was previously built. + * @param containerAppName - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @param environment - the Container App Environment that will be associated with the Container App + * @param imageToDeploy - the name of the runnable application image that the Container App will be based from + * @param optionalCmdArgs - a set of optional command line arguments + */ + public async createContainerApp( + containerAppName: string, + resourceGroup: string, + environment: string, + imageToDeploy: string, + optionalCmdArgs: string[]) { + core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + try { + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; + optionalCmdArgs.forEach(function (val: string) { + command += ` ${val}`; + }); + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Creates an Azure Container App based from a YAML configuration file. + * @param containerAppName - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @param yamlConfigPath - the path to the YAML configuration file that the Container App properties will be based from + */ + public async createContainerAppFromYaml( + containerAppName: string, + resourceGroup: string, + yamlConfigPath: string) { + core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + try { + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Updates an existing Azure Container App based from an image that was previously built. + * @param containerAppName - the name of the existing Container App + * @param resourceGroup - the resource group that the existing Container App is found in + * @param imageToDeploy - the name of the runnable application image that the Container App will be based from + * @param optionalCmdArgs - a set of optional command line arguments + */ + public async updateContainerApp( + containerAppName: string, + resourceGroup: string, + imageToDeploy: string, + optionalCmdArgs: string[]) { + core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + try { + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + optionalCmdArgs.forEach(function (val: string) { + command += ` ${val}`; + }); + + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Updates an existing Azure Container App using the 'az containerapp up' command. + * @param containerAppName - the name of the existing Container App + * @param resourceGroup - the resource group that the existing Container App is found in + * @param imageToDeploy - the name of the runnable application image that the Container App will be based from + * @param optionalCmdArgs - a set of optional command line arguments + * @param ingress - the ingress that the Container App will be exposed on + * @param targetPort - the target port that the Container App will be exposed on + */ + public async updateContainerAppWithUp( + containerAppName: string, + resourceGroup: string, + imageToDeploy: string, + optionalCmdArgs: string[], + ingress?: string, + targetPort?: string) { + core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + const util = new Utility(); + try { + let command = `az containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + optionalCmdArgs.forEach(function (val: string) { + command += ` ${val}`; + }); + + if (!util.isNullOrEmpty(ingress)) { + command += ` --ingress ${ingress}`; + } + + if (!util.isNullOrEmpty(targetPort)) { + command += ` --target-port ${targetPort}`; + } + + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Updates an existing Azure Container App based from a YAML configuration file. + * @param containerAppName - the name of the existing Container App + * @param resourceGroup - the resource group that the existing Container App is found in + * @param yamlConfigPath - the path to the YAML configuration file that the Container App properties will be based from + */ + public async updateContainerAppFromYaml( + containerAppName: string, + resourceGroup: string, + yamlConfigPath: string) { + core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + try { + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Determines if the provided Container App exists in the provided resource group. + * @param containerAppName - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @returns true if the Container App exists, false otherwise + */ + public async doesContainerAppExist(containerAppName: string, resourceGroup: string): Promise { + core.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); + try { + const command = `az containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; + const {stdout, stderr} = await cpExec(`${command}`); + return !stderr; + } catch (err) { + core.warning(err.message); + return false; + } + } + + /** + * Determines if the provided Container App Environment exists in the provided resource group. + * @param containerAppEnvironment - the name of the Container App Environment + * @param resourceGroup - the resource group that the Container App Environment is found in + * @returns true if the Container App Environment exists, false otherwise + */ + public async doesContainerAppEnvironmentExist(containerAppEnvironment: string, resourceGroup: string): Promise { + core.debug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); + try { + const command = `az containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; + const {stdout, stderr} = await cpExec(`${command}`); + return !stderr; + } catch (err) { + core.warning(err.message); + return false; + } + } + + /** + * Determines if the provided resource group exists. + * @param resourceGroup - the name of the resource group + * @returns true if the resource group exists, false otherwise + */ + public async doesResourceGroupExist(resourceGroup: string): Promise { + core.debug(`Attempting to determine if resource group "${resourceGroup}" exists`); + try { + const command = `az group show -n ${resourceGroup} -o none`; + const {stdout, stderr} = await cpExec(`${command}`); + return !stderr; + } catch (err) { + core.warning(err.message); + return false; + } + } + + /** + * Gets the default location for the Container App provider. + * @returns the default location if found, otherwise 'eastus2' + */ + public async getDefaultContainerAppLocation(): Promise { + core.debug(`Attempting to get the default location for the Container App service for the subscription.`); + try { + const command = `az provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"` + const {stdout, stderr} = await cpExec(`${command}`); + // If successful, strip out double quotes, spaces and parentheses from the first location returned + return !stderr ? stdout.toLowerCase().replace(/["() ]/g, "") : `eastus2`; + } catch (err) { + core.warning(err.message); + return `eastus2`; + } + } + + /** + * Creates a new resource group in the provided location. + * @param name - the name of the resource group to create + * @param location - the location to create the resource group in + */ + public async createResourceGroup(name: string, location: string) { + core.debug(`Attempting to create resource group "${name}" in location "${location}"`); + try { + const command = `az group create -n ${name} -l ${location}`; + await cpExec(`${command}`); + + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Gets the name of an existing Container App Environment in the provided resource group. + * @param resourceGroup - the resource group to check for an existing Container App Environment + * @returns the name of the existing Container App Environment, null if none exists + */ + public async getExistingContainerAppEnvironment(resourceGroup: string) { + core.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); + try { + const command = `az containerapp env list -g ${resourceGroup} --query [0].name"`; + const {stdout, stderr} = await cpExec(`${command}`); + return !stderr ? stdout : null; + } catch (err) { + core.warning(err.message); + return null; + } + } + + /** + * Creates a new Azure Container App Environment in the provided resource group. + * @param name - the name of the Container App Environment + * @param resourceGroup - the resource group that the Container App Environment will be created in + * @param location - the location that the Container App Environment will be created in + */ + public async createContainerAppEnvironment(name: string, resourceGroup: string, location?: string) { + const util = new Utility(); + core.debug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); + try { + let command = `az containerapp env create -n ${name} -g ${resourceGroup}`; + if (!util.isNullOrEmpty(location)) { + command += ` -l ${location}`; + } + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Disables ingress on an existing Container App. + * @param name - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + */ + public async disableContainerAppIngress(name: string, resourceGroup: string) { + core.debug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); + try { + const command = `az containerapp ingress disable -n ${name} -g ${resourceGroup}`; + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Updates the ACR details on an existing Container App. + * @param name - the name of the Container App + * @param resourceGroup - the resource group that the Container App is found in + * @param acrName - the name of the Azure Container Registry (without the .azurecr.io suffix) + * @param acrUsername - the username used to authenticate with the Azure Container Registry + * @param acrPassword - the password used to authenticate with the Azure Container Registry + */ + public async updateContainerAppRegistryDetails(name: string, resourceGroup: string, acrName: string, acrUsername: string, acrPassword: string) { + core.debug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); + try { + const command = `az containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Using the Oryx++ Builder, creates a runnable application image from the provided application source. + * @param imageToDeploy - the name of the runnable application image that is created and can be later deployed + * @param appSourcePath - the path to the application source on the machine + * @param runtimeStack - the runtime stack to use in the image layer that runs the application + */ + public async createRunnableAppImage( + imageToDeploy: string, + appSourcePath: string, + runtimeStack: string) { + core.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); + try { + let telemetryArg = `--env "CALLER_ID=azure-pipelines-rc-v1"`; + if (this.disableTelemetry) { + telemetryArg = `--env "ORYX_DISABLE_TELEMETRY=true"`; + } + await cpExec(`${PACK_CMD} build ${imageToDeploy} --path ${appSourcePath} --builder ${ORYX_BUILDER_IMAGE} --run-image mcr.microsoft.com/oryx/${runtimeStack} ${telemetryArg}`); + } catch (err) { + core.error(err.message); + throw err; + } + } + + /** + * Using a Dockerfile that was provided or found at the root of the application source, + * creates a runable application image. + * @param imageToDeploy - the name of the runnable application image that is created and can be later deployed + * @param appSourcePath - the path to the application source on the machine + * @param dockerfilePath - the path to the Dockerfile to build and tag with the provided image name + */ + public async createRunnableAppImageFromDockerfile( + imageToDeploy: string, + appSourcePath: string, + dockerfilePath: string) { + core.debug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + try { + const dockerTool = await io.which("docker", true); + await new Utility().executeAndthrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); + core.debug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + } catch (err) { + core.setFailed(err.message); + throw err; + } + } + + /** + * Determines the runtime stack to use for the runnable application image. + * @param appSourcePath - the path to the application source on the machine + * @returns a string representing the runtime stack that can be used for the Oryx MCR runtime images + */ + public async determineRuntimeStackAsync(appSourcePath: string): Promise { + core.debug('Attempting to determine the runtime stack needed for the provided application source'); + try { + const dockerTool: string = await io.which("docker", true); + // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file + await new Utility().executeAndthrowIfError(dockerTool, ['run', '--rm', '-v', `${appSourcePath}:/app`, `${ORYX_CLI_IMAGE}`, '/bin/bash', '-c', `oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt`]) + + // Read the temp file to get the runtime stack into a variable + const oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); + let command: string = `head -n 1 ${oryxRuntimeTxtPath}`; + if (IS_WINDOWS_AGENT) { + command = `Get-Content -Path ${oryxRuntimeTxtPath} -Head 1`; + } + + const runtimeStack = await new CommandHelper().execCommandAsync(command); + + // Delete the temp file + command = `rm ${oryxRuntimeTxtPath}`; + if (IS_WINDOWS_AGENT) { + command = `Remove-Item -Path ${oryxRuntimeTxtPath}`; + } + + await new CommandHelper().execCommandAsync(command); + + return runtimeStack; + } catch (err) { + core.setFailed(err.message); + throw err; + } + } + + /** + * Sets the default builder on the machine to the Oryx++ Builder to prevent an exception from being thrown due + * to no default builder set. + */ + public async setDefaultBuilder() { + core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); + try + { + await cpExec(`pack config default-builder ${ORYX_BUILDER_IMAGE}`); + } + catch (err) { + core.setFailed(err.message); + throw err; + } + } + + /** + * Installs the pack CLI that will be used to build a runnable application image. + * For more information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ + */ + public async installPackCliAsync() { + core.debug('Attempting to install the pack CLI'); + try { + let command: string = ''; + if (IS_WINDOWS_AGENT) { + const packZipDownloadUri: string = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; + const packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); + + command = `New-Item -ItemType Directory -Path ${PACK_CMD} -Force | Out-Null;` + + `Invoke-WebRequest -Uri ${packZipDownloadUri} -OutFile ${packZipDownloadFilePath}; ` + + `Expand-Archive -LiteralPath ${packZipDownloadFilePath} -DestinationPath ${PACK_CMD}; ` + + `Remove-Item -Path ${packZipDownloadFilePath}`; + } else { + const tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; + command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; + } + await new CommandHelper().execCommandAsync(command); + } catch (err) { + core.error(`Unable to install the pack CLI. Error: ${err.message}`); + core.setFailed(err.message); + throw err; + } + } +} \ No newline at end of file diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts new file mode 100644 index 00000000..367b2dfe --- /dev/null +++ b/src/ContainerRegistryHelper.ts @@ -0,0 +1,55 @@ +import * as core from '@actions/core'; +import * as exec from '@actions/exec'; +import * as io from '@actions/io'; +import { CommandHelper } from './CommandHelper'; +import { Utility } from './Utility'; + +export class ContainerRegistryHelper { + /** + * Authorizes Docker to make calls to the provided ACR instance using username and password. + * @param acrName - the name of the ACR instance to authenticate calls to + * @param acrUsername - the username for authentication + * @param acrPassword - the password for authentication + */ + public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { + core.debug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); + try { + await exec.exec('docker', [`login`, `--password-stdin`, `--username`, `${acrUsername}`, `${acrName}.azurecr.io`], { input: Buffer.from(acrPassword) }); + } catch (err) { + core.error(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); + throw err; + } + } + + /** + * Authorizes Docker to make calls to the provided ACR instance using an access token that is generated via + * the 'az acr login --expose-token' command. + * @param acrName - the name of the ACR instance to authenticate calls to. + */ + public async loginAcrWithAccessTokenAsync(acrName: string) { + core.debug(`Attempting to log in to ACR instance "${acrName}" with access token`); + try { + const command: string = `CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`; + await new CommandHelper().execCommandAsync(command); + } catch (err) { + core.error(`Failed to log in to ACR instance "${acrName}" with access token`) + throw err; + } + } + + /** + * Pushes an image to the ACR instance that was previously authenticated against. + * @param imageToPush - the name of the image to push to ACR + */ + public async pushImageToAcr(imageToPush: string) { + core.debug(`Attempting to push image "${imageToPush}" to ACR`); + try { + const dockerTool: string = await io.which("docker", true); + await new Utility().executeAndthrowIfError(dockerTool, [`push`, `${imageToPush}`]); + } catch (err) { + core.error(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); + core.setFailed(err.message); + throw err; + } + } +} \ No newline at end of file diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts new file mode 100644 index 00000000..e9dd9600 --- /dev/null +++ b/src/TelemetryHelper.ts @@ -0,0 +1,108 @@ +import * as core from '@actions/core'; +import { Utility } from './Utility'; +import * as io from '@actions/io'; + +const ORYX_CLI_IMAGE: string = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; + +const SUCCESSFUL_RESULT: string = "succeeded"; +const FAILED_RESULT: string = "failed"; + +const BUILDER_SCENARIO: string = "used-builder"; +const DOCKERFILE_SCENARIO: string = "used-dockerfile"; +const IMAGE_SCENARIO: string = "used-image"; + +const util = new Utility(); + +export class TelemetryHelper { + readonly disableTelemetry: boolean; + + private scenario: string; + private result: string; + private errorMessage: string; + private taskStartMilliseconds: number; + + constructor(disableTelemetry: boolean) { + this.disableTelemetry = disableTelemetry; + this.taskStartMilliseconds = Date.now(); + } + + /** + * Marks that the task was successful in telemetry. + */ + public setSuccessfulResult() { + this.result = SUCCESSFUL_RESULT; + } + + /** + * Marks that the task failed in telemetry. + */ + public setFailedResult(errorMessage: string) { + this.result = FAILED_RESULT; + this.errorMessage = errorMessage; + } + + /** + * Marks that the task used the builder scenario. + */ + public setBuilderScenario() { + this.scenario = BUILDER_SCENARIO; + } + + /** + * Marks that the task used the Dockerfile scenario. + */ + public setDockerfileScenario() { + this.scenario = DOCKERFILE_SCENARIO; + } + + /** + * Marks that the task used the previously built image scenario. + */ + public setImageScenario() { + this.scenario = IMAGE_SCENARIO; + } + + /** + * If telemetry is enabled, uses the "oryx telemetry" command to log metadata about this task execution. + */ + public async sendLogs() { + const taskLengthMilliseconds: number = Date.now() - this.taskStartMilliseconds; + if (!this.disableTelemetry) { + core.info(`Telemetry enabled; logging metadata about task result, length and scenario targeted.`); + try { + let resultArg: string = ''; + if (!util.isNullOrEmpty(this.result)) { + resultArg = `--property 'result=${this.result}'`; + } + + let scenarioArg: string = ''; + if (!util.isNullOrEmpty(this.scenario)) { + scenarioArg = `--property 'scenario=${this.scenario}'`; + } + + let errorMessageArg: string = ''; + if (!util.isNullOrEmpty(this.errorMessage)) { + errorMessageArg = `--property 'errorMessage=${this.errorMessage}'`; + } + + let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name 'ContainerAppsPipelinesTaskRCV1' ` + `--processing-time '${taskLengthMilliseconds}' ${resultArg} ${scenarioArg} ${errorMessageArg}"`]; + + // Don't use Utility's throwIfError() since it will still record an error in the pipeline logs, but won't fail the task + await executeDockerCommand(args, true) + } catch (err) { + core.warning(`Skipping telemetry logging due to the following exception: ${err.message}`); + } + } + } +} + +const executeDockerCommand = async (args: string[], continueOnError: boolean = false): Promise => { + try { + const dockerTool: string = await io.which("docker", true); + await new Utility().executeAndthrowIfError(dockerTool, args, continueOnError); + } + catch (err) { + core.setFailed(`Error: ${err.message}`); + throw err; // Re-throw the error + } +} \ No newline at end of file diff --git a/src/Utility.ts b/src/Utility.ts new file mode 100644 index 00000000..9f9fa0eb --- /dev/null +++ b/src/Utility.ts @@ -0,0 +1,58 @@ +import * as core from '@actions/core'; +import * as exec from '@actions/exec'; +import util = require('util'); +const cpExec = util.promisify(require('child_process').exec); +export class Utility { + /** + * @param commandLine - the command to execute + * @param args - the arguments to pass to the command + * @param continueOnError - whether or not to continue execution if the command fails + */ + + public async executeAndthrowIfError(commandLine: string, args: string[], continueOnError: boolean = false): Promise { + try { + let stdout = ''; + let stderr = ''; + + const options: exec.ExecOptions = { + listeners: { + stdout: (data: Buffer) => { + stdout += data.toString(); + core.info(data.toString()); + }, + stderr: (data: Buffer) => { + stderr += data.toString(); + core.error(data.toString()); + }, + }, + }; + + const exitCode = await exec.exec(commandLine, args, options); + + if (!continueOnError && exitCode !== 0) { + core.error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); + throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); + } + } catch (error) { + core.setFailed(`Error: ${error.message}`); + throw error; // Re-throw the error + } + } + + /** + * Sets the Azure CLI to dynamically install extensions that are missing. In this case, we care about the + * Azure Container Apps module being dynamically installed while it's still in preview. + */ + public async setAzureCliDynamicInstall() { + await cpExec(`az config set extension.use_dynamic_install=yes_without_prompt`); + } + + /** + * Checks whether or not the provided string is null, undefined or empty. + * @param str - the string to validate + * @returns true if the string is null, undefined or empty, false otherwise + */ + public isNullOrEmpty(str: string): boolean { + return str === null || str === undefined || str === ""; + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..27c1c391 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "target": "ES2016", + "module": "CommonJS", + "moduleResolution": "node", + "lib": ["es2018", "dom"], // Add any other required libraries + // ... + } +} From 7d220c530f7eca7e57b188c5d14326d724aeefe9 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 19 Sep 2023 16:55:15 -0700 Subject: [PATCH 02/42] Add step to delete container app env back --- .github/workflows/run-validation.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/run-validation.yml b/.github/workflows/run-validation.yml index 9495df46..42e26ffb 100644 --- a/.github/workflows/run-validation.yml +++ b/.github/workflows/run-validation.yml @@ -271,6 +271,11 @@ jobs: WORKSPACE_NAME=$(az monitor log-analytics workspace list -g ${{ vars.TEST_RESOURCE_GROUP_NAME }} --query '[?customerId == `${{ env.CUSTOMER_ID }}`].name | [0]') echo "WORKSPACE_NAME=${WORKSPACE_NAME}" >> $GITHUB_ENV + - name: Delete created Azure Container App environment + if: ${{ always() }} + shell: bash + run: az containerapp env delete -g ${{ vars.TEST_RESOURCE_GROUP_NAME }} -n ${{ env.TEST_NEW_CONTAINER_APP_ENV }} -y + - name: Delete created workspace if: ${{ always() }} shell: bash From 1c150f0f1a869a2bd4c26d5a2a196beef41927b6 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 19 Sep 2023 16:56:10 -0700 Subject: [PATCH 03/42] Remove workflow_dispatch --- .github/workflows/run-validation.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/run-validation.yml b/.github/workflows/run-validation.yml index 42e26ffb..efb5b534 100644 --- a/.github/workflows/run-validation.yml +++ b/.github/workflows/run-validation.yml @@ -1,7 +1,6 @@ name: Run validation on action on: - workflow_dispatch: push: branches: - main From 16a977bde70459017605a4d1379e627bbab61992 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 19 Sep 2023 17:12:24 -0700 Subject: [PATCH 04/42] Remove commented out code --- azurecontainerapps.ts | 3 --- dist/index.js | 6 ------ src/TelemetryHelper.ts | 1 - tsconfig.json | 3 +-- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index ba92c6eb..6ddd9dea 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -53,9 +53,6 @@ export class azurecontainerapps { core.setFailed(err.message); this.telemetryHelper.setFailedResult(err.message); } finally { - // Logout of Azure if logged in during this task session - // this.authHelper.logoutAzure(); - // If telemetry is enabled, will log metadata for this task run await this.telemetryHelper.sendLogs(); } diff --git a/dist/index.js b/dist/index.js index 6c495437..8466529d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -109,13 +109,9 @@ var azurecontainerapps = /** @class */ (function () { this.telemetryHelper.setFailedResult(err_1.message); return [3 /*break*/, 11]; case 9: - // Logout of Azure if logged in during this task session - // this.authHelper.logoutAzure(); // If telemetry is enabled, will log metadata for this task run return [4 /*yield*/, this.telemetryHelper.sendLogs()]; case 10: - // Logout of Azure if logged in during this task session - // this.authHelper.logoutAzure(); // If telemetry is enabled, will log metadata for this task run _a.sent(); return [7 /*endfinally*/]; @@ -5729,10 +5725,8 @@ var TelemetryHelper = /** @class */ (function () { errorMessageArg = "--property 'errorMessage=" + this.errorMessage + "'"; } args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name 'ContainerAppsPipelinesTaskRCV1' " + ("--processing-time '" + taskLengthMilliseconds + "' " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; - // Don't use Utility's throwIfError() since it will still record an error in the pipeline logs, but won't fail the task return [4 /*yield*/, executeDockerCommand(args, true)]; case 2: - // Don't use Utility's throwIfError() since it will still record an error in the pipeline logs, but won't fail the task _a.sent(); return [3 /*break*/, 4]; case 3: diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index e9dd9600..139b5086 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -87,7 +87,6 @@ export class TelemetryHelper { let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name 'ContainerAppsPipelinesTaskRCV1' ` + `--processing-time '${taskLengthMilliseconds}' ${resultArg} ${scenarioArg} ${errorMessageArg}"`]; - // Don't use Utility's throwIfError() since it will still record an error in the pipeline logs, but won't fail the task await executeDockerCommand(args, true) } catch (err) { core.warning(`Skipping telemetry logging due to the following exception: ${err.message}`); diff --git a/tsconfig.json b/tsconfig.json index 27c1c391..deab28d2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,6 @@ "target": "ES2016", "module": "CommonJS", "moduleResolution": "node", - "lib": ["es2018", "dom"], // Add any other required libraries - // ... + "lib": ["es2018", "dom"], } } From d7cb5903dd03e5e38b41040e3c85011936564d90 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 19 Sep 2023 17:25:05 -0700 Subject: [PATCH 05/42] Fix formating --- azurecontainerapps.ts | 40 +++---- src/ContainerAppHelper.ts | 185 ++++++++++++++++----------------- src/ContainerRegistryHelper.ts | 8 +- 3 files changed, 116 insertions(+), 117 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index 6ddd9dea..f80a61d0 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -105,7 +105,7 @@ export class azurecontainerapps { this.telemetryHelper = new TelemetryHelper(disableTelemetry); // Set up AzureAuthenticationHelper for managing logging in and out of Azure CLI using provided service connection - // this.authHelper = new AzureAuthenticationHelper(); + // this.authHelper = new AzureAuthenticationHelper(); // Set up ContainerAppHelper for managing calls around the Container App this.appHelper = new ContainerAppHelper(disableTelemetry); @@ -121,16 +121,16 @@ export class azurecontainerapps { private static validateSupportedScenarioArguments() { // Get the path to the application source to build and run, if provided - this.appSourcePath = core.getInput('appSourcePath', {required: false}); + this.appSourcePath = core.getInput('appSourcePath', { required: false }); // Get the name of the ACR instance to push images to, if provided - this.acrName = core.getInput('acrName', {required: false}); + this.acrName = core.getInput('acrName', { required: false }); // Get the previously built image to deploy, if provided - this.imageToDeploy = core.getInput('imageToDeploy', {required: false}); + this.imageToDeploy = core.getInput('imageToDeploy', { required: false }); // Get the YAML configuration file, if provided - this.yamlConfigPath = core.getInput('yamlConfigPath', {required: false}); + this.yamlConfigPath = core.getInput('yamlConfigPath', { required: false }); // Ensure that acrName is also provided if appSourcePath is provided if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { @@ -185,7 +185,7 @@ export class azurecontainerapps { * @returns The name of the Container App to use for the task. */ private static getContainerAppName(): string { - let containerAppName: string = core.getInput('containerAppName', {required: false}); + let containerAppName: string = core.getInput('containerAppName', { required: false }); if (util.isNullOrEmpty(containerAppName)) { containerAppName = `app-${this.buildId}-${this.buildNumber}`; @@ -204,7 +204,7 @@ export class azurecontainerapps { */ private static async getLocation(): Promise { // Set deployment location, if provided - let location: string = core.getInput('location', {required: false}); + let location: string = core.getInput('location', { required: false }); // If no location was provided, use the default location for the Container App service if (util.isNullOrEmpty(location)) { @@ -224,7 +224,7 @@ export class azurecontainerapps { */ private static async getOrCreateResourceGroup(containerAppName: string, location: string): Promise { // Get the resource group to deploy to if it was provided, or generate it from the Container App name - let resourceGroup: string = core.getInput('resourceGroup', {required: false}); + let resourceGroup: string = core.getInput('resourceGroup', { required: false }); if (util.isNullOrEmpty(resourceGroup)) { resourceGroup = `${containerAppName}-rg`; core.info(`Default resource group name: ${resourceGroup}`); @@ -254,7 +254,7 @@ export class azurecontainerapps { resourceGroup: string, location: string): Promise { // Get the Container App environment if it was provided - let containerAppEnvironment: string = core.getInput('containerAppEnvironment', {required: false}); + let containerAppEnvironment: string = core.getInput('containerAppEnvironment', { required: false }); // See if we can reuse an existing Container App environment found in the resource group if (util.isNullOrEmpty(containerAppEnvironment)) { @@ -284,8 +284,8 @@ export class azurecontainerapps { * Authenticates calls to the provided Azure Container Registry. */ private static async authenticateAzureContainerRegistryAsync() { - this.acrUsername = core.getInput('acrUsername', {required: false}); - this.acrPassword = core.getInput('acrPassword', {required: false}); + this.acrUsername = core.getInput('acrUsername', { required: false }); + this.acrPassword = core.getInput('acrPassword', { required: false }); // Login to ACR if credentials were provided if (!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword)) { @@ -310,7 +310,7 @@ export class azurecontainerapps { */ private static async buildAndPushImageAsync() { // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = core.getInput('imageToBuild', {required: false}); + this.imageToBuild = core.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { this.imageToBuild = `${this.acrName}.azurecr.io/ado-task/container-app:${this.buildId}.${this.buildNumber}`; core.info(`Default image to build: ${this.imageToBuild}`); @@ -323,7 +323,7 @@ export class azurecontainerapps { } // Get Dockerfile to build, if provided, or check if one exists at the root of the provided application - let dockerfilePath: string = core.getInput('dockerfilePath', {required: false}); + let dockerfilePath: string = core.getInput('dockerfilePath', { required: false }); if (util.isNullOrEmpty(dockerfilePath)) { core.info(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); const rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); @@ -358,7 +358,7 @@ export class azurecontainerapps { core.info(`Successfully installed the pack CLI.`) // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = core.getInput('runtimeStack', {required: false}); + this.runtimeStack = core.getInput('runtimeStack', { required: false }); if (util.isNullOrEmpty(this.runtimeStack)) { this.runtimeStack = await this.appHelper.determineRuntimeStackAsync(appSourcePath); core.info(`Runtime stack determined to be: ${this.runtimeStack}`); @@ -398,14 +398,14 @@ export class azurecontainerapps { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = core.getInput('ingress', {required: false}); - this.targetPort = core.getInput('targetPort', {required: false}); + this.ingress = core.getInput('ingress', { required: false }); + this.targetPort = core.getInput('targetPort', { required: false }); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. this.shouldUseUpdateCommand = this.containerAppExists && - util.isNullOrEmpty(this.targetPort) && - (util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); + util.isNullOrEmpty(this.targetPort) && + (util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); // Pass the ACR credentials when creating a Container App or updating a Container App via the 'up' command if (!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword) && @@ -435,7 +435,7 @@ export class azurecontainerapps { // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = core.getInput('targetPort', {required: false}); + this.targetPort = core.getInput('targetPort', { required: false }); if (util.isNullOrEmpty(this.targetPort)) { if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; @@ -459,7 +459,7 @@ export class azurecontainerapps { } } - const environmentVariables: string = core.getInput('environmentVariables', {required: false}); + const environmentVariables: string = core.getInput('environmentVariables', { required: false }); // Add user-specified environment variables if (!util.isNullOrEmpty(environmentVariables)) { diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 4a456b48..dfbf653d 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -27,23 +27,23 @@ export class ContainerAppHelper { * @param imageToDeploy - the name of the runnable application image that the Container App will be based from * @param optionalCmdArgs - a set of optional command line arguments */ - public async createContainerApp( + public async createContainerApp( containerAppName: string, resourceGroup: string, environment: string, imageToDeploy: string, optionalCmdArgs: string[]) { - core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); - try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; - optionalCmdArgs.forEach(function (val: string) { - command += ` ${val}`; - }); - await cpExec(`${command}`); - } catch (err) { - core.error(err.message); - throw err; - } + core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + try { + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; + optionalCmdArgs.forEach(function (val: string) { + command += ` ${val}`; + }); + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } } /** @@ -56,14 +56,14 @@ export class ContainerAppHelper { containerAppName: string, resourceGroup: string, yamlConfigPath: string) { - core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); - try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await cpExec(`${command}`); - } catch (err) { - core.error(err.message); - throw err; - } + core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + try { + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } } /** @@ -78,18 +78,18 @@ export class ContainerAppHelper { resourceGroup: string, imageToDeploy: string, optionalCmdArgs: string[]) { - core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); - try { - let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; - optionalCmdArgs.forEach(function (val: string) { - command += ` ${val}`; - }); - - await cpExec(`${command}`); - } catch (err) { - core.error(err.message); - throw err; - } + core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + try { + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + optionalCmdArgs.forEach(function (val: string) { + command += ` ${val}`; + }); + + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } } /** @@ -108,28 +108,28 @@ export class ContainerAppHelper { optionalCmdArgs: string[], ingress?: string, targetPort?: string) { - core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); - const util = new Utility(); - try { - let command = `az containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; - optionalCmdArgs.forEach(function (val: string) { - command += ` ${val}`; - }); - - if (!util.isNullOrEmpty(ingress)) { - command += ` --ingress ${ingress}`; - } - - if (!util.isNullOrEmpty(targetPort)) { - command += ` --target-port ${targetPort}`; - } - - await cpExec(`${command}`); - } catch (err) { - core.error(err.message); - throw err; + core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + const util = new Utility(); + try { + let command = `az containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + optionalCmdArgs.forEach(function (val: string) { + command += ` ${val}`; + }); + + if (!util.isNullOrEmpty(ingress)) { + command += ` --ingress ${ingress}`; + } + + if (!util.isNullOrEmpty(targetPort)) { + command += ` --target-port ${targetPort}`; } + + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; } + } /** * Updates an existing Azure Container App based from a YAML configuration file. @@ -141,14 +141,14 @@ export class ContainerAppHelper { containerAppName: string, resourceGroup: string, yamlConfigPath: string) { - core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); - try { - let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await cpExec(`${command}`); - } catch (err) { - core.error(err.message); - throw err; - } + core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + try { + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await cpExec(`${command}`); + } catch (err) { + core.error(err.message); + throw err; + } } /** @@ -161,7 +161,7 @@ export class ContainerAppHelper { core.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { const command = `az containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; - const {stdout, stderr} = await cpExec(`${command}`); + const { stdout, stderr } = await cpExec(`${command}`); return !stderr; } catch (err) { core.warning(err.message); @@ -179,7 +179,7 @@ export class ContainerAppHelper { core.debug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { const command = `az containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; - const {stdout, stderr} = await cpExec(`${command}`); + const { stdout, stderr } = await cpExec(`${command}`); return !stderr; } catch (err) { core.warning(err.message); @@ -196,7 +196,7 @@ export class ContainerAppHelper { core.debug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { const command = `az group show -n ${resourceGroup} -o none`; - const {stdout, stderr} = await cpExec(`${command}`); + const { stdout, stderr } = await cpExec(`${command}`); return !stderr; } catch (err) { core.warning(err.message); @@ -212,7 +212,7 @@ export class ContainerAppHelper { core.debug(`Attempting to get the default location for the Container App service for the subscription.`); try { const command = `az provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"` - const {stdout, stderr} = await cpExec(`${command}`); + const { stdout, stderr } = await cpExec(`${command}`); // If successful, strip out double quotes, spaces and parentheses from the first location returned return !stderr ? stdout.toLowerCase().replace(/["() ]/g, "") : `eastus2`; } catch (err) { @@ -247,7 +247,7 @@ export class ContainerAppHelper { core.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { const command = `az containerapp env list -g ${resourceGroup} --query [0].name"`; - const {stdout, stderr} = await cpExec(`${command}`); + const { stdout, stderr } = await cpExec(`${command}`); return !stderr ? stdout : null; } catch (err) { core.warning(err.message); @@ -321,17 +321,17 @@ export class ContainerAppHelper { imageToDeploy: string, appSourcePath: string, runtimeStack: string) { - core.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); - try { - let telemetryArg = `--env "CALLER_ID=azure-pipelines-rc-v1"`; - if (this.disableTelemetry) { - telemetryArg = `--env "ORYX_DISABLE_TELEMETRY=true"`; - } - await cpExec(`${PACK_CMD} build ${imageToDeploy} --path ${appSourcePath} --builder ${ORYX_BUILDER_IMAGE} --run-image mcr.microsoft.com/oryx/${runtimeStack} ${telemetryArg}`); - } catch (err) { - core.error(err.message); - throw err; + core.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); + try { + let telemetryArg = `--env "CALLER_ID=azure-pipelines-rc-v1"`; + if (this.disableTelemetry) { + telemetryArg = `--env "ORYX_DISABLE_TELEMETRY=true"`; } + await cpExec(`${PACK_CMD} build ${imageToDeploy} --path ${appSourcePath} --builder ${ORYX_BUILDER_IMAGE} --run-image mcr.microsoft.com/oryx/${runtimeStack} ${telemetryArg}`); + } catch (err) { + core.error(err.message); + throw err; + } } /** @@ -345,15 +345,15 @@ export class ContainerAppHelper { imageToDeploy: string, appSourcePath: string, dockerfilePath: string) { - core.debug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); - try { - const dockerTool = await io.which("docker", true); - await new Utility().executeAndthrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); - core.debug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); - } catch (err) { - core.setFailed(err.message); - throw err; - } + core.debug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + try { + const dockerTool = await io.which("docker", true); + await new Utility().executeAndthrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); + core.debug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + } catch (err) { + core.setFailed(err.message); + throw err; + } } /** @@ -361,7 +361,7 @@ export class ContainerAppHelper { * @param appSourcePath - the path to the application source on the machine * @returns a string representing the runtime stack that can be used for the Oryx MCR runtime images */ - public async determineRuntimeStackAsync(appSourcePath: string): Promise { + public async determineRuntimeStackAsync(appSourcePath: string): Promise { core.debug('Attempting to determine the runtime stack needed for the provided application source'); try { const dockerTool: string = await io.which("docker", true); @@ -396,10 +396,9 @@ export class ContainerAppHelper { * Sets the default builder on the machine to the Oryx++ Builder to prevent an exception from being thrown due * to no default builder set. */ - public async setDefaultBuilder() { + public async setDefaultBuilder() { core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); - try - { + try { await cpExec(`pack config default-builder ${ORYX_BUILDER_IMAGE}`); } catch (err) { @@ -412,7 +411,7 @@ export class ContainerAppHelper { * Installs the pack CLI that will be used to build a runnable application image. * For more information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ */ - public async installPackCliAsync() { + public async installPackCliAsync() { core.debug('Attempting to install the pack CLI'); try { let command: string = ''; @@ -421,13 +420,13 @@ export class ContainerAppHelper { const packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); command = `New-Item -ItemType Directory -Path ${PACK_CMD} -Force | Out-Null;` + - `Invoke-WebRequest -Uri ${packZipDownloadUri} -OutFile ${packZipDownloadFilePath}; ` + - `Expand-Archive -LiteralPath ${packZipDownloadFilePath} -DestinationPath ${PACK_CMD}; ` + - `Remove-Item -Path ${packZipDownloadFilePath}`; + `Invoke-WebRequest -Uri ${packZipDownloadUri} -OutFile ${packZipDownloadFilePath}; ` + + `Expand-Archive -LiteralPath ${packZipDownloadFilePath} -DestinationPath ${PACK_CMD}; ` + + `Remove-Item -Path ${packZipDownloadFilePath}`; } else { const tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + - 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; } await new CommandHelper().execCommandAsync(command); } catch (err) { diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 367b2dfe..9aeb0514 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -11,10 +11,10 @@ export class ContainerRegistryHelper { * @param acrUsername - the username for authentication * @param acrPassword - the password for authentication */ - public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { + public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { core.debug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); try { - await exec.exec('docker', [`login`, `--password-stdin`, `--username`, `${acrUsername}`, `${acrName}.azurecr.io`], { input: Buffer.from(acrPassword) }); + await exec.exec('docker', [`login`, `--password-stdin`, `--username`, `${acrUsername}`, `${acrName}.azurecr.io`], { input: Buffer.from(acrPassword) }); } catch (err) { core.error(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); throw err; @@ -26,7 +26,7 @@ export class ContainerRegistryHelper { * the 'az acr login --expose-token' command. * @param acrName - the name of the ACR instance to authenticate calls to. */ - public async loginAcrWithAccessTokenAsync(acrName: string) { + public async loginAcrWithAccessTokenAsync(acrName: string) { core.debug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { const command: string = `CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`; @@ -41,7 +41,7 @@ export class ContainerRegistryHelper { * Pushes an image to the ACR instance that was previously authenticated against. * @param imageToPush - the name of the image to push to ACR */ - public async pushImageToAcr(imageToPush: string) { + public async pushImageToAcr(imageToPush: string) { core.debug(`Attempting to push image "${imageToPush}" to ACR`); try { const dockerTool: string = await io.which("docker", true); From a0e5eff1c590234ed94c45c0c4581da038075811 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Wed, 20 Sep 2023 02:46:07 -0700 Subject: [PATCH 06/42] Update image name --- azurecontainerapps.ts | 2 +- dist/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index f80a61d0..6d93ba82 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -312,7 +312,7 @@ export class azurecontainerapps { // Get the name of the image to build if it was provided, or generate it from build variables this.imageToBuild = core.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = `${this.acrName}.azurecr.io/ado-task/container-app:${this.buildId}.${this.buildNumber}`; + this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.buildId}.${this.buildNumber}`; core.info(`Default image to build: ${this.imageToBuild}`); } diff --git a/dist/index.js b/dist/index.js index 8466529d..d70bc01b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -379,7 +379,7 @@ var azurecontainerapps = /** @class */ (function () { // Get the name of the image to build if it was provided, or generate it from build variables this.imageToBuild = core.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = this.acrName + ".azurecr.io/ado-task/container-app:" + this.buildId + "." + this.buildNumber; + this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.buildId + "." + this.buildNumber; core.info("Default image to build: " + this.imageToBuild); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' From 9c6f5d05ef6759c98ba0372159ef96e626aa6ac5 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 22 Sep 2023 15:19:52 -0700 Subject: [PATCH 07/42] Address PR comments --- azurecontainerapps.ts | 17 +- dist/index.js | 436 ++++++++++++-------------------------- dist/licenses.txt | 10 + package.json | 2 +- src/CommandHelper.ts | 89 -------- src/ContainerAppHelper.ts | 120 +++++------ src/TelemetryHelper.ts | 2 +- src/Utility.ts | 10 +- 8 files changed, 222 insertions(+), 464 deletions(-) delete mode 100644 src/CommandHelper.ts diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index 6d93ba82..47c1de10 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -58,9 +58,9 @@ export class azurecontainerapps { } } - // Azure DevOps build properties - private static buildId: string = process.env.GITHUB_RUN_ID; - private static buildNumber = process.env.GITHUB_RUN_NUMBER; + // GitHub Action properties + private static githubRunId: string = process.env.GITHUB_RUN_ID; + private static githubRunNumber = process.env.GITHUB_RUN_NUMBER; // Supported scenario properties private static appSourcePath: string; @@ -85,7 +85,6 @@ export class azurecontainerapps { // Helper properties private static telemetryHelper: TelemetryHelper; - //private static authHelper: AzureAuthenticationHelper; private static appHelper: ContainerAppHelper; private static registryHelper: ContainerRegistryHelper; @@ -104,9 +103,6 @@ export class azurecontainerapps { // Set up TelemetryHelper for managing telemetry calls this.telemetryHelper = new TelemetryHelper(disableTelemetry); - // Set up AzureAuthenticationHelper for managing logging in and out of Azure CLI using provided service connection - // this.authHelper = new AzureAuthenticationHelper(); - // Set up ContainerAppHelper for managing calls around the Container App this.appHelper = new ContainerAppHelper(disableTelemetry); @@ -141,6 +137,7 @@ export class azurecontainerapps { // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { core.error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); + throw Error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); } } @@ -181,13 +178,13 @@ export class azurecontainerapps { /** * Gets the name of the Container App to use for the task. If the 'containerAppName' argument is not provided, - * then a default name will be generated in the form 'ado-task-app--'. + * then a default name will be generated in the form 'gh-action-app--'. * @returns The name of the Container App to use for the task. */ private static getContainerAppName(): string { let containerAppName: string = core.getInput('containerAppName', { required: false }); if (util.isNullOrEmpty(containerAppName)) { - containerAppName = `app-${this.buildId}-${this.buildNumber}`; + containerAppName = `gh-action-app-${this.githubRunId}-${this.githubRunNumber}`; // Replace all '.' characters with '-' characters in the Container App name containerAppName = containerAppName.replace(/\./gi, "-"); @@ -312,7 +309,7 @@ export class azurecontainerapps { // Get the name of the image to build if it was provided, or generate it from build variables this.imageToBuild = core.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.buildId}.${this.buildNumber}`; + this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.githubRunId}.${this.githubRunNumber}`; core.info(`Default image to build: ${this.imageToBuild}`); } diff --git a/dist/index.js b/dist/index.js index d70bc01b..9bf3de2f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -127,8 +127,6 @@ var azurecontainerapps = /** @class */ (function () { azurecontainerapps.initializeHelpers = function (disableTelemetry) { // Set up TelemetryHelper for managing telemetry calls this.telemetryHelper = new TelemetryHelper_1.TelemetryHelper(disableTelemetry); - // Set up AzureAuthenticationHelper for managing logging in and out of Azure CLI using provided service connection - // this.authHelper = new AzureAuthenticationHelper(); // Set up ContainerAppHelper for managing calls around the Container App this.appHelper = new ContainerAppHelper_1.ContainerAppHelper(disableTelemetry); // Set up ContainerRegistryHelper for managing calls around ACR @@ -155,6 +153,7 @@ var azurecontainerapps = /** @class */ (function () { // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { core.error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); + throw Error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); } }; /** @@ -222,13 +221,13 @@ var azurecontainerapps = /** @class */ (function () { }; /** * Gets the name of the Container App to use for the task. If the 'containerAppName' argument is not provided, - * then a default name will be generated in the form 'ado-task-app--'. + * then a default name will be generated in the form 'gh-action-app--'. * @returns The name of the Container App to use for the task. */ azurecontainerapps.getContainerAppName = function () { var containerAppName = core.getInput('containerAppName', { required: false }); if (util.isNullOrEmpty(containerAppName)) { - containerAppName = "app-" + this.buildId + "-" + this.buildNumber; + containerAppName = "gh-action-app-" + this.githubRunId + "-" + this.githubRunNumber; // Replace all '.' characters with '-' characters in the Container App name containerAppName = containerAppName.replace(/\./gi, "-"); core.info("Default Container App name: " + containerAppName); @@ -379,7 +378,7 @@ var azurecontainerapps = /** @class */ (function () { // Get the name of the image to build if it was provided, or generate it from build variables this.imageToBuild = core.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.buildId + "." + this.buildNumber; + this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.githubRunId + "." + this.githubRunNumber; core.info("Default image to build: " + this.imageToBuild); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' @@ -625,9 +624,9 @@ var azurecontainerapps = /** @class */ (function () { }); }); }; - // Azure DevOps build properties - azurecontainerapps.buildId = process.env.GITHUB_RUN_ID; - azurecontainerapps.buildNumber = process.env.GITHUB_RUN_NUMBER; + // GitHub Action properties + azurecontainerapps.githubRunId = process.env.GITHUB_RUN_ID; + azurecontainerapps.githubRunNumber = process.env.GITHUB_RUN_NUMBER; return azurecontainerapps; }()); exports.azurecontainerapps = azurecontainerapps; @@ -4586,182 +4585,6 @@ function version(uuid) { var _default = version; exports["default"] = _default; -/***/ }), - -/***/ 1988: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -exports.__esModule = true; -exports.CommandHelper = void 0; -var os = __nccwpck_require__(2037); -var core = __nccwpck_require__(3195); -var exec = __nccwpck_require__(9714); -var CommandHelper = /** @class */ (function () { - function CommandHelper() { - } - /** - * Runs a command based on the OS of the agent running this task. - * @param command - the command to execute - * @returns the string output from the command - */ - CommandHelper.prototype.execCommandAsync = function (command) { - return __awaiter(this, void 0, void 0, function () { - var _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - if (!(os.platform() == 'win32')) return [3 /*break*/, 2]; - return [4 /*yield*/, this.execPwshCommandAsync(command)]; - case 1: - _a = _b.sent(); - return [3 /*break*/, 4]; - case 2: return [4 /*yield*/, this.execBashCommandAsync(command)]; - case 3: - _a = _b.sent(); - _b.label = 4; - case 4: return [2 /*return*/, _a]; - } - }); - }); - }; - /** - * @param command - the command to execute in Bash - * @returns the string output from the command - */ - CommandHelper.prototype.execBashCommandAsync = function (command) { - return __awaiter(this, void 0, void 0, function () { - var bashOutput, errorStream, options, exitCode, err_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - bashOutput = ''; - errorStream = ''; - options = { - listeners: { - stdout: function (data) { - bashOutput += data.toString(); - core.info(data.toString()); - }, - stderr: function (data) { - errorStream += data.toString(); - core.error(data.toString()); - } - }, - failOnStdErr: true, - ignoreReturnCode: false, - errStream: process.stderr, - outStream: process.stdout - }; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, exec.exec('bash', ['-c', command], options)]; - case 2: - exitCode = _a.sent(); - if (exitCode !== 0) { - throw new Error("Command failed with exit code " + exitCode + ". Error stream: " + errorStream); - } - return [2 /*return*/, bashOutput.trim()]; - case 3: - err_1 = _a.sent(); - core.setFailed(err_1.message); - throw err_1; - case 4: return [2 /*return*/]; - } - }); - }); - }; - /** - * Executes a given command using the pwsh executable. - * @param command - the command to execute in PowerShell - * @returns the string output from the command - */ - CommandHelper.prototype.execPwshCommandAsync = function (command) { - return __awaiter(this, void 0, void 0, function () { - var pwshOutput, errorStream, options, exitCode, err_2; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - pwshOutput = ''; - errorStream = ''; - options = { - listeners: { - stdout: function (data) { - pwshOutput += data.toString(); - core.info(data.toString()); - }, - stderr: function (data) { - errorStream += data.toString(); - core.error(data.toString()); - } - }, - failOnStdErr: true, - ignoreReturnCode: false, - errStream: process.stderr, - outStream: process.stdout - }; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, exec.exec('pwsh', [command], options)]; - case 2: - exitCode = _a.sent(); - if (exitCode !== 0) { - throw new Error("Command failed with exit code " + exitCode + ". Error stream: " + errorStream); - } - return [2 /*return*/, pwshOutput.trim()]; - case 3: - err_2 = _a.sent(); - core.setFailed(err_2.message); - throw err_2; - case 4: return [2 /*return*/]; - } - }); - }); - }; - return CommandHelper; -}()); -exports.CommandHelper = CommandHelper; - - /***/ }), /***/ 2929: @@ -4811,14 +4634,11 @@ var core = __nccwpck_require__(3195); var io = __nccwpck_require__(9529); var path = __nccwpck_require__(1017); var os = __nccwpck_require__(2037); -var CommandHelper_1 = __nccwpck_require__(1988); var Utility_1 = __nccwpck_require__(2135); -var util = __nccwpck_require__(3837); -var cpExec = util.promisify((__nccwpck_require__(2081).exec)); +var fs = __nccwpck_require__(7147); var ORYX_CLI_IMAGE = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; var ORYX_BUILDER_IMAGE = 'mcr.microsoft.com/oryx/builder:20230208.1'; var IS_WINDOWS_AGENT = os.platform() == 'win32'; -var PACK_CMD = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; var ContainerAppHelper = /** @class */ (function () { function ContainerAppHelper(disableTelemetry) { this.disableTelemetry = false; @@ -4842,11 +4662,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_1 = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; + command_1 = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, cpExec("" + command_1)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command_1.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4875,8 +4695,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, cpExec("" + command)]; + command = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4906,11 +4726,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_2 = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; + command_2 = "containerapp update -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; optionalCmdArgs.forEach(function (val) { command_2 += " " + val; }); - return [4 /*yield*/, cpExec("" + command_2)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command_2.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4943,7 +4763,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_3 = "az containerapp up -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; + command_3 = "containerapp up -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; optionalCmdArgs.forEach(function (val) { command_3 += " " + val; }); @@ -4953,7 +4773,7 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(targetPort)) { command_3 += " --target-port " + targetPort; } - return [4 /*yield*/, cpExec("" + command_3)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command_3.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4982,8 +4802,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, cpExec("" + command)]; + command = "containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5004,21 +4824,21 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesContainerAppExist = function (containerAppName, resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, _a, stdout, stderr, err_6; - return __generator(this, function (_b) { - switch (_b.label) { + var command, executionResult, err_6; + return __generator(this, function (_a) { + switch (_a.label) { case 0: core.debug("Attempting to determine if Container App with name \"" + containerAppName + "\" exists in resource group \"" + resourceGroup + "\""); - _b.label = 1; + _a.label = 1; case 1: - _b.trys.push([1, 3, , 4]); - command = "az containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, cpExec("" + command)]; + _a.trys.push([1, 3, , 4]); + command = "containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: - _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; - return [2 /*return*/, !stderr]; + executionResult = _a.sent(); + return [2 /*return*/, !executionResult.stderr]; case 3: - err_6 = _b.sent(); + err_6 = _a.sent(); core.warning(err_6.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; @@ -5034,21 +4854,21 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesContainerAppEnvironmentExist = function (containerAppEnvironment, resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, _a, stdout, stderr, err_7; - return __generator(this, function (_b) { - switch (_b.label) { + var command, executionResult, err_7; + return __generator(this, function (_a) { + switch (_a.label) { case 0: core.debug("Attempting to determine if Container App Environment with name \"" + containerAppEnvironment + "\" exists in resource group \"" + resourceGroup + "\""); - _b.label = 1; + _a.label = 1; case 1: - _b.trys.push([1, 3, , 4]); - command = "az containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, cpExec("" + command)]; + _a.trys.push([1, 3, , 4]); + command = "containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: - _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; - return [2 /*return*/, !stderr]; + executionResult = _a.sent(); + return [2 /*return*/, !executionResult.stderr]; case 3: - err_7 = _b.sent(); + err_7 = _a.sent(); core.warning(err_7.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; @@ -5063,21 +4883,21 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesResourceGroupExist = function (resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, _a, stdout, stderr, err_8; - return __generator(this, function (_b) { - switch (_b.label) { + var command, executionResult, err_8; + return __generator(this, function (_a) { + switch (_a.label) { case 0: core.debug("Attempting to determine if resource group \"" + resourceGroup + "\" exists"); - _b.label = 1; + _a.label = 1; case 1: - _b.trys.push([1, 3, , 4]); - command = "az group show -n " + resourceGroup + " -o none"; - return [4 /*yield*/, cpExec("" + command)]; + _a.trys.push([1, 3, , 4]); + command = "group show -n " + resourceGroup + " -o none"; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: - _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; - return [2 /*return*/, !stderr]; + executionResult = _a.sent(); + return [2 /*return*/, !executionResult.stderr]; case 3: - err_8 = _b.sent(); + err_8 = _a.sent(); core.warning(err_8.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; @@ -5091,22 +4911,22 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getDefaultContainerAppLocation = function () { return __awaiter(this, void 0, void 0, function () { - var command, _a, stdout, stderr, err_9; - return __generator(this, function (_b) { - switch (_b.label) { + var command, executionResult, err_9; + return __generator(this, function (_a) { + switch (_a.label) { case 0: core.debug("Attempting to get the default location for the Container App service for the subscription."); - _b.label = 1; + _a.label = 1; case 1: - _b.trys.push([1, 3, , 4]); - command = "az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; - return [4 /*yield*/, cpExec("" + command)]; + _a.trys.push([1, 3, , 4]); + command = "provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: - _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; + executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return [2 /*return*/, !stderr ? stdout.toLowerCase().replace(/["() ]/g, "") : "eastus2"]; + return [2 /*return*/, !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "") : "eastus2"]; case 3: - err_9 = _b.sent(); + err_9 = _a.sent(); core.warning(err_9.message); return [2 /*return*/, "eastus2"]; case 4: return [2 /*return*/]; @@ -5129,8 +4949,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az group create -n " + name + " -l " + location; - return [4 /*yield*/, cpExec("" + command)]; + command = "group create -n " + name + " -l " + location; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5150,21 +4970,21 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getExistingContainerAppEnvironment = function (resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, _a, stdout, stderr, err_11; - return __generator(this, function (_b) { - switch (_b.label) { + var command, executionResult, err_11; + return __generator(this, function (_a) { + switch (_a.label) { case 0: core.debug("Attempting to get the existing Container App Environment in resource group \"" + resourceGroup + "\""); - _b.label = 1; + _a.label = 1; case 1: - _b.trys.push([1, 3, , 4]); - command = "az containerapp env list -g " + resourceGroup + " --query [0].name\""; - return [4 /*yield*/, cpExec("" + command)]; + _a.trys.push([1, 3, , 4]); + command = "containerapp env list -g " + resourceGroup + " --query [0].name\""; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: - _a = _b.sent(), stdout = _a.stdout, stderr = _a.stderr; - return [2 /*return*/, !stderr ? stdout : null]; + executionResult = _a.sent(); + return [2 /*return*/, !executionResult.stderr ? executionResult.stdout : null]; case 3: - err_11 = _b.sent(); + err_11 = _a.sent(); core.warning(err_11.message); return [2 /*return*/, null]; case 4: return [2 /*return*/]; @@ -5189,11 +5009,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp env create -n " + name + " -g " + resourceGroup; + command = "containerapp env create -n " + name + " -g " + resourceGroup; if (!util.isNullOrEmpty(location)) { command += " -l " + location; } - return [4 /*yield*/, cpExec("" + command)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5221,8 +5041,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp ingress disable -n " + name + " -g " + resourceGroup; - return [4 /*yield*/, cpExec("" + command)]; + command = "containerapp ingress disable -n " + name + " -g " + resourceGroup; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5253,8 +5073,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; - return [4 /*yield*/, cpExec("" + command)]; + command = "containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5283,11 +5103,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - telemetryArg = "--env \"CALLER_ID=azure-pipelines-rc-v1\""; + telemetryArg = "--env \"CALLER_ID=github-actions-v1\""; if (this.disableTelemetry) { telemetryArg = "--env \"ORYX_DISABLE_TELEMETRY=true\""; } - return [4 /*yield*/, cpExec(PACK_CMD + " build " + imageToDeploy + " --path " + appSourcePath + " --builder " + ORYX_BUILDER_IMAGE + " --run-image mcr.microsoft.com/oryx/" + runtimeStack + " " + telemetryArg)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("pack", ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, "" + telemetryArg])]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5341,14 +5161,14 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.determineRuntimeStackAsync = function (appSourcePath) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, oryxRuntimeTxtPath, command, runtimeStack, err_17; + var dockerTool, oryxRuntimeTxtPath_1, runtimeStack, err_17; return __generator(this, function (_a) { switch (_a.label) { case 0: core.debug('Attempting to determine the runtime stack needed for the provided application source'); _a.label = 1; case 1: - _a.trys.push([1, 6, , 7]); + _a.trys.push([1, 4, , 5]); return [4 /*yield*/, io.which("docker", true)]; case 2: dockerTool = _a.sent(); @@ -5359,28 +5179,26 @@ var ContainerAppHelper = /** @class */ (function () { case 3: // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file _a.sent(); - oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); - command = "head -n 1 " + oryxRuntimeTxtPath; - if (IS_WINDOWS_AGENT) { - command = "Get-Content -Path " + oryxRuntimeTxtPath + " -Head 1"; - } - return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; - case 4: - runtimeStack = _a.sent(); + oryxRuntimeTxtPath_1 = path.join(appSourcePath, 'oryx-runtime.txt'); + runtimeStack = fs.promises.readFile(oryxRuntimeTxtPath_1, 'utf8').then(function (data) { + var lines = data.split('\n'); + return lines[0]; + })["catch"](function (err) { + core.setFailed(err.message); + throw err; + }); // Delete the temp file - command = "rm " + oryxRuntimeTxtPath; - if (IS_WINDOWS_AGENT) { - command = "Remove-Item -Path " + oryxRuntimeTxtPath; - } - return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; - case 5: - _a.sent(); + fs.unlink(oryxRuntimeTxtPath_1, function (err) { + if (err) { + core.warning("Unable to delete the temporary file \"" + oryxRuntimeTxtPath_1 + "\". Error: " + err.message); + } + }); return [2 /*return*/, runtimeStack]; - case 6: + case 4: err_17 = _a.sent(); core.setFailed(err_17.message); throw err_17; - case 7: return [2 /*return*/]; + case 5: return [2 /*return*/]; } }); }); @@ -5399,7 +5217,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, cpExec("pack config default-builder " + ORYX_BUILDER_IMAGE)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("pack", ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5418,38 +5236,41 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.installPackCliAsync = function () { return __awaiter(this, void 0, void 0, function () { - var command, packZipDownloadUri, packZipDownloadFilePath, tgzSuffix, err_19; + var downloadUrl, tgzSuffix, err_19; return __generator(this, function (_a) { switch (_a.label) { case 0: core.debug('Attempting to install the pack CLI'); _a.label = 1; case 1: - _a.trys.push([1, 3, , 4]); - command = ''; + _a.trys.push([1, 7, , 8]); + downloadUrl = ''; if (IS_WINDOWS_AGENT) { - packZipDownloadUri = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; - packZipDownloadFilePath = path.join(PACK_CMD, 'pack-windows.zip'); - command = "New-Item -ItemType Directory -Path " + PACK_CMD + " -Force | Out-Null;" + - ("Invoke-WebRequest -Uri " + packZipDownloadUri + " -OutFile " + packZipDownloadFilePath + "; ") + - ("Expand-Archive -LiteralPath " + packZipDownloadFilePath + " -DestinationPath " + PACK_CMD + "; ") + - ("Remove-Item -Path " + packZipDownloadFilePath); + downloadUrl = "https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip"; } else { tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = "(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + - 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; + downloadUrl = "https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz"; } - return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("curl", ["-L", "" + downloadUrl, "-o", "pack.zip"])]; case 2: _a.sent(); - return [3 /*break*/, 4]; + if (!IS_WINDOWS_AGENT) return [3 /*break*/, 4]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("tar", ["-xf", "pack.zip"])]; case 3: + _a.sent(); + return [3 /*break*/, 6]; + case 4: return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("unzip", ["pack.zip"])]; + case 5: + _a.sent(); + _a.label = 6; + case 6: return [3 /*break*/, 8]; + case 7: err_19 = _a.sent(); core.error("Unable to install the pack CLI. Error: " + err_19.message); core.setFailed(err_19.message); throw err_19; - case 4: return [2 /*return*/]; + case 8: return [2 /*return*/]; } }); }); @@ -5507,7 +5328,7 @@ exports.ContainerRegistryHelper = void 0; var core = __nccwpck_require__(3195); var exec = __nccwpck_require__(9714); var io = __nccwpck_require__(9529); -var CommandHelper_1 = __nccwpck_require__(1988); +var CommandHelper_1 = __nccwpck_require__(2433); var Utility_1 = __nccwpck_require__(2135); var ContainerRegistryHelper = /** @class */ (function () { function ContainerRegistryHelper() { @@ -5724,7 +5545,7 @@ var TelemetryHelper = /** @class */ (function () { if (!util.isNullOrEmpty(this.errorMessage)) { errorMessageArg = "--property 'errorMessage=" + this.errorMessage + "'"; } - args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name 'ContainerAppsPipelinesTaskRCV1' " + ("--processing-time '" + taskLengthMilliseconds + "' " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; + args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name 'ContainerAppsGitHubActionV1' " + ("--processing-time '" + taskLengthMilliseconds + "' " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; return [4 /*yield*/, executeDockerCommand(args, true)]; case 2: _a.sent(); @@ -5827,7 +5648,7 @@ var Utility = /** @class */ (function () { Utility.prototype.executeAndthrowIfError = function (commandLine, args, continueOnError) { if (continueOnError === void 0) { continueOnError = false; } return __awaiter(this, void 0, void 0, function () { - var stdout_1, stderr_1, options, exitCode, error_1; + var stdout_1, stderr_1, options, exitCode_1, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5848,12 +5669,19 @@ var Utility = /** @class */ (function () { }; return [4 /*yield*/, exec.exec(commandLine, args, options)]; case 1: - exitCode = _a.sent(); - if (!continueOnError && exitCode !== 0) { - core.error("Command failed with exit code " + exitCode + ". Error stream: " + stderr_1); - throw new Error("Command failed with exit code " + exitCode + ". Error stream: " + stderr_1); + exitCode_1 = _a.sent(); + if (!continueOnError && exitCode_1 !== 0) { + core.error("Command failed with exit code " + exitCode_1 + ". Error stream: " + stderr_1); + throw new Error("Command failed with exit code " + exitCode_1 + ". Error stream: " + stderr_1); } - return [3 /*break*/, 3]; + return [2 /*return*/, new Promise(function (resolve, reject) { + var executionResult = { + exitCode: exitCode_1, + stdout: stdout_1, + stderr: stderr_1 + }; + resolve(executionResult); + })]; case 2: error_1 = _a.sent(); core.setFailed("Error: " + error_1.message); @@ -5892,6 +5720,14 @@ var Utility = /** @class */ (function () { exports.Utility = Utility; +/***/ }), + +/***/ 2433: +/***/ ((module) => { + +module.exports = eval("require")("./CommandHelper"); + + /***/ }), /***/ 9491: diff --git a/dist/licenses.txt b/dist/licenses.txt index d7718469..cc497671 100644 --- a/dist/licenses.txt +++ b/dist/licenses.txt @@ -59,6 +59,16 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +@vercel/ncc +MIT +Copyright 2018 ZEIT, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + tunnel MIT The MIT License (MIT) diff --git a/package.json b/package.json index a80a3598..6b9c3dc4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "container-apps-deploy-action", "version": "1.0.0", - "description": "This action allows users to easily deploy their application source to an\r [Azure Container App](https://azure.microsoft.com/en-us/services/container-apps/) in their GitHub workflow by either\r providing a previously built image, a Dockerfile that an image can be built from, or using a builder to create a\r runnable application image for the user.", + "description": "This action allows users to easily deploy their application source to an [Azure Container App](https://azure.microsoft.com/en-us/services/container-apps/) in their GitHub workflow by either providing a previously built image, a Dockerfile that an image can be built from, or using a builder to create a runnable application image for the user.", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" diff --git a/src/CommandHelper.ts b/src/CommandHelper.ts deleted file mode 100644 index 5b23649e..00000000 --- a/src/CommandHelper.ts +++ /dev/null @@ -1,89 +0,0 @@ -import * as os from 'os' -import * as core from '@actions/core'; -import * as exec from '@actions/exec'; - -export class CommandHelper { - - /** - * Runs a command based on the OS of the agent running this task. - * @param command - the command to execute - * @returns the string output from the command - */ - public async execCommandAsync(command: string): Promise { - return os.platform() == 'win32' ? - await this.execPwshCommandAsync(command) : - await this.execBashCommandAsync(command); - } - - /** - * @param command - the command to execute in Bash - * @returns the string output from the command - */ - private async execBashCommandAsync(command: string): Promise { - var bashOutput: string = ''; - var errorStream: string = ''; - - const options: any = { - listeners: { - stdout: (data: Buffer) => { - bashOutput += data.toString(); - core.info(data.toString()); - }, - stderr: (data: Buffer) => { - errorStream += data.toString(); - core.error(data.toString()); - } - }, - failOnStdErr: true, - ignoreReturnCode: false, - errStream: process.stderr, - outStream: process.stdout, - } - try { - var exitCode = await exec.exec('bash', ['-c', command], options); - if (exitCode !== 0) { - throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${errorStream}`); - } - return bashOutput.trim(); - } catch (err) { - core.setFailed(err.message); - throw err; - } - } - - /** - * Executes a given command using the pwsh executable. - * @param command - the command to execute in PowerShell - * @returns the string output from the command - */ - private async execPwshCommandAsync(command: string): Promise { - var pwshOutput: string = ''; - var errorStream: string = ''; - const options: any = { - listeners: { - stdout: (data: Buffer) => { - pwshOutput += data.toString(); - core.info(data.toString()); - }, - stderr: (data: Buffer) => { - errorStream += data.toString(); - core.error(data.toString()); - } - }, - failOnStdErr: true, - ignoreReturnCode: false, - errStream: process.stderr, - outStream: process.stdout, - } - try { - var exitCode = await exec.exec('pwsh', [command], options); - if (exitCode !== 0) { - throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${errorStream}`); - } - return pwshOutput.trim(); - } catch (err) { - core.setFailed(err.message); - throw err; - } - } -} \ No newline at end of file diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index dfbf653d..28e85ea6 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -2,15 +2,12 @@ import * as core from '@actions/core'; import * as io from '@actions/io'; import * as path from 'path'; import * as os from 'os'; -import { CommandHelper } from './CommandHelper'; import { Utility } from './Utility'; -import util = require('util'); -const cpExec = util.promisify(require('child_process').exec); +import fs = require('fs'); const ORYX_CLI_IMAGE: string = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; const ORYX_BUILDER_IMAGE: string = 'mcr.microsoft.com/oryx/builder:20230208.1'; const IS_WINDOWS_AGENT: boolean = os.platform() == 'win32'; -const PACK_CMD: string = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; export class ContainerAppHelper { readonly disableTelemetry: boolean = false; @@ -35,11 +32,11 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; + let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await cpExec(`${command}`); + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -58,8 +55,8 @@ export class ContainerAppHelper { yamlConfigPath: string) { core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await cpExec(`${command}`); + let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -80,12 +77,12 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await cpExec(`${command}`); + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -111,7 +108,7 @@ export class ContainerAppHelper { core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); const util = new Utility(); try { - let command = `az containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + let command = `containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); @@ -124,7 +121,7 @@ export class ContainerAppHelper { command += ` --target-port ${targetPort}`; } - await cpExec(`${command}`); + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -143,8 +140,8 @@ export class ContainerAppHelper { yamlConfigPath: string) { core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await cpExec(`${command}`); + let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -160,9 +157,9 @@ export class ContainerAppHelper { public async doesContainerAppExist(containerAppName: string, resourceGroup: string): Promise { core.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { - const command = `az containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; - const { stdout, stderr } = await cpExec(`${command}`); - return !stderr; + const command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; + const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + return !executionResult.stderr; } catch (err) { core.warning(err.message); return false; @@ -178,9 +175,9 @@ export class ContainerAppHelper { public async doesContainerAppEnvironmentExist(containerAppEnvironment: string, resourceGroup: string): Promise { core.debug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { - const command = `az containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; - const { stdout, stderr } = await cpExec(`${command}`); - return !stderr; + const command = `containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; + const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + return !executionResult.stderr; } catch (err) { core.warning(err.message); return false; @@ -195,9 +192,9 @@ export class ContainerAppHelper { public async doesResourceGroupExist(resourceGroup: string): Promise { core.debug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { - const command = `az group show -n ${resourceGroup} -o none`; - const { stdout, stderr } = await cpExec(`${command}`); - return !stderr; + const command = `group show -n ${resourceGroup} -o none`; + const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + return !executionResult.stderr; } catch (err) { core.warning(err.message); return false; @@ -211,10 +208,10 @@ export class ContainerAppHelper { public async getDefaultContainerAppLocation(): Promise { core.debug(`Attempting to get the default location for the Container App service for the subscription.`); try { - const command = `az provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"` - const { stdout, stderr } = await cpExec(`${command}`); + const command = `provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"` + const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return !stderr ? stdout.toLowerCase().replace(/["() ]/g, "") : `eastus2`; + return !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "") : `eastus2`; } catch (err) { core.warning(err.message); return `eastus2`; @@ -229,8 +226,8 @@ export class ContainerAppHelper { public async createResourceGroup(name: string, location: string) { core.debug(`Attempting to create resource group "${name}" in location "${location}"`); try { - const command = `az group create -n ${name} -l ${location}`; - await cpExec(`${command}`); + const command = `group create -n ${name} -l ${location}`; + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); @@ -246,9 +243,9 @@ export class ContainerAppHelper { public async getExistingContainerAppEnvironment(resourceGroup: string) { core.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { - const command = `az containerapp env list -g ${resourceGroup} --query [0].name"`; - const { stdout, stderr } = await cpExec(`${command}`); - return !stderr ? stdout : null; + const command = `containerapp env list -g ${resourceGroup} --query [0].name"`; + const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + return !executionResult.stderr ? executionResult.stdout : null; } catch (err) { core.warning(err.message); return null; @@ -265,11 +262,11 @@ export class ContainerAppHelper { const util = new Utility(); core.debug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); try { - let command = `az containerapp env create -n ${name} -g ${resourceGroup}`; + let command = `containerapp env create -n ${name} -g ${resourceGroup}`; if (!util.isNullOrEmpty(location)) { command += ` -l ${location}`; } - await cpExec(`${command}`); + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -284,8 +281,8 @@ export class ContainerAppHelper { public async disableContainerAppIngress(name: string, resourceGroup: string) { core.debug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); try { - const command = `az containerapp ingress disable -n ${name} -g ${resourceGroup}`; - await cpExec(`${command}`); + const command = `containerapp ingress disable -n ${name} -g ${resourceGroup}`; + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -303,8 +300,8 @@ export class ContainerAppHelper { public async updateContainerAppRegistryDetails(name: string, resourceGroup: string, acrName: string, acrUsername: string, acrPassword: string) { core.debug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { - const command = `az containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; - await cpExec(`${command}`); + const command = `containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; + await new Utility().executeAndthrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -323,11 +320,11 @@ export class ContainerAppHelper { runtimeStack: string) { core.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); try { - let telemetryArg = `--env "CALLER_ID=azure-pipelines-rc-v1"`; + let telemetryArg = `--env "CALLER_ID=github-actions-v1"`; if (this.disableTelemetry) { telemetryArg = `--env "ORYX_DISABLE_TELEMETRY=true"`; } - await cpExec(`${PACK_CMD} build ${imageToDeploy} --path ${appSourcePath} --builder ${ORYX_BUILDER_IMAGE} --run-image mcr.microsoft.com/oryx/${runtimeStack} ${telemetryArg}`); + await new Utility().executeAndthrowIfError(`pack`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, `${telemetryArg}`]); } catch (err) { core.error(err.message); throw err; @@ -370,20 +367,21 @@ export class ContainerAppHelper { // Read the temp file to get the runtime stack into a variable const oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); - let command: string = `head -n 1 ${oryxRuntimeTxtPath}`; - if (IS_WINDOWS_AGENT) { - command = `Get-Content -Path ${oryxRuntimeTxtPath} -Head 1`; - } - const runtimeStack = await new CommandHelper().execCommandAsync(command); + const runtimeStack = fs.promises.readFile(oryxRuntimeTxtPath, 'utf8').then((data) => { + const lines = data.split('\n'); + return lines[0]; + }).catch((err) => { + core.setFailed(err.message); + throw err; + }); // Delete the temp file - command = `rm ${oryxRuntimeTxtPath}`; - if (IS_WINDOWS_AGENT) { - command = `Remove-Item -Path ${oryxRuntimeTxtPath}`; - } - - await new CommandHelper().execCommandAsync(command); + fs.unlink(oryxRuntimeTxtPath, (err) => { + if (err) { + core.warning(`Unable to delete the temporary file "${oryxRuntimeTxtPath}". Error: ${err.message}`); + } + }); return runtimeStack; } catch (err) { @@ -399,7 +397,7 @@ export class ContainerAppHelper { public async setDefaultBuilder() { core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { - await cpExec(`pack config default-builder ${ORYX_BUILDER_IMAGE}`); + await new Utility().executeAndthrowIfError(`pack`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); } catch (err) { core.setFailed(err.message); @@ -414,21 +412,19 @@ export class ContainerAppHelper { public async installPackCliAsync() { core.debug('Attempting to install the pack CLI'); try { - let command: string = ''; + let downloadUrl: string = ''; if (IS_WINDOWS_AGENT) { - const packZipDownloadUri: string = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; - const packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); - - command = `New-Item -ItemType Directory -Path ${PACK_CMD} -Force | Out-Null;` + - `Invoke-WebRequest -Uri ${packZipDownloadUri} -OutFile ${packZipDownloadFilePath}; ` + - `Expand-Archive -LiteralPath ${packZipDownloadFilePath} -DestinationPath ${PACK_CMD}; ` + - `Remove-Item -Path ${packZipDownloadFilePath}`; + downloadUrl = `https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip` } else { const tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + - 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; + downloadUrl = `https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz`; + } + await new Utility().executeAndthrowIfError(`curl`, [`-L`, `${downloadUrl}`, `-o`, `pack.zip`]); + if (IS_WINDOWS_AGENT) { + await new Utility().executeAndthrowIfError(`tar`, [`-xf`, `pack.zip`]); + } else { + await new Utility().executeAndthrowIfError(`unzip`, [`pack.zip`]); } - await new CommandHelper().execCommandAsync(command); } catch (err) { core.error(`Unable to install the pack CLI. Error: ${err.message}`); core.setFailed(err.message); diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 139b5086..4d9d75b3 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -85,7 +85,7 @@ export class TelemetryHelper { errorMessageArg = `--property 'errorMessage=${this.errorMessage}'`; } - let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name 'ContainerAppsPipelinesTaskRCV1' ` + `--processing-time '${taskLengthMilliseconds}' ${resultArg} ${scenarioArg} ${errorMessageArg}"`]; + let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name 'ContainerAppsGitHubActionV1' ` + `--processing-time '${taskLengthMilliseconds}' ${resultArg} ${scenarioArg} ${errorMessageArg}"`]; await executeDockerCommand(args, true) } catch (err) { diff --git a/src/Utility.ts b/src/Utility.ts index 9f9fa0eb..8279f0ef 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -9,7 +9,7 @@ export class Utility { * @param continueOnError - whether or not to continue execution if the command fails */ - public async executeAndthrowIfError(commandLine: string, args: string[], continueOnError: boolean = false): Promise { + public async executeAndthrowIfError(commandLine: string, args: string[], continueOnError: boolean = false) : Promise<{exitCode:number, stdout:string, stderr:string}> { try { let stdout = ''; let stderr = ''; @@ -33,6 +33,14 @@ export class Utility { core.error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); } + return new Promise((resolve, reject) => { + const executionResult = { + exitCode: exitCode, + stdout: stdout, + stderr: stderr + } + resolve(executionResult); + }); } catch (error) { core.setFailed(`Error: ${error.message}`); throw error; // Re-throw the error From 9c829f2abddba6de3ee5542151ddf1b7f212d1ff Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 22 Sep 2023 15:36:59 -0700 Subject: [PATCH 08/42] Remove reference to Command Helper --- dist/index.js | 299 ++++++++++++++++----------------- dist/licenses.txt | 10 -- src/ContainerRegistryHelper.ts | 5 +- 3 files changed, 149 insertions(+), 165 deletions(-) diff --git a/dist/index.js b/dist/index.js index 9bf3de2f..211944de 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,7 +1,7 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 3238: +/***/ 238: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -44,13 +44,13 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.azurecontainerapps = void 0; -var core = __nccwpck_require__(3195); -var fs = __nccwpck_require__(7147); -var path = __nccwpck_require__(1017); -var ContainerAppHelper_1 = __nccwpck_require__(2929); -var ContainerRegistryHelper_1 = __nccwpck_require__(4769); -var TelemetryHelper_1 = __nccwpck_require__(7166); -var Utility_1 = __nccwpck_require__(2135); +var core = __nccwpck_require__(195); +var fs = __nccwpck_require__(147); +var path = __nccwpck_require__(822); +var ContainerAppHelper_1 = __nccwpck_require__(929); +var ContainerRegistryHelper_1 = __nccwpck_require__(769); +var TelemetryHelper_1 = __nccwpck_require__(166); +var Utility_1 = __nccwpck_require__(135); var util = new Utility_1.Utility(); var azurecontainerapps = /** @class */ (function () { function azurecontainerapps() { @@ -635,7 +635,7 @@ azurecontainerapps.runMain(); /***/ }), -/***/ 5688: +/***/ 688: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -661,7 +661,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.issue = exports.issueCommand = void 0; -const os = __importStar(__nccwpck_require__(2037)); +const os = __importStar(__nccwpck_require__(37)); const utils_1 = __nccwpck_require__(869); /** * Commands @@ -734,7 +734,7 @@ function escapeProperty(s) { /***/ }), -/***/ 3195: +/***/ 195: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -769,12 +769,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(5688); -const file_command_1 = __nccwpck_require__(3930); +const command_1 = __nccwpck_require__(688); +const file_command_1 = __nccwpck_require__(930); const utils_1 = __nccwpck_require__(869); -const os = __importStar(__nccwpck_require__(2037)); -const path = __importStar(__nccwpck_require__(1017)); -const oidc_utils_1 = __nccwpck_require__(1755); +const os = __importStar(__nccwpck_require__(37)); +const path = __importStar(__nccwpck_require__(822)); +const oidc_utils_1 = __nccwpck_require__(755); /** * The code to exit an action */ @@ -1059,12 +1059,12 @@ exports.getIDToken = getIDToken; /** * Summary exports */ -var summary_1 = __nccwpck_require__(8606); +var summary_1 = __nccwpck_require__(606); Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); /** * @deprecated use core.summary */ -var summary_2 = __nccwpck_require__(8606); +var summary_2 = __nccwpck_require__(606); Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); /** * Path exports @@ -1077,7 +1077,7 @@ Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: funct /***/ }), -/***/ 3930: +/***/ 930: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1106,9 +1106,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__nccwpck_require__(7147)); -const os = __importStar(__nccwpck_require__(2037)); -const uuid_1 = __nccwpck_require__(5814); +const fs = __importStar(__nccwpck_require__(147)); +const os = __importStar(__nccwpck_require__(37)); +const uuid_1 = __nccwpck_require__(814); const utils_1 = __nccwpck_require__(869); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; @@ -1142,7 +1142,7 @@ exports.prepareKeyValueMessage = prepareKeyValueMessage; /***/ }), -/***/ 1755: +/***/ 755: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1158,9 +1158,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(9780); -const auth_1 = __nccwpck_require__(8833); -const core_1 = __nccwpck_require__(3195); +const http_client_1 = __nccwpck_require__(780); +const auth_1 = __nccwpck_require__(833); +const core_1 = __nccwpck_require__(195); class OidcClient { static createHttpClient(allowRetry = true, maxRetry = 10) { const requestOptions = { @@ -1252,7 +1252,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; -const path = __importStar(__nccwpck_require__(1017)); +const path = __importStar(__nccwpck_require__(822)); /** * toPosixPath converts the given path to the posix form. On Windows, \\ will be * replaced with /. @@ -1291,7 +1291,7 @@ exports.toPlatformPath = toPlatformPath; /***/ }), -/***/ 8606: +/***/ 606: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1307,8 +1307,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; -const os_1 = __nccwpck_require__(2037); -const fs_1 = __nccwpck_require__(7147); +const os_1 = __nccwpck_require__(37); +const fs_1 = __nccwpck_require__(147); const { access, appendFile, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; @@ -1628,7 +1628,7 @@ exports.toCommandProperties = toCommandProperties; /***/ }), -/***/ 9714: +/***/ 714: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1663,8 +1663,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getExecOutput = exports.exec = void 0; -const string_decoder_1 = __nccwpck_require__(1576); -const tr = __importStar(__nccwpck_require__(5315)); +const string_decoder_1 = __nccwpck_require__(576); +const tr = __importStar(__nccwpck_require__(315)); /** * Exec a command. * Output will be streamed to the live console. @@ -1738,7 +1738,7 @@ exports.getExecOutput = getExecOutput; /***/ }), -/***/ 5315: +/***/ 315: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1773,13 +1773,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.argStringToArray = exports.ToolRunner = void 0; -const os = __importStar(__nccwpck_require__(2037)); -const events = __importStar(__nccwpck_require__(2361)); -const child = __importStar(__nccwpck_require__(2081)); -const path = __importStar(__nccwpck_require__(1017)); -const io = __importStar(__nccwpck_require__(9529)); -const ioUtil = __importStar(__nccwpck_require__(7821)); -const timers_1 = __nccwpck_require__(9512); +const os = __importStar(__nccwpck_require__(37)); +const events = __importStar(__nccwpck_require__(361)); +const child = __importStar(__nccwpck_require__(81)); +const path = __importStar(__nccwpck_require__(822)); +const io = __importStar(__nccwpck_require__(529)); +const ioUtil = __importStar(__nccwpck_require__(821)); +const timers_1 = __nccwpck_require__(512); /* eslint-disable @typescript-eslint/unbound-method */ const IS_WINDOWS = process.platform === 'win32'; /* @@ -2363,7 +2363,7 @@ class ExecState extends events.EventEmitter { /***/ }), -/***/ 8833: +/***/ 833: /***/ (function(__unused_webpack_module, exports) { "use strict"; @@ -2451,7 +2451,7 @@ exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHand /***/ }), -/***/ 9780: +/***/ 780: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -2487,10 +2487,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; -const http = __importStar(__nccwpck_require__(3685)); -const https = __importStar(__nccwpck_require__(5687)); -const pm = __importStar(__nccwpck_require__(4492)); -const tunnel = __importStar(__nccwpck_require__(9041)); +const http = __importStar(__nccwpck_require__(685)); +const https = __importStar(__nccwpck_require__(687)); +const pm = __importStar(__nccwpck_require__(492)); +const tunnel = __importStar(__nccwpck_require__(41)); var HttpCodes; (function (HttpCodes) { HttpCodes[HttpCodes["OK"] = 200] = "OK"; @@ -3076,7 +3076,7 @@ const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCa /***/ }), -/***/ 4492: +/***/ 492: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -3165,7 +3165,7 @@ function isLoopbackAddress(host) { /***/ }), -/***/ 7821: +/***/ 821: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -3201,8 +3201,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge var _a; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; -const fs = __importStar(__nccwpck_require__(7147)); -const path = __importStar(__nccwpck_require__(1017)); +const fs = __importStar(__nccwpck_require__(147)); +const path = __importStar(__nccwpck_require__(822)); _a = fs.promises // export const {open} = 'fs' , exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; @@ -3355,7 +3355,7 @@ exports.getCmdPath = getCmdPath; /***/ }), -/***/ 9529: +/***/ 529: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -3390,9 +3390,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; -const assert_1 = __nccwpck_require__(9491); -const path = __importStar(__nccwpck_require__(1017)); -const ioUtil = __importStar(__nccwpck_require__(7821)); +const assert_1 = __nccwpck_require__(491); +const path = __importStar(__nccwpck_require__(822)); +const ioUtil = __importStar(__nccwpck_require__(821)); /** * Copies a file or folder. * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js @@ -3661,27 +3661,27 @@ function copyFile(srcFile, destFile, force) { /***/ }), -/***/ 9041: +/***/ 41: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = __nccwpck_require__(7111); +module.exports = __nccwpck_require__(111); /***/ }), -/***/ 7111: +/***/ 111: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; -var net = __nccwpck_require__(1808); -var tls = __nccwpck_require__(4404); -var http = __nccwpck_require__(3685); -var https = __nccwpck_require__(5687); -var events = __nccwpck_require__(2361); -var assert = __nccwpck_require__(9491); -var util = __nccwpck_require__(3837); +var net = __nccwpck_require__(808); +var tls = __nccwpck_require__(404); +var http = __nccwpck_require__(685); +var https = __nccwpck_require__(687); +var events = __nccwpck_require__(361); +var assert = __nccwpck_require__(491); +var util = __nccwpck_require__(837); exports.httpOverHttp = httpOverHttp; @@ -3941,7 +3941,7 @@ exports.debug = debug; // for test /***/ }), -/***/ 5814: +/***/ 814: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4005,29 +4005,29 @@ Object.defineProperty(exports, "parse", ({ } })); -var _v = _interopRequireDefault(__nccwpck_require__(6471)); +var _v = _interopRequireDefault(__nccwpck_require__(471)); -var _v2 = _interopRequireDefault(__nccwpck_require__(3384)); +var _v2 = _interopRequireDefault(__nccwpck_require__(384)); -var _v3 = _interopRequireDefault(__nccwpck_require__(5940)); +var _v3 = _interopRequireDefault(__nccwpck_require__(940)); -var _v4 = _interopRequireDefault(__nccwpck_require__(9193)); +var _v4 = _interopRequireDefault(__nccwpck_require__(193)); -var _nil = _interopRequireDefault(__nccwpck_require__(8654)); +var _nil = _interopRequireDefault(__nccwpck_require__(654)); -var _version = _interopRequireDefault(__nccwpck_require__(2362)); +var _version = _interopRequireDefault(__nccwpck_require__(362)); -var _validate = _interopRequireDefault(__nccwpck_require__(9815)); +var _validate = _interopRequireDefault(__nccwpck_require__(815)); -var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(183)); -var _parse = _interopRequireDefault(__nccwpck_require__(5108)); +var _parse = _interopRequireDefault(__nccwpck_require__(108)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), -/***/ 9313: +/***/ 313: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4038,7 +4038,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4057,7 +4057,7 @@ exports["default"] = _default; /***/ }), -/***/ 8654: +/***/ 654: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -4072,7 +4072,7 @@ exports["default"] = _default; /***/ }), -/***/ 5108: +/***/ 108: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4083,7 +4083,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(9815)); +var _validate = _interopRequireDefault(__nccwpck_require__(815)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4124,7 +4124,7 @@ exports["default"] = _default; /***/ }), -/***/ 1629: +/***/ 629: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -4139,7 +4139,7 @@ exports["default"] = _default; /***/ }), -/***/ 9271: +/***/ 271: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4150,7 +4150,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = rng; -var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4170,7 +4170,7 @@ function rng() { /***/ }), -/***/ 2017: +/***/ 17: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4181,7 +4181,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4200,7 +4200,7 @@ exports["default"] = _default; /***/ }), -/***/ 5183: +/***/ 183: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4211,7 +4211,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(9815)); +var _validate = _interopRequireDefault(__nccwpck_require__(815)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4246,7 +4246,7 @@ exports["default"] = _default; /***/ }), -/***/ 6471: +/***/ 471: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4257,9 +4257,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(9271)); +var _rng = _interopRequireDefault(__nccwpck_require__(271)); -var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(183)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4360,7 +4360,7 @@ exports["default"] = _default; /***/ }), -/***/ 3384: +/***/ 384: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4371,9 +4371,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(5717)); +var _v = _interopRequireDefault(__nccwpck_require__(717)); -var _md = _interopRequireDefault(__nccwpck_require__(9313)); +var _md = _interopRequireDefault(__nccwpck_require__(313)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4383,7 +4383,7 @@ exports["default"] = _default; /***/ }), -/***/ 5717: +/***/ 717: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4395,9 +4395,9 @@ Object.defineProperty(exports, "__esModule", ({ exports["default"] = _default; exports.URL = exports.DNS = void 0; -var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(183)); -var _parse = _interopRequireDefault(__nccwpck_require__(5108)); +var _parse = _interopRequireDefault(__nccwpck_require__(108)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4468,7 +4468,7 @@ function _default(name, version, hashfunc) { /***/ }), -/***/ 5940: +/***/ 940: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4479,9 +4479,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(9271)); +var _rng = _interopRequireDefault(__nccwpck_require__(271)); -var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(183)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4512,7 +4512,7 @@ exports["default"] = _default; /***/ }), -/***/ 9193: +/***/ 193: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4523,9 +4523,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(5717)); +var _v = _interopRequireDefault(__nccwpck_require__(717)); -var _sha = _interopRequireDefault(__nccwpck_require__(2017)); +var _sha = _interopRequireDefault(__nccwpck_require__(17)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4535,7 +4535,7 @@ exports["default"] = _default; /***/ }), -/***/ 9815: +/***/ 815: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4546,7 +4546,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _regex = _interopRequireDefault(__nccwpck_require__(1629)); +var _regex = _interopRequireDefault(__nccwpck_require__(629)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4559,7 +4559,7 @@ exports["default"] = _default; /***/ }), -/***/ 2362: +/***/ 362: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4570,7 +4570,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(9815)); +var _validate = _interopRequireDefault(__nccwpck_require__(815)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4587,7 +4587,7 @@ exports["default"] = _default; /***/ }), -/***/ 2929: +/***/ 929: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -4630,12 +4630,12 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.ContainerAppHelper = void 0; -var core = __nccwpck_require__(3195); -var io = __nccwpck_require__(9529); -var path = __nccwpck_require__(1017); -var os = __nccwpck_require__(2037); -var Utility_1 = __nccwpck_require__(2135); -var fs = __nccwpck_require__(7147); +var core = __nccwpck_require__(195); +var io = __nccwpck_require__(529); +var path = __nccwpck_require__(822); +var os = __nccwpck_require__(37); +var Utility_1 = __nccwpck_require__(135); +var fs = __nccwpck_require__(147); var ORYX_CLI_IMAGE = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; var ORYX_BUILDER_IMAGE = 'mcr.microsoft.com/oryx/builder:20230208.1'; var IS_WINDOWS_AGENT = os.platform() == 'win32'; @@ -5282,7 +5282,7 @@ exports.ContainerAppHelper = ContainerAppHelper; /***/ }), -/***/ 4769: +/***/ 769: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -5325,11 +5325,11 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.ContainerRegistryHelper = void 0; -var core = __nccwpck_require__(3195); -var exec = __nccwpck_require__(9714); -var io = __nccwpck_require__(9529); -var CommandHelper_1 = __nccwpck_require__(2433); -var Utility_1 = __nccwpck_require__(2135); +var core = __nccwpck_require__(195); +var exec = __nccwpck_require__(714); +var io = __nccwpck_require__(529); +var os = __nccwpck_require__(37); +var Utility_1 = __nccwpck_require__(135); var ContainerRegistryHelper = /** @class */ (function () { function ContainerRegistryHelper() { } @@ -5369,7 +5369,7 @@ var ContainerRegistryHelper = /** @class */ (function () { */ ContainerRegistryHelper.prototype.loginAcrWithAccessTokenAsync = function (acrName) { return __awaiter(this, void 0, void 0, function () { - var command, err_2; + var command, shell, err_2; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5378,7 +5378,8 @@ var ContainerRegistryHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"; - return [4 /*yield*/, new CommandHelper_1.CommandHelper().execCommandAsync(command)]; + shell = os.platform() === 'win32' ? 'pwsh' : 'bash'; + return [4 /*yield*/, exec.exec(shell, ['-c', command])]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5429,7 +5430,7 @@ exports.ContainerRegistryHelper = ContainerRegistryHelper; /***/ }), -/***/ 7166: +/***/ 166: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -5472,9 +5473,9 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.TelemetryHelper = void 0; -var core = __nccwpck_require__(3195); -var Utility_1 = __nccwpck_require__(2135); -var io = __nccwpck_require__(9529); +var core = __nccwpck_require__(195); +var Utility_1 = __nccwpck_require__(135); +var io = __nccwpck_require__(529); var ORYX_CLI_IMAGE = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; var SUCCESSFUL_RESULT = "succeeded"; var FAILED_RESULT = "failed"; @@ -5590,7 +5591,7 @@ var executeDockerCommand = function (args, continueOnError) { /***/ }), -/***/ 2135: +/***/ 135: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -5633,10 +5634,10 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.Utility = void 0; -var core = __nccwpck_require__(3195); -var exec = __nccwpck_require__(9714); -var util = __nccwpck_require__(3837); -var cpExec = util.promisify((__nccwpck_require__(2081).exec)); +var core = __nccwpck_require__(195); +var exec = __nccwpck_require__(714); +var util = __nccwpck_require__(837); +var cpExec = util.promisify((__nccwpck_require__(81).exec)); var Utility = /** @class */ (function () { function Utility() { } @@ -5722,15 +5723,7 @@ exports.Utility = Utility; /***/ }), -/***/ 2433: -/***/ ((module) => { - -module.exports = eval("require")("./CommandHelper"); - - -/***/ }), - -/***/ 9491: +/***/ 491: /***/ ((module) => { "use strict"; @@ -5738,7 +5731,7 @@ module.exports = require("assert"); /***/ }), -/***/ 2081: +/***/ 81: /***/ ((module) => { "use strict"; @@ -5746,7 +5739,7 @@ module.exports = require("child_process"); /***/ }), -/***/ 6113: +/***/ 113: /***/ ((module) => { "use strict"; @@ -5754,7 +5747,7 @@ module.exports = require("crypto"); /***/ }), -/***/ 2361: +/***/ 361: /***/ ((module) => { "use strict"; @@ -5762,7 +5755,7 @@ module.exports = require("events"); /***/ }), -/***/ 7147: +/***/ 147: /***/ ((module) => { "use strict"; @@ -5770,7 +5763,7 @@ module.exports = require("fs"); /***/ }), -/***/ 3685: +/***/ 685: /***/ ((module) => { "use strict"; @@ -5778,7 +5771,7 @@ module.exports = require("http"); /***/ }), -/***/ 5687: +/***/ 687: /***/ ((module) => { "use strict"; @@ -5786,7 +5779,7 @@ module.exports = require("https"); /***/ }), -/***/ 1808: +/***/ 808: /***/ ((module) => { "use strict"; @@ -5794,7 +5787,7 @@ module.exports = require("net"); /***/ }), -/***/ 2037: +/***/ 37: /***/ ((module) => { "use strict"; @@ -5802,7 +5795,7 @@ module.exports = require("os"); /***/ }), -/***/ 1017: +/***/ 822: /***/ ((module) => { "use strict"; @@ -5810,7 +5803,7 @@ module.exports = require("path"); /***/ }), -/***/ 1576: +/***/ 576: /***/ ((module) => { "use strict"; @@ -5818,7 +5811,7 @@ module.exports = require("string_decoder"); /***/ }), -/***/ 9512: +/***/ 512: /***/ ((module) => { "use strict"; @@ -5826,7 +5819,7 @@ module.exports = require("timers"); /***/ }), -/***/ 4404: +/***/ 404: /***/ ((module) => { "use strict"; @@ -5834,7 +5827,7 @@ module.exports = require("tls"); /***/ }), -/***/ 3837: +/***/ 837: /***/ ((module) => { "use strict"; @@ -5884,7 +5877,7 @@ module.exports = require("util"); /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __nccwpck_require__(3238); +/******/ var __webpack_exports__ = __nccwpck_require__(238); /******/ module.exports = __webpack_exports__; /******/ /******/ })() diff --git a/dist/licenses.txt b/dist/licenses.txt index cc497671..d7718469 100644 --- a/dist/licenses.txt +++ b/dist/licenses.txt @@ -59,16 +59,6 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -@vercel/ncc -MIT -Copyright 2018 ZEIT, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - tunnel MIT The MIT License (MIT) diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 9aeb0514..d758f1e7 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -1,7 +1,7 @@ import * as core from '@actions/core'; import * as exec from '@actions/exec'; import * as io from '@actions/io'; -import { CommandHelper } from './CommandHelper'; +import * as os from 'os'; import { Utility } from './Utility'; export class ContainerRegistryHelper { @@ -30,7 +30,8 @@ export class ContainerRegistryHelper { core.debug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { const command: string = `CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`; - await new CommandHelper().execCommandAsync(command); + const shell = os.platform() === 'win32' ? 'pwsh' : 'bash'; + await exec.exec(shell, ['-c', command]); } catch (err) { core.error(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; From 2a5a4fbcba77c6aa292901cfa9ac1f383343bc52 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sat, 23 Sep 2023 23:06:54 -0700 Subject: [PATCH 09/42] Address PR comments --- dist/index.js | 94 +++++++++++++++++++-------------------- src/ContainerAppHelper.ts | 61 ++++++++++++++----------- src/Utility.ts | 2 - 3 files changed, 81 insertions(+), 76 deletions(-) diff --git a/dist/index.js b/dist/index.js index 211944de..712c1412 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4632,6 +4632,7 @@ exports.__esModule = true; exports.ContainerAppHelper = void 0; var core = __nccwpck_require__(195); var io = __nccwpck_require__(529); +var exec = __nccwpck_require__(714); var path = __nccwpck_require__(822); var os = __nccwpck_require__(37); var Utility_1 = __nccwpck_require__(135); @@ -4639,6 +4640,7 @@ var fs = __nccwpck_require__(147); var ORYX_CLI_IMAGE = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; var ORYX_BUILDER_IMAGE = 'mcr.microsoft.com/oryx/builder:20230208.1'; var IS_WINDOWS_AGENT = os.platform() == 'win32'; +var PACK_CMD = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; var ContainerAppHelper = /** @class */ (function () { function ContainerAppHelper(disableTelemetry) { this.disableTelemetry = false; @@ -4824,7 +4826,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesContainerAppExist = function (containerAppName, resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, executionResult, err_6; + var command, exitCode, err_6; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4833,10 +4835,11 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, exec.exec("az", command.split(' '))]; case 2: - executionResult = _a.sent(); - return [2 /*return*/, !executionResult.stderr]; + exitCode = _a.sent(); + // const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + return [2 /*return*/, exitCode === 0]; case 3: err_6 = _a.sent(); core.warning(err_6.message); @@ -4854,7 +4857,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesContainerAppEnvironmentExist = function (containerAppEnvironment, resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, executionResult, err_7; + var command, exitCode, err_7; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4863,10 +4866,10 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, exec.exec("az", command.split(' '))]; case 2: - executionResult = _a.sent(); - return [2 /*return*/, !executionResult.stderr]; + exitCode = _a.sent(); + return [2 /*return*/, exitCode === 0]; case 3: err_7 = _a.sent(); core.warning(err_7.message); @@ -4883,7 +4886,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesResourceGroupExist = function (resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, executionResult, err_8; + var command, exitCode, err_8; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4892,10 +4895,10 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "group show -n " + resourceGroup + " -o none"; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, exec.exec("az", command.split(' '))]; case 2: - executionResult = _a.sent(); - return [2 /*return*/, !executionResult.stderr]; + exitCode = _a.sent(); + return [2 /*return*/, exitCode === 0]; case 3: err_8 = _a.sent(); core.warning(err_8.message); @@ -4911,7 +4914,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getDefaultContainerAppLocation = function () { return __awaiter(this, void 0, void 0, function () { - var command, executionResult, err_9; + var args, executionResult, err_9; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4919,12 +4922,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + args = ["provider", "show", "-n", "Microsoft.App", "--query", "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", args)]; case 2: executionResult = _a.sent(); - // If successful, strip out double quotes, spaces and parentheses from the first location returned - return [2 /*return*/, !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "") : "eastus2"]; + return [2 /*return*/, !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; case 3: err_9 = _a.sent(); core.warning(err_9.message); @@ -4970,7 +4972,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getExistingContainerAppEnvironment = function (resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, executionResult, err_11; + var args, executionResult, err_11; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4978,8 +4980,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp env list -g " + resourceGroup + " --query [0].name\""; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + args = ["containerapp", "env", "list", "-g", "" + resourceGroup, "--query", "[0].name"]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", args)]; case 2: executionResult = _a.sent(); return [2 /*return*/, !executionResult.stderr ? executionResult.stdout : null]; @@ -5000,7 +5002,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.createContainerAppEnvironment = function (name, resourceGroup, location) { return __awaiter(this, void 0, void 0, function () { - var util, command, err_12; + var util, args, err_12; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5009,11 +5011,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp env create -n " + name + " -g " + resourceGroup; + args = ["containerapp", "env", "create", "-n", "" + name, "-g", "" + resourceGroup]; if (!util.isNullOrEmpty(location)) { - command += " -l " + location; + args.push("-l", "" + location); } - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", args)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5103,11 +5105,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - telemetryArg = "--env \"CALLER_ID=github-actions-v1\""; + telemetryArg = "CALLER_ID=github-actions-v1"; if (this.disableTelemetry) { - telemetryArg = "--env \"ORYX_DISABLE_TELEMETRY=true\""; + telemetryArg = "ORYX_DISABLE_TELEMETRY=true"; } - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("pack", ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, "" + telemetryArg])]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("" + PACK_CMD, ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, '--env', "" + telemetryArg])]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5217,7 +5219,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("pack", ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("" + PACK_CMD, ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5236,41 +5238,41 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.installPackCliAsync = function () { return __awaiter(this, void 0, void 0, function () { - var downloadUrl, tgzSuffix, err_19; + var command, commandLine, args, packZipDownloadUri, packZipDownloadFilePath, tgzSuffix, err_19; return __generator(this, function (_a) { switch (_a.label) { case 0: core.debug('Attempting to install the pack CLI'); _a.label = 1; case 1: - _a.trys.push([1, 7, , 8]); - downloadUrl = ''; + _a.trys.push([1, 3, , 4]); + command = ''; + commandLine = ''; + args = []; if (IS_WINDOWS_AGENT) { - downloadUrl = "https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip"; + packZipDownloadUri = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; + packZipDownloadFilePath = path.join(PACK_CMD, 'pack-windows.zip'); + args = ["New-Item", "-ItemType", "Directory", "-Path", "" + PACK_CMD, "-Force | Out-Null;", "Invoke-WebRequest", "-Uri", "" + packZipDownloadUri, "-OutFile", packZipDownloadFilePath + ";", "Expand-Archive", "-LiteralPath", "" + packZipDownloadFilePath, "-DestinationPath", PACK_CMD + ";", "Remove-Item", "-Path", "" + packZipDownloadFilePath, + "Expand-Archive", "-LiteralPath", "" + packZipDownloadFilePath, "-DestinationPath", PACK_CMD + ";", "Remove-Item", "-Path", "" + packZipDownloadFilePath]; + commandLine = 'pwsh'; } else { tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - downloadUrl = "https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz"; + command = "(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; + args = ['-c', command]; + commandLine = 'bash'; } - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("curl", ["-L", "" + downloadUrl, "-o", "pack.zip"])]; + return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(commandLine, args)]; case 2: _a.sent(); - if (!IS_WINDOWS_AGENT) return [3 /*break*/, 4]; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("tar", ["-xf", "pack.zip"])]; + return [3 /*break*/, 4]; case 3: - _a.sent(); - return [3 /*break*/, 6]; - case 4: return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("unzip", ["pack.zip"])]; - case 5: - _a.sent(); - _a.label = 6; - case 6: return [3 /*break*/, 8]; - case 7: err_19 = _a.sent(); core.error("Unable to install the pack CLI. Error: " + err_19.message); core.setFailed(err_19.message); throw err_19; - case 8: return [2 /*return*/]; + case 4: return [2 /*return*/]; } }); }); @@ -5660,11 +5662,9 @@ var Utility = /** @class */ (function () { listeners: { stdout: function (data) { stdout_1 += data.toString(); - core.info(data.toString()); }, stderr: function (data) { stderr_1 += data.toString(); - core.error(data.toString()); } } }; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 28e85ea6..868128e9 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -1,5 +1,6 @@ import * as core from '@actions/core'; import * as io from '@actions/io'; +import * as exec from '@actions/exec'; import * as path from 'path'; import * as os from 'os'; import { Utility } from './Utility'; @@ -8,6 +9,7 @@ import fs = require('fs'); const ORYX_CLI_IMAGE: string = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; const ORYX_BUILDER_IMAGE: string = 'mcr.microsoft.com/oryx/builder:20230208.1'; const IS_WINDOWS_AGENT: boolean = os.platform() == 'win32'; +const PACK_CMD: string = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; export class ContainerAppHelper { readonly disableTelemetry: boolean = false; @@ -158,8 +160,9 @@ export class ContainerAppHelper { core.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { const command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; - const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); - return !executionResult.stderr; + const exitCode = await exec.exec(`az`, command.split(' ')); + // const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + return exitCode === 0; } catch (err) { core.warning(err.message); return false; @@ -176,8 +179,8 @@ export class ContainerAppHelper { core.debug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { const command = `containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; - const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); - return !executionResult.stderr; + const exitCode = await exec.exec(`az`, command.split(' ')); + return exitCode === 0; } catch (err) { core.warning(err.message); return false; @@ -193,8 +196,8 @@ export class ContainerAppHelper { core.debug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { const command = `group show -n ${resourceGroup} -o none`; - const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); - return !executionResult.stderr; + const exitCode = await exec.exec(`az`, command.split(' ')); + return exitCode === 0; } catch (err) { core.warning(err.message); return false; @@ -208,10 +211,10 @@ export class ContainerAppHelper { public async getDefaultContainerAppLocation(): Promise { core.debug(`Attempting to get the default location for the Container App service for the subscription.`); try { - const command = `provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"` - const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + let args = [`provider`, `show`, `-n`, `Microsoft.App`, `--query`, `resourceTypes[?resourceType=='containerApps'].locations[] | [0]`]; + const executionResult = await new Utility().executeAndthrowIfError(`az`, args); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "") : `eastus2`; + return !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { core.warning(err.message); return `eastus2`; @@ -243,8 +246,8 @@ export class ContainerAppHelper { public async getExistingContainerAppEnvironment(resourceGroup: string) { core.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { - const command = `containerapp env list -g ${resourceGroup} --query [0].name"`; - const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + let args = [`containerapp`, `env`, `list`, `-g`, `${resourceGroup}`, `--query`, `[0].name`]; + const executionResult = await new Utility().executeAndthrowIfError(`az`, args); return !executionResult.stderr ? executionResult.stdout : null; } catch (err) { core.warning(err.message); @@ -262,11 +265,11 @@ export class ContainerAppHelper { const util = new Utility(); core.debug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); try { - let command = `containerapp env create -n ${name} -g ${resourceGroup}`; + let args = [`containerapp`, `env`, `create`, `-n`, `${name}`, `-g`, `${resourceGroup}`]; if (!util.isNullOrEmpty(location)) { - command += ` -l ${location}`; + args.push(`-l`, `${location}`); } - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndthrowIfError(`az`, args); } catch (err) { core.error(err.message); throw err; @@ -320,11 +323,11 @@ export class ContainerAppHelper { runtimeStack: string) { core.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); try { - let telemetryArg = `--env "CALLER_ID=github-actions-v1"`; + let telemetryArg = `CALLER_ID=github-actions-v1`; if (this.disableTelemetry) { - telemetryArg = `--env "ORYX_DISABLE_TELEMETRY=true"`; + telemetryArg = `ORYX_DISABLE_TELEMETRY=true`; } - await new Utility().executeAndthrowIfError(`pack`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, `${telemetryArg}`]); + await new Utility().executeAndthrowIfError(`${PACK_CMD}`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, '--env', `${telemetryArg}`]); } catch (err) { core.error(err.message); throw err; @@ -397,7 +400,7 @@ export class ContainerAppHelper { public async setDefaultBuilder() { core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { - await new Utility().executeAndthrowIfError(`pack`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); + await new Utility().executeAndthrowIfError(`${PACK_CMD}`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); } catch (err) { core.setFailed(err.message); @@ -412,19 +415,23 @@ export class ContainerAppHelper { public async installPackCliAsync() { core.debug('Attempting to install the pack CLI'); try { - let downloadUrl: string = ''; + let command: string = ''; + let commandLine = ''; + let args: string[] = []; if (IS_WINDOWS_AGENT) { - downloadUrl = `https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip` + const packZipDownloadUri: string = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; + const packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); + args = [`New-Item`, `-ItemType`, `Directory`, `-Path`, `${PACK_CMD}`, `-Force | Out-Null;`, `Invoke-WebRequest`, `-Uri`, `${packZipDownloadUri}`, `-OutFile`, `${packZipDownloadFilePath};`, `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`, + `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`]; + commandLine = 'pwsh'; } else { const tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - downloadUrl = `https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz`; - } - await new Utility().executeAndthrowIfError(`curl`, [`-L`, `${downloadUrl}`, `-o`, `pack.zip`]); - if (IS_WINDOWS_AGENT) { - await new Utility().executeAndthrowIfError(`tar`, [`-xf`, `pack.zip`]); - } else { - await new Utility().executeAndthrowIfError(`unzip`, [`pack.zip`]); + command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; + args = ['-c', command]; + commandLine = 'bash'; } + await new Utility().executeAndthrowIfError(commandLine, args); } catch (err) { core.error(`Unable to install the pack CLI. Error: ${err.message}`); core.setFailed(err.message); diff --git a/src/Utility.ts b/src/Utility.ts index 8279f0ef..e3003266 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -18,11 +18,9 @@ export class Utility { listeners: { stdout: (data: Buffer) => { stdout += data.toString(); - core.info(data.toString()); }, stderr: (data: Buffer) => { stderr += data.toString(); - core.error(data.toString()); }, }, }; From 143c5a7c40a65900cc0492ea94d2de86868540ba Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sat, 23 Sep 2023 23:17:56 -0700 Subject: [PATCH 10/42] Remove commented code --- dist/index.js | 2 +- src/ContainerAppHelper.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dist/index.js b/dist/index.js index 712c1412..be31feb3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4838,7 +4838,6 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, exec.exec("az", command.split(' '))]; case 2: exitCode = _a.sent(); - // const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); return [2 /*return*/, exitCode === 0]; case 3: err_6 = _a.sent(); @@ -4926,6 +4925,7 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", args)]; case 2: executionResult = _a.sent(); + // If successful, strip out double quotes, spaces and parentheses from the first location returned return [2 /*return*/, !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; case 3: err_9 = _a.sent(); diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 868128e9..44f2ebb9 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -159,9 +159,8 @@ export class ContainerAppHelper { public async doesContainerAppExist(containerAppName: string, resourceGroup: string): Promise { core.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { - const command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; + let command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; const exitCode = await exec.exec(`az`, command.split(' ')); - // const executionResult = await new Utility().executeAndthrowIfError(`az`, command.split(' ')); return exitCode === 0; } catch (err) { core.warning(err.message); From ed6309fca5f98ac834b85f3241a2b2f76078ab98 Mon Sep 17 00:00:00 2001 From: snehapar9 <108305436+snehapar9@users.noreply.github.com> Date: Sun, 24 Sep 2023 00:16:00 -0700 Subject: [PATCH 11/42] ci: add Azure Static Web Apps workflow file on-behalf-of: @Azure opensource@microsoft.com --- ...e-static-web-apps-ashy-ocean-015179e0f.yml | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml diff --git a/.github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml b/.github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml new file mode 100644 index 00000000..11983cb8 --- /dev/null +++ b/.github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml @@ -0,0 +1,45 @@ +name: Azure Static Web Apps CI/CD + +on: + push: + branches: + - snehapar/container-apps-deploy-action-javascript + pull_request: + types: [opened, synchronize, reopened, closed] + branches: + - snehapar/container-apps-deploy-action-javascript + +jobs: + build_and_deploy_job: + if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed') + runs-on: ubuntu-latest + name: Build and Deploy Job + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: Build And Deploy + id: builddeploy + uses: Azure/static-web-apps-deploy@v1 + with: + azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_OCEAN_015179E0F }} + repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) + action: "upload" + ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### + # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig + app_location: "/" # App source code path + api_location: "api" # Api source code path - optional + output_location: "public" # Built app content directory - optional + ###### End of Repository/Build Configurations ###### + + close_pull_request_job: + if: github.event_name == 'pull_request' && github.event.action == 'closed' + runs-on: ubuntu-latest + name: Close Pull Request Job + steps: + - name: Close Pull Request + id: closepullrequest + uses: Azure/static-web-apps-deploy@v1 + with: + azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_OCEAN_015179E0F }} + action: "close" From 2da69d5e4e07dd103c052e97dd0e9d0153f7afa3 Mon Sep 17 00:00:00 2001 From: snehapar9 <108305436+snehapar9@users.noreply.github.com> Date: Sun, 24 Sep 2023 00:43:37 -0700 Subject: [PATCH 12/42] Delete .github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml --- ...e-static-web-apps-ashy-ocean-015179e0f.yml | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 .github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml diff --git a/.github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml b/.github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml deleted file mode 100644 index 11983cb8..00000000 --- a/.github/workflows/azure-static-web-apps-ashy-ocean-015179e0f.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Azure Static Web Apps CI/CD - -on: - push: - branches: - - snehapar/container-apps-deploy-action-javascript - pull_request: - types: [opened, synchronize, reopened, closed] - branches: - - snehapar/container-apps-deploy-action-javascript - -jobs: - build_and_deploy_job: - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed') - runs-on: ubuntu-latest - name: Build and Deploy Job - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - name: Build And Deploy - id: builddeploy - uses: Azure/static-web-apps-deploy@v1 - with: - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_OCEAN_015179E0F }} - repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) - action: "upload" - ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### - # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig - app_location: "/" # App source code path - api_location: "api" # Api source code path - optional - output_location: "public" # Built app content directory - optional - ###### End of Repository/Build Configurations ###### - - close_pull_request_job: - if: github.event_name == 'pull_request' && github.event.action == 'closed' - runs-on: ubuntu-latest - name: Close Pull Request Job - steps: - - name: Close Pull Request - id: closepullrequest - uses: Azure/static-web-apps-deploy@v1 - with: - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_OCEAN_015179E0F }} - action: "close" From 4948dc7ad9690a82f047fd3fa53bcd3758ed16fa Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sun, 24 Sep 2023 00:55:31 -0700 Subject: [PATCH 13/42] Update Azure CLI extensions installation --- dist/index.js | 4 +--- src/Utility.ts | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index be31feb3..c90cdf45 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5638,8 +5638,6 @@ exports.__esModule = true; exports.Utility = void 0; var core = __nccwpck_require__(195); var exec = __nccwpck_require__(714); -var util = __nccwpck_require__(837); -var cpExec = util.promisify((__nccwpck_require__(81).exec)); var Utility = /** @class */ (function () { function Utility() { } @@ -5700,7 +5698,7 @@ var Utility = /** @class */ (function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, cpExec("az config set extension.use_dynamic_install=yes_without_prompt")]; + case 0: return [4 /*yield*/, new Utility().executeAndthrowIfError('az', ["config", "set", "extension.use_dynamic_install=yes_without_prompt"])]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/src/Utility.ts b/src/Utility.ts index e3003266..3a6ee55a 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -1,7 +1,5 @@ import * as core from '@actions/core'; import * as exec from '@actions/exec'; -import util = require('util'); -const cpExec = util.promisify(require('child_process').exec); export class Utility { /** * @param commandLine - the command to execute @@ -50,7 +48,7 @@ export class Utility { * Azure Container Apps module being dynamically installed while it's still in preview. */ public async setAzureCliDynamicInstall() { - await cpExec(`az config set extension.use_dynamic_install=yes_without_prompt`); + await new Utility().executeAndthrowIfError('az', [`config`, `set`, `extension.use_dynamic_install=yes_without_prompt`]); } /** From 15edd0a8d131ee39e02efc073bc7d70201e3bfaa Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sun, 24 Sep 2023 01:02:12 -0700 Subject: [PATCH 14/42] Await setupAzureCli --- azurecontainerapps.ts | 2 +- dist/index.js | 39 +++++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index 47c1de10..356dfc63 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -19,7 +19,7 @@ export class azurecontainerapps { this.validateSupportedScenarioArguments(); // Set up the Azure CLI to be used for this task - this.setupAzureCli(); + await this.setupAzureCli(); // Set up the resources required to deploy a Container App await this.setupResources(); diff --git a/dist/index.js b/dist/index.js index c90cdf45..dfeb15c4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -65,28 +65,31 @@ var azurecontainerapps = /** @class */ (function () { this.initializeHelpers(disableTelemetry); _a.label = 1; case 1: - _a.trys.push([1, 8, 9, 11]); + _a.trys.push([1, 9, 10, 12]); // Validate that the arguments provided can be used for one of the supported scenarios this.validateSupportedScenarioArguments(); // Set up the Azure CLI to be used for this task - this.setupAzureCli(); + return [4 /*yield*/, this.setupAzureCli()]; + case 2: + // Set up the Azure CLI to be used for this task + _a.sent(); // Set up the resources required to deploy a Container App return [4 /*yield*/, this.setupResources()]; - case 2: + case 3: // Set up the resources required to deploy a Container App _a.sent(); - if (!!util.isNullOrEmpty(this.acrName)) return [3 /*break*/, 4]; + if (!!util.isNullOrEmpty(this.acrName)) return [3 /*break*/, 5]; return [4 /*yield*/, this.authenticateAzureContainerRegistryAsync()]; - case 3: - _a.sent(); - _a.label = 4; case 4: - if (!!util.isNullOrEmpty(this.appSourcePath)) return [3 /*break*/, 6]; - return [4 /*yield*/, this.buildAndPushImageAsync()]; - case 5: _a.sent(); - _a.label = 6; + _a.label = 5; + case 5: + if (!!util.isNullOrEmpty(this.appSourcePath)) return [3 /*break*/, 7]; + return [4 /*yield*/, this.buildAndPushImageAsync()]; case 6: + _a.sent(); + _a.label = 7; + case 7: // If no application source was provided, set up the scenario for deploying an existing image if (util.isNullOrEmpty(this.appSourcePath)) { this.setupExistingImageScenario(); @@ -97,25 +100,25 @@ var azurecontainerapps = /** @class */ (function () { } // Create/update the Container App return [4 /*yield*/, this.createOrUpdateContainerApp()]; - case 7: + case 8: // Create/update the Container App _a.sent(); // If telemetry is enabled, log that the task completed successfully this.telemetryHelper.setSuccessfulResult(); - return [3 /*break*/, 11]; - case 8: + return [3 /*break*/, 12]; + case 9: err_1 = _a.sent(); core.setFailed(err_1.message); this.telemetryHelper.setFailedResult(err_1.message); - return [3 /*break*/, 11]; - case 9: + return [3 /*break*/, 12]; + case 10: // If telemetry is enabled, will log metadata for this task run return [4 /*yield*/, this.telemetryHelper.sendLogs()]; - case 10: + case 11: // If telemetry is enabled, will log metadata for this task run _a.sent(); return [7 /*endfinally*/]; - case 11: return [2 /*return*/]; + case 12: return [2 /*return*/]; } }); }); From 8ffbb3ef4bd33ef84a5f15ea27101cc0b39bc18f Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sun, 24 Sep 2023 15:54:46 -0700 Subject: [PATCH 15/42] Refactor and trigger pipeline --- dist/index.js | 2 +- src/Utility.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index dfeb15c4..5fc2f0cf 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5701,7 +5701,7 @@ var Utility = /** @class */ (function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, new Utility().executeAndthrowIfError('az', ["config", "set", "extension.use_dynamic_install=yes_without_prompt"])]; + case 0: return [4 /*yield*/, this.executeAndthrowIfError('az', ["config", "set", "extension.use_dynamic_install=yes_without_prompt"])]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/src/Utility.ts b/src/Utility.ts index 3a6ee55a..95e7eede 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -48,7 +48,7 @@ export class Utility { * Azure Container Apps module being dynamically installed while it's still in preview. */ public async setAzureCliDynamicInstall() { - await new Utility().executeAndthrowIfError('az', [`config`, `set`, `extension.use_dynamic_install=yes_without_prompt`]); + await this.executeAndthrowIfError('az', [`config`, `set`, `extension.use_dynamic_install=yes_without_prompt`]); } /** From bc74648f6038f7fa0d31b9a92a46c4cc7cf37282 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sun, 24 Sep 2023 20:22:12 -0700 Subject: [PATCH 16/42] Refactor TelemetryHelper --- dist/index.js | 8 ++++---- src/TelemetryHelper.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dist/index.js b/dist/index.js index 5fc2f0cf..31232cc4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5541,17 +5541,17 @@ var TelemetryHelper = /** @class */ (function () { _a.trys.push([1, 3, , 4]); resultArg = ''; if (!util.isNullOrEmpty(this.result)) { - resultArg = "--property 'result=" + this.result + "'"; + resultArg = "--property result=" + this.result; } scenarioArg = ''; if (!util.isNullOrEmpty(this.scenario)) { - scenarioArg = "--property 'scenario=" + this.scenario + "'"; + scenarioArg = "--property scenario=" + this.scenario; } errorMessageArg = ''; if (!util.isNullOrEmpty(this.errorMessage)) { - errorMessageArg = "--property 'errorMessage=" + this.errorMessage + "'"; + errorMessageArg = "--property errorMessage=" + this.errorMessage; } - args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name 'ContainerAppsGitHubActionV1' " + ("--processing-time '" + taskLengthMilliseconds + "' " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; + args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name ContainerAppsGitHubActionV1 " + ("--processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; return [4 /*yield*/, executeDockerCommand(args, true)]; case 2: _a.sent(); diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 4d9d75b3..6524c120 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -72,20 +72,20 @@ export class TelemetryHelper { try { let resultArg: string = ''; if (!util.isNullOrEmpty(this.result)) { - resultArg = `--property 'result=${this.result}'`; + resultArg = `--property result=${this.result}`; } let scenarioArg: string = ''; if (!util.isNullOrEmpty(this.scenario)) { - scenarioArg = `--property 'scenario=${this.scenario}'`; + scenarioArg = `--property scenario=${this.scenario}`; } let errorMessageArg: string = ''; if (!util.isNullOrEmpty(this.errorMessage)) { - errorMessageArg = `--property 'errorMessage=${this.errorMessage}'`; + errorMessageArg = `--property errorMessage=${this.errorMessage}`; } - let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name 'ContainerAppsGitHubActionV1' ` + `--processing-time '${taskLengthMilliseconds}' ${resultArg} ${scenarioArg} ${errorMessageArg}"`]; + let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name ContainerAppsGitHubActionV1 ` + `--processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`]; await executeDockerCommand(args, true) } catch (err) { From c24198bd3f80759588b8880811c4003d1a454bf7 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Mon, 25 Sep 2023 00:05:00 -0700 Subject: [PATCH 17/42] Reformat and remove new line --- src/ContainerAppHelper.ts | 3 +-- src/Utility.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 44f2ebb9..520d5b63 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -230,7 +230,6 @@ export class ContainerAppHelper { try { const command = `group create -n ${name} -l ${location}`; await new Utility().executeAndthrowIfError(`az`, command.split(' ')); - } catch (err) { core.error(err.message); throw err; @@ -421,7 +420,7 @@ export class ContainerAppHelper { const packZipDownloadUri: string = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; const packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); args = [`New-Item`, `-ItemType`, `Directory`, `-Path`, `${PACK_CMD}`, `-Force | Out-Null;`, `Invoke-WebRequest`, `-Uri`, `${packZipDownloadUri}`, `-OutFile`, `${packZipDownloadFilePath};`, `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`, - `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`]; + `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`]; commandLine = 'pwsh'; } else { const tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; diff --git a/src/Utility.ts b/src/Utility.ts index 95e7eede..465b06ea 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -7,7 +7,7 @@ export class Utility { * @param continueOnError - whether or not to continue execution if the command fails */ - public async executeAndthrowIfError(commandLine: string, args: string[], continueOnError: boolean = false) : Promise<{exitCode:number, stdout:string, stderr:string}> { + public async executeAndthrowIfError(commandLine: string, args: string[], continueOnError: boolean = false): Promise<{ exitCode: number, stdout: string, stderr: string }> { try { let stdout = ''; let stderr = ''; From 4c3251371f91b8ee37adc5cbc0ec348d06fa8740 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Mon, 25 Sep 2023 10:49:25 -0700 Subject: [PATCH 18/42] Refactor and re-trigger pipeline --- dist/index.js | 40 +++++++++++++++++----------------- src/ContainerAppHelper.ts | 32 +++++++++++++-------------- src/ContainerRegistryHelper.ts | 2 +- src/TelemetryHelper.ts | 2 +- src/Utility.ts | 4 ++-- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/dist/index.js b/dist/index.js index 31232cc4..6d99726a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4671,7 +4671,7 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command_1.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command_1.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4701,7 +4701,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4735,7 +4735,7 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_2 += " " + val; }); - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command_2.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command_2.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4778,7 +4778,7 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(targetPort)) { command_3 += " --target-port " + targetPort; } - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command_3.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command_3.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4808,7 +4808,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4925,7 +4925,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); args = ["provider", "show", "-n", "Microsoft.App", "--query", "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"]; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", args)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", args)]; case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned @@ -4955,7 +4955,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "group create -n " + name + " -l " + location; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4984,7 +4984,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); args = ["containerapp", "env", "list", "-g", "" + resourceGroup, "--query", "[0].name"]; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", args)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", args)]; case 2: executionResult = _a.sent(); return [2 /*return*/, !executionResult.stderr ? executionResult.stdout : null]; @@ -5018,7 +5018,7 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(location)) { args.push("-l", "" + location); } - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", args)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", args)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5047,7 +5047,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp ingress disable -n " + name + " -g " + resourceGroup; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5079,7 +5079,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("az", command.split(' '))]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5112,7 +5112,7 @@ var ContainerAppHelper = /** @class */ (function () { if (this.disableTelemetry) { telemetryArg = "ORYX_DISABLE_TELEMETRY=true"; } - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("" + PACK_CMD, ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, '--env', "" + telemetryArg])]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("" + PACK_CMD, ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, '--env', "" + telemetryArg])]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5145,7 +5145,7 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, io.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, ['build', '--file', "" + dockerfilePath, "" + appSourcePath, '--tag', "" + imageToDeploy])]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, ['build', '--file', "" + dockerfilePath, "" + appSourcePath, '--tag', "" + imageToDeploy])]; case 3: _a.sent(); core.debug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); @@ -5178,7 +5178,7 @@ var ContainerAppHelper = /** @class */ (function () { case 2: dockerTool = _a.sent(); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, ['run', '--rm', '-v', appSourcePath + ":/app", "" + ORYX_CLI_IMAGE, '/bin/bash', '-c', "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"]) + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', appSourcePath + ":/app", "" + ORYX_CLI_IMAGE, '/bin/bash', '-c', "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"]) // Read the temp file to get the runtime stack into a variable ]; case 3: @@ -5222,7 +5222,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError("" + PACK_CMD, ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("" + PACK_CMD, ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5266,7 +5266,7 @@ var ContainerAppHelper = /** @class */ (function () { args = ['-c', command]; commandLine = 'bash'; } - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(commandLine, args)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(commandLine, args)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5414,7 +5414,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [4 /*yield*/, io.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, ["push", "" + imageToPush])]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, ["push", "" + imageToPush])]; case 3: _a.sent(); return [3 /*break*/, 5]; @@ -5579,7 +5579,7 @@ var executeDockerCommand = function (args, continueOnError) { return [4 /*yield*/, io.which("docker", true)]; case 1: dockerTool = _a.sent(); - return [4 /*yield*/, new Utility_1.Utility().executeAndthrowIfError(dockerTool, args, continueOnError)]; + return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, args, continueOnError)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5649,7 +5649,7 @@ var Utility = /** @class */ (function () { * @param args - the arguments to pass to the command * @param continueOnError - whether or not to continue execution if the command fails */ - Utility.prototype.executeAndthrowIfError = function (commandLine, args, continueOnError) { + Utility.prototype.executeAndThrowIfError = function (commandLine, args, continueOnError) { if (continueOnError === void 0) { continueOnError = false; } return __awaiter(this, void 0, void 0, function () { var stdout_1, stderr_1, options, exitCode_1, error_1; @@ -5701,7 +5701,7 @@ var Utility = /** @class */ (function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, this.executeAndthrowIfError('az', ["config", "set", "extension.use_dynamic_install=yes_without_prompt"])]; + case 0: return [4 /*yield*/, this.executeAndThrowIfError('az', ["config", "set", "extension.use_dynamic_install=yes_without_prompt"])]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 520d5b63..0a150fb1 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -38,7 +38,7 @@ export class ContainerAppHelper { optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -58,7 +58,7 @@ export class ContainerAppHelper { core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -84,7 +84,7 @@ export class ContainerAppHelper { command += ` ${val}`; }); - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -123,7 +123,7 @@ export class ContainerAppHelper { command += ` --target-port ${targetPort}`; } - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -143,7 +143,7 @@ export class ContainerAppHelper { core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -211,7 +211,7 @@ export class ContainerAppHelper { core.debug(`Attempting to get the default location for the Container App service for the subscription.`); try { let args = [`provider`, `show`, `-n`, `Microsoft.App`, `--query`, `resourceTypes[?resourceType=='containerApps'].locations[] | [0]`]; - const executionResult = await new Utility().executeAndthrowIfError(`az`, args); + const executionResult = await new Utility().executeAndThrowIfError(`az`, args); // If successful, strip out double quotes, spaces and parentheses from the first location returned return !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { @@ -229,7 +229,7 @@ export class ContainerAppHelper { core.debug(`Attempting to create resource group "${name}" in location "${location}"`); try { const command = `group create -n ${name} -l ${location}`; - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -245,7 +245,7 @@ export class ContainerAppHelper { core.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { let args = [`containerapp`, `env`, `list`, `-g`, `${resourceGroup}`, `--query`, `[0].name`]; - const executionResult = await new Utility().executeAndthrowIfError(`az`, args); + const executionResult = await new Utility().executeAndThrowIfError(`az`, args); return !executionResult.stderr ? executionResult.stdout : null; } catch (err) { core.warning(err.message); @@ -267,7 +267,7 @@ export class ContainerAppHelper { if (!util.isNullOrEmpty(location)) { args.push(`-l`, `${location}`); } - await new Utility().executeAndthrowIfError(`az`, args); + await new Utility().executeAndThrowIfError(`az`, args); } catch (err) { core.error(err.message); throw err; @@ -283,7 +283,7 @@ export class ContainerAppHelper { core.debug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); try { const command = `containerapp ingress disable -n ${name} -g ${resourceGroup}`; - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -302,7 +302,7 @@ export class ContainerAppHelper { core.debug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { const command = `containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; - await new Utility().executeAndthrowIfError(`az`, command.split(' ')); + await new Utility().executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { core.error(err.message); throw err; @@ -325,7 +325,7 @@ export class ContainerAppHelper { if (this.disableTelemetry) { telemetryArg = `ORYX_DISABLE_TELEMETRY=true`; } - await new Utility().executeAndthrowIfError(`${PACK_CMD}`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, '--env', `${telemetryArg}`]); + await new Utility().executeAndThrowIfError(`${PACK_CMD}`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, '--env', `${telemetryArg}`]); } catch (err) { core.error(err.message); throw err; @@ -346,7 +346,7 @@ export class ContainerAppHelper { core.debug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); try { const dockerTool = await io.which("docker", true); - await new Utility().executeAndthrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); + await new Utility().executeAndThrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); core.debug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); } catch (err) { core.setFailed(err.message); @@ -364,7 +364,7 @@ export class ContainerAppHelper { try { const dockerTool: string = await io.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - await new Utility().executeAndthrowIfError(dockerTool, ['run', '--rm', '-v', `${appSourcePath}:/app`, `${ORYX_CLI_IMAGE}`, '/bin/bash', '-c', `oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt`]) + await new Utility().executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', `${appSourcePath}:/app`, `${ORYX_CLI_IMAGE}`, '/bin/bash', '-c', `oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt`]) // Read the temp file to get the runtime stack into a variable const oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); @@ -398,7 +398,7 @@ export class ContainerAppHelper { public async setDefaultBuilder() { core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { - await new Utility().executeAndthrowIfError(`${PACK_CMD}`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); + await new Utility().executeAndThrowIfError(`${PACK_CMD}`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); } catch (err) { core.setFailed(err.message); @@ -429,7 +429,7 @@ export class ContainerAppHelper { args = ['-c', command]; commandLine = 'bash'; } - await new Utility().executeAndthrowIfError(commandLine, args); + await new Utility().executeAndThrowIfError(commandLine, args); } catch (err) { core.error(`Unable to install the pack CLI. Error: ${err.message}`); core.setFailed(err.message); diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index d758f1e7..59fa4d77 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -46,7 +46,7 @@ export class ContainerRegistryHelper { core.debug(`Attempting to push image "${imageToPush}" to ACR`); try { const dockerTool: string = await io.which("docker", true); - await new Utility().executeAndthrowIfError(dockerTool, [`push`, `${imageToPush}`]); + await new Utility().executeAndThrowIfError(dockerTool, [`push`, `${imageToPush}`]); } catch (err) { core.error(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); core.setFailed(err.message); diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 6524c120..167593b5 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -98,7 +98,7 @@ export class TelemetryHelper { const executeDockerCommand = async (args: string[], continueOnError: boolean = false): Promise => { try { const dockerTool: string = await io.which("docker", true); - await new Utility().executeAndthrowIfError(dockerTool, args, continueOnError); + await new Utility().executeAndThrowIfError(dockerTool, args, continueOnError); } catch (err) { core.setFailed(`Error: ${err.message}`); diff --git a/src/Utility.ts b/src/Utility.ts index 465b06ea..7deba5c7 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -7,7 +7,7 @@ export class Utility { * @param continueOnError - whether or not to continue execution if the command fails */ - public async executeAndthrowIfError(commandLine: string, args: string[], continueOnError: boolean = false): Promise<{ exitCode: number, stdout: string, stderr: string }> { + public async executeAndThrowIfError(commandLine: string, args: string[], continueOnError: boolean = false): Promise<{ exitCode: number, stdout: string, stderr: string }> { try { let stdout = ''; let stderr = ''; @@ -48,7 +48,7 @@ export class Utility { * Azure Container Apps module being dynamically installed while it's still in preview. */ public async setAzureCliDynamicInstall() { - await this.executeAndthrowIfError('az', [`config`, `set`, `extension.use_dynamic_install=yes_without_prompt`]); + await this.executeAndThrowIfError('az', [`config`, `set`, `extension.use_dynamic_install=yes_without_prompt`]); } /** From ba6abd5ae20468346e10c4b0962aa966260028c1 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 26 Sep 2023 15:20:22 -0700 Subject: [PATCH 19/42] Address PR comments --- azurecontainerapps.ts | 89 ++--- dist/index.js | 708 +++++++++++++++++++-------------- src/ContainerAppHelper.ts | 164 ++++---- src/ContainerRegistryHelper.ts | 32 +- src/GithubActionsToolHelper.ts | 75 ++++ src/TelemetryHelper.ts | 17 +- src/Utility.ts | 31 +- 7 files changed, 644 insertions(+), 472 deletions(-) create mode 100644 src/GithubActionsToolHelper.ts diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index 356dfc63..bd74dd3d 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -1,17 +1,18 @@ -import * as core from '@actions/core'; import * as fs from 'fs'; import * as path from 'path'; import { ContainerAppHelper } from './src/ContainerAppHelper'; import { ContainerRegistryHelper } from './src/ContainerRegistryHelper'; import { TelemetryHelper } from './src/TelemetryHelper'; import { Utility } from './src/Utility'; +import { GithubActionsToolHelper } from './src/GithubActionsToolHelper'; const util = new Utility(); +const githubActionsToolHelper = new GithubActionsToolHelper(); export class azurecontainerapps { public static async runMain(): Promise { - let disableTelemetry = core.getInput('disableTelemetry').toLowerCase() === 'true'; + let disableTelemetry = githubActionsToolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; this.initializeHelpers(disableTelemetry); try { @@ -50,7 +51,7 @@ export class azurecontainerapps { // If telemetry is enabled, log that the task completed successfully this.telemetryHelper.setSuccessfulResult(); } catch (err) { - core.setFailed(err.message); + githubActionsToolHelper.setFailed(err.message); this.telemetryHelper.setFailedResult(err.message); } finally { // If telemetry is enabled, will log metadata for this task run @@ -59,8 +60,8 @@ export class azurecontainerapps { } // GitHub Action properties - private static githubRunId: string = process.env.GITHUB_RUN_ID; - private static githubRunNumber = process.env.GITHUB_RUN_NUMBER; + private static githubRunId: string = githubActionsToolHelper.getGithubRunId(); + private static githubRunNumber: string = githubActionsToolHelper.getGithubRunNumber(); // Supported scenario properties private static appSourcePath: string; @@ -117,26 +118,26 @@ export class azurecontainerapps { private static validateSupportedScenarioArguments() { // Get the path to the application source to build and run, if provided - this.appSourcePath = core.getInput('appSourcePath', { required: false }); + this.appSourcePath = githubActionsToolHelper.getInput('appSourcePath', { required: false }); // Get the name of the ACR instance to push images to, if provided - this.acrName = core.getInput('acrName', { required: false }); + this.acrName = githubActionsToolHelper.getInput('acrName', { required: false }); // Get the previously built image to deploy, if provided - this.imageToDeploy = core.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = githubActionsToolHelper.getInput('imageToDeploy', { required: false }); // Get the YAML configuration file, if provided - this.yamlConfigPath = core.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = githubActionsToolHelper.getInput('yamlConfigPath', { required: false }); // Ensure that acrName is also provided if appSourcePath is provided if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { - core.error(`The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`); + githubActionsToolHelper.error(`The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`); throw Error(`The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { - core.error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); + githubActionsToolHelper.error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); throw Error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); } } @@ -182,13 +183,9 @@ export class azurecontainerapps { * @returns The name of the Container App to use for the task. */ private static getContainerAppName(): string { - let containerAppName: string = core.getInput('containerAppName', { required: false }); + let containerAppName: string = githubActionsToolHelper.getInput('containerAppName', { required: false }); if (util.isNullOrEmpty(containerAppName)) { - containerAppName = `gh-action-app-${this.githubRunId}-${this.githubRunNumber}`; - - // Replace all '.' characters with '-' characters in the Container App name - containerAppName = containerAppName.replace(/\./gi, "-"); - core.info(`Default Container App name: ${containerAppName}`); + return githubActionsToolHelper.getContainerAppName(containerAppName); } return containerAppName; @@ -201,7 +198,7 @@ export class azurecontainerapps { */ private static async getLocation(): Promise { // Set deployment location, if provided - let location: string = core.getInput('location', { required: false }); + let location: string = githubActionsToolHelper.getInput('location', { required: false }); // If no location was provided, use the default location for the Container App service if (util.isNullOrEmpty(location)) { @@ -221,10 +218,10 @@ export class azurecontainerapps { */ private static async getOrCreateResourceGroup(containerAppName: string, location: string): Promise { // Get the resource group to deploy to if it was provided, or generate it from the Container App name - let resourceGroup: string = core.getInput('resourceGroup', { required: false }); + let resourceGroup: string = githubActionsToolHelper.getInput('resourceGroup', { required: false }); if (util.isNullOrEmpty(resourceGroup)) { resourceGroup = `${containerAppName}-rg`; - core.info(`Default resource group name: ${resourceGroup}`); + githubActionsToolHelper.info(`Default resource group name: ${resourceGroup}`); // Ensure that the resource group that the Container App will be created in exists const resourceGroupExists = await this.appHelper.doesResourceGroupExist(resourceGroup); @@ -251,13 +248,13 @@ export class azurecontainerapps { resourceGroup: string, location: string): Promise { // Get the Container App environment if it was provided - let containerAppEnvironment: string = core.getInput('containerAppEnvironment', { required: false }); + let containerAppEnvironment: string = githubActionsToolHelper.getInput('containerAppEnvironment', { required: false }); // See if we can reuse an existing Container App environment found in the resource group if (util.isNullOrEmpty(containerAppEnvironment)) { const existingContainerAppEnvironment: string = await this.appHelper.getExistingContainerAppEnvironment(resourceGroup); if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { - core.info(`Existing Container App environment found in resource group: ${existingContainerAppEnvironment}`); + githubActionsToolHelper.info(`Existing Container App environment found in resource group: ${existingContainerAppEnvironment}`); return existingContainerAppEnvironment } } @@ -265,7 +262,7 @@ export class azurecontainerapps { // Generate the Container App environment name if it was not provided if (util.isNullOrEmpty(containerAppEnvironment)) { containerAppEnvironment = `${containerAppName}-env`; - core.info(`Default Container App environment name: ${containerAppEnvironment}`); + githubActionsToolHelper.info(`Default Container App environment name: ${containerAppEnvironment}`); } // Determine if the Container App environment currently exists and create one if it doesn't @@ -281,15 +278,15 @@ export class azurecontainerapps { * Authenticates calls to the provided Azure Container Registry. */ private static async authenticateAzureContainerRegistryAsync() { - this.acrUsername = core.getInput('acrUsername', { required: false }); - this.acrPassword = core.getInput('acrPassword', { required: false }); + this.acrUsername = githubActionsToolHelper.getInput('acrUsername', { required: false }); + this.acrPassword = githubActionsToolHelper.getInput('acrPassword', { required: false }); // Login to ACR if credentials were provided if (!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword)) { - core.info(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); + githubActionsToolHelper.info(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); await this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword); } else { - core.info(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); + githubActionsToolHelper.info(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); await this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName); } } @@ -307,25 +304,25 @@ export class azurecontainerapps { */ private static async buildAndPushImageAsync() { // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = core.getInput('imageToBuild', { required: false }); + this.imageToBuild = githubActionsToolHelper.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.githubRunId}.${this.githubRunNumber}`; - core.info(`Default image to build: ${this.imageToBuild}`); + githubActionsToolHelper.info(`Default image to build: ${this.imageToBuild}`); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' if (util.isNullOrEmpty(this.imageToDeploy)) { this.imageToDeploy = this.imageToBuild; - core.info(`Default image to deploy: ${this.imageToDeploy}`); + githubActionsToolHelper.info(`Default image to deploy: ${this.imageToDeploy}`); } // Get Dockerfile to build, if provided, or check if one exists at the root of the provided application - let dockerfilePath: string = core.getInput('dockerfilePath', { required: false }); + let dockerfilePath: string = githubActionsToolHelper.getInput('dockerfilePath', { required: false }); if (util.isNullOrEmpty(dockerfilePath)) { - core.info(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); + githubActionsToolHelper.info(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); const rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); if (fs.existsSync(rootDockerfilePath)) { - core.info(`Dockerfile found at root of application source.`) + githubActionsToolHelper.info(`Dockerfile found at root of application source.`) dockerfilePath = rootDockerfilePath; } else { // No Dockerfile found or provided, build the image using the builder @@ -352,16 +349,16 @@ export class azurecontainerapps { private static async buildImageFromBuilderAsync(appSourcePath: string, imageToBuild: string) { // Install the pack CLI await this.appHelper.installPackCliAsync(); - core.info(`Successfully installed the pack CLI.`) + githubActionsToolHelper.info(`Successfully installed the pack CLI.`) // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = core.getInput('runtimeStack', { required: false }); + this.runtimeStack = githubActionsToolHelper.getInput('runtimeStack', { required: false }); if (util.isNullOrEmpty(this.runtimeStack)) { this.runtimeStack = await this.appHelper.determineRuntimeStackAsync(appSourcePath); - core.info(`Runtime stack determined to be: ${this.runtimeStack}`); + githubActionsToolHelper.info(`Runtime stack determined to be: ${this.runtimeStack}`); } - core.info(`Building image "${imageToBuild}" using the Oryx++ Builder`); + githubActionsToolHelper.info(`Building image "${imageToBuild}" using the Oryx++ Builder`); // Set the Oryx++ Builder as the default builder locally await this.appHelper.setDefaultBuilder(); @@ -380,7 +377,7 @@ export class azurecontainerapps { * @param imageToBuild - The name of the image to build. */ private static async builderImageFromDockerfile(appSourcePath: string, dockerfilePath: string, imageToBuild: string) { - core.info(`Building image "${imageToBuild}" using the provided Dockerfile`); + githubActionsToolHelper.info(`Building image "${imageToBuild}" using the provided Dockerfile`); await this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath); // If telemetry is enabled, log that the Dockerfile scenario was targeted for this task @@ -395,8 +392,8 @@ export class azurecontainerapps { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = core.getInput('ingress', { required: false }); - this.targetPort = core.getInput('targetPort', { required: false }); + this.ingress = githubActionsToolHelper.getInput('ingress', { required: false }); + this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. @@ -420,19 +417,19 @@ export class azurecontainerapps { // Set the ingress value to 'external' if it was not provided if (util.isNullOrEmpty(this.ingress)) { this.ingress = 'external'; - core.info(`Default ingress value: ${this.ingress}`); + githubActionsToolHelper.info(`Default ingress value: ${this.ingress}`); } // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' if (this.ingress == 'disabled') { this.ingressEnabled = false; - core.info(`Ingress is disabled for this Container App.`); + githubActionsToolHelper.info(`Ingress is disabled for this Container App.`); } // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = core.getInput('targetPort', { required: false }); + this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); if (util.isNullOrEmpty(this.targetPort)) { if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; @@ -440,13 +437,13 @@ export class azurecontainerapps { this.targetPort = '8080'; } - core.info(`Default target port: ${this.targetPort}`); + githubActionsToolHelper.info(`Default target port: ${this.targetPort}`); } // Set the target port to 80 if it was not provided or determined if (util.isNullOrEmpty(this.targetPort)) { this.targetPort = '80'; - core.info(`Default target port: ${this.targetPort}`); + githubActionsToolHelper.info(`Default target port: ${this.targetPort}`); } // Add the ingress value and target port to the optional arguments array @@ -456,7 +453,7 @@ export class azurecontainerapps { } } - const environmentVariables: string = core.getInput('environmentVariables', { required: false }); + const environmentVariables: string = githubActionsToolHelper.getInput('environmentVariables', { required: false }); // Add user-specified environment variables if (!util.isNullOrEmpty(environmentVariables)) { diff --git a/dist/index.js b/dist/index.js index 6d99726a..5729b38e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,7 +1,7 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 238: +/***/ 3238: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -44,14 +44,15 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.azurecontainerapps = void 0; -var core = __nccwpck_require__(195); -var fs = __nccwpck_require__(147); -var path = __nccwpck_require__(822); -var ContainerAppHelper_1 = __nccwpck_require__(929); -var ContainerRegistryHelper_1 = __nccwpck_require__(769); -var TelemetryHelper_1 = __nccwpck_require__(166); -var Utility_1 = __nccwpck_require__(135); +var fs = __nccwpck_require__(7147); +var path = __nccwpck_require__(1017); +var ContainerAppHelper_1 = __nccwpck_require__(2929); +var ContainerRegistryHelper_1 = __nccwpck_require__(4769); +var TelemetryHelper_1 = __nccwpck_require__(7166); +var Utility_1 = __nccwpck_require__(2135); +var GithubActionsToolHelper_1 = __nccwpck_require__(2153); var util = new Utility_1.Utility(); +var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); var azurecontainerapps = /** @class */ (function () { function azurecontainerapps() { } @@ -61,7 +62,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - disableTelemetry = core.getInput('disableTelemetry').toLowerCase() === 'true'; + disableTelemetry = githubActionsToolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; this.initializeHelpers(disableTelemetry); _a.label = 1; case 1: @@ -108,7 +109,7 @@ var azurecontainerapps = /** @class */ (function () { return [3 /*break*/, 12]; case 9: err_1 = _a.sent(); - core.setFailed(err_1.message); + githubActionsToolHelper.setFailed(err_1.message); this.telemetryHelper.setFailedResult(err_1.message); return [3 /*break*/, 12]; case 10: @@ -141,21 +142,21 @@ var azurecontainerapps = /** @class */ (function () { */ azurecontainerapps.validateSupportedScenarioArguments = function () { // Get the path to the application source to build and run, if provided - this.appSourcePath = core.getInput('appSourcePath', { required: false }); + this.appSourcePath = githubActionsToolHelper.getInput('appSourcePath', { required: false }); // Get the name of the ACR instance to push images to, if provided - this.acrName = core.getInput('acrName', { required: false }); + this.acrName = githubActionsToolHelper.getInput('acrName', { required: false }); // Get the previously built image to deploy, if provided - this.imageToDeploy = core.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = githubActionsToolHelper.getInput('imageToDeploy', { required: false }); // Get the YAML configuration file, if provided - this.yamlConfigPath = core.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = githubActionsToolHelper.getInput('yamlConfigPath', { required: false }); // Ensure that acrName is also provided if appSourcePath is provided if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { - core.error("The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."); + githubActionsToolHelper.error("The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."); throw Error("The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { - core.error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); + githubActionsToolHelper.error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); throw Error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); } }; @@ -228,12 +229,9 @@ var azurecontainerapps = /** @class */ (function () { * @returns The name of the Container App to use for the task. */ azurecontainerapps.getContainerAppName = function () { - var containerAppName = core.getInput('containerAppName', { required: false }); + var containerAppName = githubActionsToolHelper.getInput('containerAppName', { required: false }); if (util.isNullOrEmpty(containerAppName)) { - containerAppName = "gh-action-app-" + this.githubRunId + "-" + this.githubRunNumber; - // Replace all '.' characters with '-' characters in the Container App name - containerAppName = containerAppName.replace(/\./gi, "-"); - core.info("Default Container App name: " + containerAppName); + return githubActionsToolHelper.getContainerAppName(containerAppName); } return containerAppName; }; @@ -248,7 +246,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - location = core.getInput('location', { required: false }); + location = githubActionsToolHelper.getInput('location', { required: false }); if (!util.isNullOrEmpty(location)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getDefaultContainerAppLocation()]; case 1: @@ -273,10 +271,10 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - resourceGroup = core.getInput('resourceGroup', { required: false }); + resourceGroup = githubActionsToolHelper.getInput('resourceGroup', { required: false }); if (!util.isNullOrEmpty(resourceGroup)) return [3 /*break*/, 3]; resourceGroup = containerAppName + "-rg"; - core.info("Default resource group name: " + resourceGroup); + githubActionsToolHelper.info("Default resource group name: " + resourceGroup); return [4 /*yield*/, this.appHelper.doesResourceGroupExist(resourceGroup)]; case 1: resourceGroupExists = _a.sent(); @@ -306,13 +304,13 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - containerAppEnvironment = core.getInput('containerAppEnvironment', { required: false }); + containerAppEnvironment = githubActionsToolHelper.getInput('containerAppEnvironment', { required: false }); if (!util.isNullOrEmpty(containerAppEnvironment)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getExistingContainerAppEnvironment(resourceGroup)]; case 1: existingContainerAppEnvironment = _a.sent(); if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { - core.info("Existing Container App environment found in resource group: " + existingContainerAppEnvironment); + githubActionsToolHelper.info("Existing Container App environment found in resource group: " + existingContainerAppEnvironment); return [2 /*return*/, existingContainerAppEnvironment]; } _a.label = 2; @@ -320,7 +318,7 @@ var azurecontainerapps = /** @class */ (function () { // Generate the Container App environment name if it was not provided if (util.isNullOrEmpty(containerAppEnvironment)) { containerAppEnvironment = containerAppName + "-env"; - core.info("Default Container App environment name: " + containerAppEnvironment); + githubActionsToolHelper.info("Default Container App environment name: " + containerAppEnvironment); } return [4 /*yield*/, this.appHelper.doesContainerAppEnvironmentExist(containerAppEnvironment, resourceGroup)]; case 3: @@ -343,16 +341,16 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - this.acrUsername = core.getInput('acrUsername', { required: false }); - this.acrPassword = core.getInput('acrPassword', { required: false }); + this.acrUsername = githubActionsToolHelper.getInput('acrUsername', { required: false }); + this.acrPassword = githubActionsToolHelper.getInput('acrPassword', { required: false }); if (!(!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 2]; - core.info("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); + githubActionsToolHelper.info("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); return [4 /*yield*/, this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword)]; case 1: _a.sent(); return [3 /*break*/, 4]; case 2: - core.info("No ACR credentials provided; attempting to log in to ACR instance \"" + this.acrName + "\" with access token"); + githubActionsToolHelper.info("No ACR credentials provided; attempting to log in to ACR instance \"" + this.acrName + "\" with access token"); return [4 /*yield*/, this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName)]; case 3: _a.sent(); @@ -379,22 +377,22 @@ var azurecontainerapps = /** @class */ (function () { switch (_a.label) { case 0: // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = core.getInput('imageToBuild', { required: false }); + this.imageToBuild = githubActionsToolHelper.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.githubRunId + "." + this.githubRunNumber; - core.info("Default image to build: " + this.imageToBuild); + githubActionsToolHelper.info("Default image to build: " + this.imageToBuild); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' if (util.isNullOrEmpty(this.imageToDeploy)) { this.imageToDeploy = this.imageToBuild; - core.info("Default image to deploy: " + this.imageToDeploy); + githubActionsToolHelper.info("Default image to deploy: " + this.imageToDeploy); } - dockerfilePath = core.getInput('dockerfilePath', { required: false }); + dockerfilePath = githubActionsToolHelper.getInput('dockerfilePath', { required: false }); if (!util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 4]; - core.info("No Dockerfile path provided; checking for Dockerfile at root of application source."); + githubActionsToolHelper.info("No Dockerfile path provided; checking for Dockerfile at root of application source."); rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); if (!fs.existsSync(rootDockerfilePath)) return [3 /*break*/, 1]; - core.info("Dockerfile found at root of application source."); + githubActionsToolHelper.info("Dockerfile found at root of application source."); dockerfilePath = rootDockerfilePath; return [3 /*break*/, 3]; case 1: @@ -443,18 +441,18 @@ var azurecontainerapps = /** @class */ (function () { case 1: // Install the pack CLI _b.sent(); - core.info("Successfully installed the pack CLI."); + githubActionsToolHelper.info("Successfully installed the pack CLI."); // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = core.getInput('runtimeStack', { required: false }); + this.runtimeStack = githubActionsToolHelper.getInput('runtimeStack', { required: false }); if (!util.isNullOrEmpty(this.runtimeStack)) return [3 /*break*/, 3]; _a = this; return [4 /*yield*/, this.appHelper.determineRuntimeStackAsync(appSourcePath)]; case 2: _a.runtimeStack = _b.sent(); - core.info("Runtime stack determined to be: " + this.runtimeStack); + githubActionsToolHelper.info("Runtime stack determined to be: " + this.runtimeStack); _b.label = 3; case 3: - core.info("Building image \"" + imageToBuild + "\" using the Oryx++ Builder"); + githubActionsToolHelper.info("Building image \"" + imageToBuild + "\" using the Oryx++ Builder"); // Set the Oryx++ Builder as the default builder locally return [4 /*yield*/, this.appHelper.setDefaultBuilder()]; case 4: @@ -483,7 +481,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.info("Building image \"" + imageToBuild + "\" using the provided Dockerfile"); + githubActionsToolHelper.info("Building image \"" + imageToBuild + "\" using the provided Dockerfile"); return [4 /*yield*/, this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath)]; case 1: _a.sent(); @@ -501,8 +499,8 @@ var azurecontainerapps = /** @class */ (function () { azurecontainerapps.setupContainerAppProperties = function () { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = core.getInput('ingress', { required: false }); - this.targetPort = core.getInput('targetPort', { required: false }); + this.ingress = githubActionsToolHelper.getInput('ingress', { required: false }); + this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. this.shouldUseUpdateCommand = this.containerAppExists && @@ -519,17 +517,17 @@ var azurecontainerapps = /** @class */ (function () { // Set the ingress value to 'external' if it was not provided if (util.isNullOrEmpty(this.ingress)) { this.ingress = 'external'; - core.info("Default ingress value: " + this.ingress); + githubActionsToolHelper.info("Default ingress value: " + this.ingress); } // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' if (this.ingress == 'disabled') { this.ingressEnabled = false; - core.info("Ingress is disabled for this Container App."); + githubActionsToolHelper.info("Ingress is disabled for this Container App."); } // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = core.getInput('targetPort', { required: false }); + this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); if (util.isNullOrEmpty(this.targetPort)) { if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; @@ -537,12 +535,12 @@ var azurecontainerapps = /** @class */ (function () { else { this.targetPort = '8080'; } - core.info("Default target port: " + this.targetPort); + githubActionsToolHelper.info("Default target port: " + this.targetPort); } // Set the target port to 80 if it was not provided or determined if (util.isNullOrEmpty(this.targetPort)) { this.targetPort = '80'; - core.info("Default target port: " + this.targetPort); + githubActionsToolHelper.info("Default target port: " + this.targetPort); } // Add the ingress value and target port to the optional arguments array // Note: this step should be skipped if we're updating an existing Container App (ingress is enabled via a separate command) @@ -550,7 +548,7 @@ var azurecontainerapps = /** @class */ (function () { this.commandLineArgs.push("--target-port " + this.targetPort); } } - var environmentVariables = core.getInput('environmentVariables', { required: false }); + var environmentVariables = githubActionsToolHelper.getInput('environmentVariables', { required: false }); // Add user-specified environment variables if (!util.isNullOrEmpty(environmentVariables)) { // The --replace-env-vars flag is only used for the 'update' command, @@ -628,8 +626,8 @@ var azurecontainerapps = /** @class */ (function () { }); }; // GitHub Action properties - azurecontainerapps.githubRunId = process.env.GITHUB_RUN_ID; - azurecontainerapps.githubRunNumber = process.env.GITHUB_RUN_NUMBER; + azurecontainerapps.githubRunId = githubActionsToolHelper.getGithubRunId(); + azurecontainerapps.githubRunNumber = githubActionsToolHelper.getGithubRunNumber(); return azurecontainerapps; }()); exports.azurecontainerapps = azurecontainerapps; @@ -638,7 +636,7 @@ azurecontainerapps.runMain(); /***/ }), -/***/ 688: +/***/ 5688: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -664,7 +662,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.issue = exports.issueCommand = void 0; -const os = __importStar(__nccwpck_require__(37)); +const os = __importStar(__nccwpck_require__(2037)); const utils_1 = __nccwpck_require__(869); /** * Commands @@ -737,7 +735,7 @@ function escapeProperty(s) { /***/ }), -/***/ 195: +/***/ 3195: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -772,12 +770,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; -const command_1 = __nccwpck_require__(688); -const file_command_1 = __nccwpck_require__(930); +const command_1 = __nccwpck_require__(5688); +const file_command_1 = __nccwpck_require__(3930); const utils_1 = __nccwpck_require__(869); -const os = __importStar(__nccwpck_require__(37)); -const path = __importStar(__nccwpck_require__(822)); -const oidc_utils_1 = __nccwpck_require__(755); +const os = __importStar(__nccwpck_require__(2037)); +const path = __importStar(__nccwpck_require__(1017)); +const oidc_utils_1 = __nccwpck_require__(1755); /** * The code to exit an action */ @@ -1062,12 +1060,12 @@ exports.getIDToken = getIDToken; /** * Summary exports */ -var summary_1 = __nccwpck_require__(606); +var summary_1 = __nccwpck_require__(8606); Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); /** * @deprecated use core.summary */ -var summary_2 = __nccwpck_require__(606); +var summary_2 = __nccwpck_require__(8606); Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); /** * Path exports @@ -1080,7 +1078,7 @@ Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: funct /***/ }), -/***/ 930: +/***/ 3930: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1109,9 +1107,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__nccwpck_require__(147)); -const os = __importStar(__nccwpck_require__(37)); -const uuid_1 = __nccwpck_require__(814); +const fs = __importStar(__nccwpck_require__(7147)); +const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5814); const utils_1 = __nccwpck_require__(869); function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; @@ -1145,7 +1143,7 @@ exports.prepareKeyValueMessage = prepareKeyValueMessage; /***/ }), -/***/ 755: +/***/ 1755: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1161,9 +1159,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.OidcClient = void 0; -const http_client_1 = __nccwpck_require__(780); -const auth_1 = __nccwpck_require__(833); -const core_1 = __nccwpck_require__(195); +const http_client_1 = __nccwpck_require__(9780); +const auth_1 = __nccwpck_require__(8833); +const core_1 = __nccwpck_require__(3195); class OidcClient { static createHttpClient(allowRetry = true, maxRetry = 10) { const requestOptions = { @@ -1255,7 +1253,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; -const path = __importStar(__nccwpck_require__(822)); +const path = __importStar(__nccwpck_require__(1017)); /** * toPosixPath converts the given path to the posix form. On Windows, \\ will be * replaced with /. @@ -1294,7 +1292,7 @@ exports.toPlatformPath = toPlatformPath; /***/ }), -/***/ 606: +/***/ 8606: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1310,8 +1308,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; -const os_1 = __nccwpck_require__(37); -const fs_1 = __nccwpck_require__(147); +const os_1 = __nccwpck_require__(2037); +const fs_1 = __nccwpck_require__(7147); const { access, appendFile, writeFile } = fs_1.promises; exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; @@ -1631,7 +1629,7 @@ exports.toCommandProperties = toCommandProperties; /***/ }), -/***/ 714: +/***/ 9714: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1666,8 +1664,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getExecOutput = exports.exec = void 0; -const string_decoder_1 = __nccwpck_require__(576); -const tr = __importStar(__nccwpck_require__(315)); +const string_decoder_1 = __nccwpck_require__(1576); +const tr = __importStar(__nccwpck_require__(5315)); /** * Exec a command. * Output will be streamed to the live console. @@ -1741,7 +1739,7 @@ exports.getExecOutput = getExecOutput; /***/ }), -/***/ 315: +/***/ 5315: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -1776,13 +1774,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.argStringToArray = exports.ToolRunner = void 0; -const os = __importStar(__nccwpck_require__(37)); -const events = __importStar(__nccwpck_require__(361)); -const child = __importStar(__nccwpck_require__(81)); -const path = __importStar(__nccwpck_require__(822)); -const io = __importStar(__nccwpck_require__(529)); -const ioUtil = __importStar(__nccwpck_require__(821)); -const timers_1 = __nccwpck_require__(512); +const os = __importStar(__nccwpck_require__(2037)); +const events = __importStar(__nccwpck_require__(2361)); +const child = __importStar(__nccwpck_require__(2081)); +const path = __importStar(__nccwpck_require__(1017)); +const io = __importStar(__nccwpck_require__(9529)); +const ioUtil = __importStar(__nccwpck_require__(7821)); +const timers_1 = __nccwpck_require__(9512); /* eslint-disable @typescript-eslint/unbound-method */ const IS_WINDOWS = process.platform === 'win32'; /* @@ -2366,7 +2364,7 @@ class ExecState extends events.EventEmitter { /***/ }), -/***/ 833: +/***/ 8833: /***/ (function(__unused_webpack_module, exports) { "use strict"; @@ -2454,7 +2452,7 @@ exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHand /***/ }), -/***/ 780: +/***/ 9780: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -2490,10 +2488,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; -const http = __importStar(__nccwpck_require__(685)); -const https = __importStar(__nccwpck_require__(687)); -const pm = __importStar(__nccwpck_require__(492)); -const tunnel = __importStar(__nccwpck_require__(41)); +const http = __importStar(__nccwpck_require__(3685)); +const https = __importStar(__nccwpck_require__(5687)); +const pm = __importStar(__nccwpck_require__(4492)); +const tunnel = __importStar(__nccwpck_require__(9041)); var HttpCodes; (function (HttpCodes) { HttpCodes[HttpCodes["OK"] = 200] = "OK"; @@ -3079,7 +3077,7 @@ const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCa /***/ }), -/***/ 492: +/***/ 4492: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -3168,7 +3166,7 @@ function isLoopbackAddress(host) { /***/ }), -/***/ 821: +/***/ 7821: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -3204,8 +3202,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge var _a; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; -const fs = __importStar(__nccwpck_require__(147)); -const path = __importStar(__nccwpck_require__(822)); +const fs = __importStar(__nccwpck_require__(7147)); +const path = __importStar(__nccwpck_require__(1017)); _a = fs.promises // export const {open} = 'fs' , exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; @@ -3358,7 +3356,7 @@ exports.getCmdPath = getCmdPath; /***/ }), -/***/ 529: +/***/ 9529: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -3393,9 +3391,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; -const assert_1 = __nccwpck_require__(491); -const path = __importStar(__nccwpck_require__(822)); -const ioUtil = __importStar(__nccwpck_require__(821)); +const assert_1 = __nccwpck_require__(9491); +const path = __importStar(__nccwpck_require__(1017)); +const ioUtil = __importStar(__nccwpck_require__(7821)); /** * Copies a file or folder. * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js @@ -3664,27 +3662,27 @@ function copyFile(srcFile, destFile, force) { /***/ }), -/***/ 41: +/***/ 9041: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -module.exports = __nccwpck_require__(111); +module.exports = __nccwpck_require__(7111); /***/ }), -/***/ 111: +/***/ 7111: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; -var net = __nccwpck_require__(808); -var tls = __nccwpck_require__(404); -var http = __nccwpck_require__(685); -var https = __nccwpck_require__(687); -var events = __nccwpck_require__(361); -var assert = __nccwpck_require__(491); -var util = __nccwpck_require__(837); +var net = __nccwpck_require__(1808); +var tls = __nccwpck_require__(4404); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var events = __nccwpck_require__(2361); +var assert = __nccwpck_require__(9491); +var util = __nccwpck_require__(3837); exports.httpOverHttp = httpOverHttp; @@ -3944,7 +3942,7 @@ exports.debug = debug; // for test /***/ }), -/***/ 814: +/***/ 5814: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4008,29 +4006,29 @@ Object.defineProperty(exports, "parse", ({ } })); -var _v = _interopRequireDefault(__nccwpck_require__(471)); +var _v = _interopRequireDefault(__nccwpck_require__(6471)); -var _v2 = _interopRequireDefault(__nccwpck_require__(384)); +var _v2 = _interopRequireDefault(__nccwpck_require__(3384)); -var _v3 = _interopRequireDefault(__nccwpck_require__(940)); +var _v3 = _interopRequireDefault(__nccwpck_require__(5940)); -var _v4 = _interopRequireDefault(__nccwpck_require__(193)); +var _v4 = _interopRequireDefault(__nccwpck_require__(9193)); -var _nil = _interopRequireDefault(__nccwpck_require__(654)); +var _nil = _interopRequireDefault(__nccwpck_require__(8654)); -var _version = _interopRequireDefault(__nccwpck_require__(362)); +var _version = _interopRequireDefault(__nccwpck_require__(2362)); -var _validate = _interopRequireDefault(__nccwpck_require__(815)); +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); -var _stringify = _interopRequireDefault(__nccwpck_require__(183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); -var _parse = _interopRequireDefault(__nccwpck_require__(108)); +var _parse = _interopRequireDefault(__nccwpck_require__(5108)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), -/***/ 313: +/***/ 9313: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4041,7 +4039,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4060,7 +4058,7 @@ exports["default"] = _default; /***/ }), -/***/ 654: +/***/ 8654: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -4075,7 +4073,7 @@ exports["default"] = _default; /***/ }), -/***/ 108: +/***/ 5108: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4086,7 +4084,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(815)); +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4127,7 +4125,7 @@ exports["default"] = _default; /***/ }), -/***/ 629: +/***/ 1629: /***/ ((__unused_webpack_module, exports) => { "use strict"; @@ -4142,7 +4140,7 @@ exports["default"] = _default; /***/ }), -/***/ 271: +/***/ 9271: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4153,7 +4151,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = rng; -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4173,7 +4171,7 @@ function rng() { /***/ }), -/***/ 17: +/***/ 2017: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4184,7 +4182,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _crypto = _interopRequireDefault(__nccwpck_require__(113)); +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4203,7 +4201,7 @@ exports["default"] = _default; /***/ }), -/***/ 183: +/***/ 5183: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4214,7 +4212,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(815)); +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4249,7 +4247,7 @@ exports["default"] = _default; /***/ }), -/***/ 471: +/***/ 6471: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4260,9 +4258,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(271)); +var _rng = _interopRequireDefault(__nccwpck_require__(9271)); -var _stringify = _interopRequireDefault(__nccwpck_require__(183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4363,7 +4361,7 @@ exports["default"] = _default; /***/ }), -/***/ 384: +/***/ 3384: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4374,9 +4372,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(717)); +var _v = _interopRequireDefault(__nccwpck_require__(5717)); -var _md = _interopRequireDefault(__nccwpck_require__(313)); +var _md = _interopRequireDefault(__nccwpck_require__(9313)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4386,7 +4384,7 @@ exports["default"] = _default; /***/ }), -/***/ 717: +/***/ 5717: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4398,9 +4396,9 @@ Object.defineProperty(exports, "__esModule", ({ exports["default"] = _default; exports.URL = exports.DNS = void 0; -var _stringify = _interopRequireDefault(__nccwpck_require__(183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); -var _parse = _interopRequireDefault(__nccwpck_require__(108)); +var _parse = _interopRequireDefault(__nccwpck_require__(5108)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4471,7 +4469,7 @@ function _default(name, version, hashfunc) { /***/ }), -/***/ 940: +/***/ 5940: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4482,9 +4480,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _rng = _interopRequireDefault(__nccwpck_require__(271)); +var _rng = _interopRequireDefault(__nccwpck_require__(9271)); -var _stringify = _interopRequireDefault(__nccwpck_require__(183)); +var _stringify = _interopRequireDefault(__nccwpck_require__(5183)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4515,7 +4513,7 @@ exports["default"] = _default; /***/ }), -/***/ 193: +/***/ 9193: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4526,9 +4524,9 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _v = _interopRequireDefault(__nccwpck_require__(717)); +var _v = _interopRequireDefault(__nccwpck_require__(5717)); -var _sha = _interopRequireDefault(__nccwpck_require__(17)); +var _sha = _interopRequireDefault(__nccwpck_require__(2017)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4538,7 +4536,7 @@ exports["default"] = _default; /***/ }), -/***/ 815: +/***/ 9815: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4549,7 +4547,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _regex = _interopRequireDefault(__nccwpck_require__(629)); +var _regex = _interopRequireDefault(__nccwpck_require__(1629)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4562,7 +4560,7 @@ exports["default"] = _default; /***/ }), -/***/ 362: +/***/ 2362: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; @@ -4573,7 +4571,7 @@ Object.defineProperty(exports, "__esModule", ({ })); exports["default"] = void 0; -var _validate = _interopRequireDefault(__nccwpck_require__(815)); +var _validate = _interopRequireDefault(__nccwpck_require__(9815)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -4590,7 +4588,7 @@ exports["default"] = _default; /***/ }), -/***/ 929: +/***/ 2929: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -4633,17 +4631,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.ContainerAppHelper = void 0; -var core = __nccwpck_require__(195); -var io = __nccwpck_require__(529); -var exec = __nccwpck_require__(714); -var path = __nccwpck_require__(822); -var os = __nccwpck_require__(37); -var Utility_1 = __nccwpck_require__(135); -var fs = __nccwpck_require__(147); +var path = __nccwpck_require__(1017); +var os = __nccwpck_require__(2037); +var Utility_1 = __nccwpck_require__(2135); +var GithubActionsToolHelper_1 = __nccwpck_require__(2153); +var fs = __nccwpck_require__(7147); var ORYX_CLI_IMAGE = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; var ORYX_BUILDER_IMAGE = 'mcr.microsoft.com/oryx/builder:20230208.1'; var IS_WINDOWS_AGENT = os.platform() == 'win32'; var PACK_CMD = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; +var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); +var util = new Utility_1.Utility(); var ContainerAppHelper = /** @class */ (function () { function ContainerAppHelper(disableTelemetry) { this.disableTelemetry = false; @@ -4663,7 +4661,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + githubActionsToolHelper.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4671,13 +4669,13 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command_1.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command_1.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_1 = _a.sent(); - core.error(err_1.message); + githubActionsToolHelper.error(err_1.message); throw err_1; case 4: return [2 /*return*/]; } @@ -4696,18 +4694,18 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); + githubActionsToolHelper.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_2 = _a.sent(); - core.error(err_2.message); + githubActionsToolHelper.error(err_2.message); throw err_2; case 4: return [2 /*return*/]; } @@ -4727,7 +4725,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + githubActionsToolHelper.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4735,13 +4733,13 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_2 += " " + val; }); - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command_2.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command_2.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_3 = _a.sent(); - core.error(err_3.message); + githubActionsToolHelper.error(err_3.message); throw err_3; case 4: return [2 /*return*/]; } @@ -4759,12 +4757,11 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.updateContainerAppWithUp = function (containerAppName, resourceGroup, imageToDeploy, optionalCmdArgs, ingress, targetPort) { return __awaiter(this, void 0, void 0, function () { - var util, command_3, err_4; + var command_3, err_4; return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); - util = new Utility_1.Utility(); + githubActionsToolHelper.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4778,13 +4775,13 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(targetPort)) { command_3 += " --target-port " + targetPort; } - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command_3.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command_3.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_4 = _a.sent(); - core.error(err_4.message); + githubActionsToolHelper.error(err_4.message); throw err_4; case 4: return [2 /*return*/]; } @@ -4803,18 +4800,18 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); + githubActionsToolHelper.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_5 = _a.sent(); - core.error(err_5.message); + githubActionsToolHelper.error(err_5.message); throw err_5; case 4: return [2 /*return*/]; } @@ -4829,22 +4826,22 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesContainerAppExist = function (containerAppName, resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, exitCode, err_6; + var command, executionResult, err_6; return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to determine if Container App with name \"" + containerAppName + "\" exists in resource group \"" + resourceGroup + "\""); + githubActionsToolHelper.debug("Attempting to determine if Container App with name \"" + containerAppName + "\" exists in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, exec.exec("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: - exitCode = _a.sent(); - return [2 /*return*/, exitCode === 0]; + executionResult = _a.sent(); + return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_6 = _a.sent(); - core.warning(err_6.message); + githubActionsToolHelper.warning(err_6.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4859,22 +4856,22 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesContainerAppEnvironmentExist = function (containerAppEnvironment, resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, exitCode, err_7; + var command, executionResult, err_7; return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to determine if Container App Environment with name \"" + containerAppEnvironment + "\" exists in resource group \"" + resourceGroup + "\""); + githubActionsToolHelper.debug("Attempting to determine if Container App Environment with name \"" + containerAppEnvironment + "\" exists in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, exec.exec("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: - exitCode = _a.sent(); - return [2 /*return*/, exitCode === 0]; + executionResult = _a.sent(); + return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_7 = _a.sent(); - core.warning(err_7.message); + githubActionsToolHelper.warning(err_7.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4888,22 +4885,22 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.doesResourceGroupExist = function (resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var command, exitCode, err_8; + var command, executionResult, err_8; return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to determine if resource group \"" + resourceGroup + "\" exists"); + githubActionsToolHelper.debug("Attempting to determine if resource group \"" + resourceGroup + "\" exists"); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "group show -n " + resourceGroup + " -o none"; - return [4 /*yield*/, exec.exec("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: - exitCode = _a.sent(); - return [2 /*return*/, exitCode === 0]; + executionResult = _a.sent(); + return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_8 = _a.sent(); - core.warning(err_8.message); + githubActionsToolHelper.warning(err_8.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4920,19 +4917,19 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to get the default location for the Container App service for the subscription."); + githubActionsToolHelper.debug("Attempting to get the default location for the Container App service for the subscription."); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); args = ["provider", "show", "-n", "Microsoft.App", "--query", "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"]; - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", args)]; + return [4 /*yield*/, util.executeAndThrowIfError("az", args)]; case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned return [2 /*return*/, !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; case 3: err_9 = _a.sent(); - core.warning(err_9.message); + githubActionsToolHelper.warning(err_9.message); return [2 /*return*/, "eastus2"]; case 4: return [2 /*return*/]; } @@ -4950,18 +4947,18 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to create resource group \"" + name + "\" in location \"" + location + "\""); + githubActionsToolHelper.debug("Attempting to create resource group \"" + name + "\" in location \"" + location + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "group create -n " + name + " -l " + location; - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_10 = _a.sent(); - core.error(err_10.message); + githubActionsToolHelper.error(err_10.message); throw err_10; case 4: return [2 /*return*/]; } @@ -4979,18 +4976,18 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to get the existing Container App Environment in resource group \"" + resourceGroup + "\""); + githubActionsToolHelper.debug("Attempting to get the existing Container App Environment in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); args = ["containerapp", "env", "list", "-g", "" + resourceGroup, "--query", "[0].name"]; - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", args)]; + return [4 /*yield*/, util.executeAndThrowIfError("az", args)]; case 2: executionResult = _a.sent(); return [2 /*return*/, !executionResult.stderr ? executionResult.stdout : null]; case 3: err_11 = _a.sent(); - core.warning(err_11.message); + githubActionsToolHelper.warning(err_11.message); return [2 /*return*/, null]; case 4: return [2 /*return*/]; } @@ -5010,7 +5007,7 @@ var ContainerAppHelper = /** @class */ (function () { switch (_a.label) { case 0: util = new Utility_1.Utility(); - core.debug("Attempting to create Container App Environment with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + githubActionsToolHelper.debug("Attempting to create Container App Environment with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5018,13 +5015,13 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(location)) { args.push("-l", "" + location); } - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", args)]; + return [4 /*yield*/, util.executeAndThrowIfError("az", args)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_12 = _a.sent(); - core.error(err_12.message); + githubActionsToolHelper.error(err_12.message); throw err_12; case 4: return [2 /*return*/]; } @@ -5042,18 +5039,18 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to disable ingress for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + githubActionsToolHelper.debug("Attempting to disable ingress for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "containerapp ingress disable -n " + name + " -g " + resourceGroup; - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_13 = _a.sent(); - core.error(err_13.message); + githubActionsToolHelper.error(err_13.message); throw err_13; case 4: return [2 /*return*/]; } @@ -5074,18 +5071,18 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to set the ACR details for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + githubActionsToolHelper.debug("Attempting to set the ACR details for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_14 = _a.sent(); - core.error(err_14.message); + githubActionsToolHelper.error(err_14.message); throw err_14; case 4: return [2 /*return*/]; } @@ -5104,21 +5101,21 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to create a runnable application image using the Oryx++ Builder with image name \"" + imageToDeploy + "\""); + githubActionsToolHelper.debug("Attempting to create a runnable application image using the Oryx++ Builder with image name \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - telemetryArg = "CALLER_ID=github-actions-v1"; + telemetryArg = githubActionsToolHelper.getTelemetryArg(); if (this.disableTelemetry) { telemetryArg = "ORYX_DISABLE_TELEMETRY=true"; } - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("" + PACK_CMD, ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, '--env', "" + telemetryArg])]; + return [4 /*yield*/, util.executeAndThrowIfError("" + PACK_CMD, ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, '--env', "" + telemetryArg])]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_15 = _a.sent(); - core.error(err_15.message); + githubActionsToolHelper.error(err_15.message); throw err_15; case 4: return [2 /*return*/]; } @@ -5138,21 +5135,21 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to create a runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); + githubActionsToolHelper.debug("Attempting to create a runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, io.which("docker", true)]; + return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, ['build', '--file', "" + dockerfilePath, "" + appSourcePath, '--tag', "" + imageToDeploy])]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ['build', '--file', "" + dockerfilePath, "" + appSourcePath, '--tag', "" + imageToDeploy])]; case 3: _a.sent(); - core.debug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); + githubActionsToolHelper.debug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); return [3 /*break*/, 5]; case 4: err_16 = _a.sent(); - core.setFailed(err_16.message); + githubActionsToolHelper.error(err_16.message); throw err_16; case 5: return [2 /*return*/]; } @@ -5170,15 +5167,15 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug('Attempting to determine the runtime stack needed for the provided application source'); + githubActionsToolHelper.debug('Attempting to determine the runtime stack needed for the provided application source'); _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, io.which("docker", true)]; + return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', appSourcePath + ":/app", "" + ORYX_CLI_IMAGE, '/bin/bash', '-c', "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"]) + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', appSourcePath + ":/app", "" + ORYX_CLI_IMAGE, '/bin/bash', '-c', "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"]) // Read the temp file to get the runtime stack into a variable ]; case 3: @@ -5189,19 +5186,19 @@ var ContainerAppHelper = /** @class */ (function () { var lines = data.split('\n'); return lines[0]; })["catch"](function (err) { - core.setFailed(err.message); + githubActionsToolHelper.error(err.message); throw err; }); // Delete the temp file fs.unlink(oryxRuntimeTxtPath_1, function (err) { if (err) { - core.warning("Unable to delete the temporary file \"" + oryxRuntimeTxtPath_1 + "\". Error: " + err.message); + githubActionsToolHelper.warning("Unable to delete the temporary file \"" + oryxRuntimeTxtPath_1 + "\". Error: " + err.message); } }); return [2 /*return*/, runtimeStack]; case 4: err_17 = _a.sent(); - core.setFailed(err_17.message); + githubActionsToolHelper.error(err_17.message); throw err_17; case 5: return [2 /*return*/]; } @@ -5218,17 +5215,17 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); + githubActionsToolHelper.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError("" + PACK_CMD, ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; + return [4 /*yield*/, util.executeAndThrowIfError("" + PACK_CMD, ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_18 = _a.sent(); - core.setFailed(err_18.message); + githubActionsToolHelper.error(err_18.message); throw err_18; case 4: return [2 /*return*/]; } @@ -5245,7 +5242,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug('Attempting to install the pack CLI'); + githubActionsToolHelper.debug('Attempting to install the pack CLI'); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5266,14 +5263,13 @@ var ContainerAppHelper = /** @class */ (function () { args = ['-c', command]; commandLine = 'bash'; } - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(commandLine, args)]; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine, args)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_19 = _a.sent(); - core.error("Unable to install the pack CLI. Error: " + err_19.message); - core.setFailed(err_19.message); + githubActionsToolHelper.error("Unable to install the pack CLI. Error: " + err_19.message); throw err_19; case 4: return [2 /*return*/]; } @@ -5287,7 +5283,7 @@ exports.ContainerAppHelper = ContainerAppHelper; /***/ }), -/***/ 769: +/***/ 4769: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -5330,11 +5326,11 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.ContainerRegistryHelper = void 0; -var core = __nccwpck_require__(195); -var exec = __nccwpck_require__(714); -var io = __nccwpck_require__(529); -var os = __nccwpck_require__(37); -var Utility_1 = __nccwpck_require__(135); +var os = __nccwpck_require__(2037); +var Utility_1 = __nccwpck_require__(2135); +var GithubActionsToolHelper_1 = __nccwpck_require__(2153); +var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); +var util = new Utility_1.Utility(); var ContainerRegistryHelper = /** @class */ (function () { function ContainerRegistryHelper() { } @@ -5350,17 +5346,17 @@ var ContainerRegistryHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + githubActionsToolHelper.debug("Attempting to log in to ACR instance \"" + acrName + "\" with username and password credentials"); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, exec.exec('docker', ["login", "--password-stdin", "--username", "" + acrUsername, acrName + ".azurecr.io"], { input: Buffer.from(acrPassword) })]; + return [4 /*yield*/, githubActionsToolHelper.exec('docker', ["login", "--password-stdin", "--username", "" + acrUsername, acrName + ".azurecr.io"], { input: Buffer.from(acrPassword) })]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_1 = _a.sent(); - core.error("Failed to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + githubActionsToolHelper.error("Failed to log in to ACR instance \"" + acrName + "\" with username and password credentials"); throw err_1; case 4: return [2 /*return*/]; } @@ -5374,23 +5370,23 @@ var ContainerRegistryHelper = /** @class */ (function () { */ ContainerRegistryHelper.prototype.loginAcrWithAccessTokenAsync = function (acrName) { return __awaiter(this, void 0, void 0, function () { - var command, shell, err_2; + var command, commandLine, err_2; return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to log in to ACR instance \"" + acrName + "\" with access token"); + githubActionsToolHelper.debug("Attempting to log in to ACR instance \"" + acrName + "\" with access token"); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); command = "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"; - shell = os.platform() === 'win32' ? 'pwsh' : 'bash'; - return [4 /*yield*/, exec.exec(shell, ['-c', command])]; + commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine, ['-c', command])]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_2 = _a.sent(); - core.error("Failed to log in to ACR instance \"" + acrName + "\" with access token"); + githubActionsToolHelper.error("Failed to log in to ACR instance \"" + acrName + "\" with access token"); throw err_2; case 4: return [2 /*return*/]; } @@ -5407,21 +5403,20 @@ var ContainerRegistryHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - core.debug("Attempting to push image \"" + imageToPush + "\" to ACR"); + githubActionsToolHelper.debug("Attempting to push image \"" + imageToPush + "\" to ACR"); _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, io.which("docker", true)]; + return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, ["push", "" + imageToPush])]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ["push", "" + imageToPush])]; case 3: _a.sent(); return [3 /*break*/, 5]; case 4: err_3 = _a.sent(); - core.error("Failed to push image \"" + imageToPush + "\" to ACR. Error: " + err_3.message); - core.setFailed(err_3.message); + githubActionsToolHelper.error("Failed to push image \"" + imageToPush + "\" to ACR. Error: " + err_3.message); throw err_3; case 5: return [2 /*return*/]; } @@ -5435,7 +5430,130 @@ exports.ContainerRegistryHelper = ContainerRegistryHelper; /***/ }), -/***/ 166: +/***/ 2153: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.GithubActionsToolHelper = void 0; +var core = __nccwpck_require__(3195); +var io = __nccwpck_require__(9529); +var exec = __nccwpck_require__(9714); +var GithubActionsToolHelper = /** @class */ (function () { + function GithubActionsToolHelper() { + } + GithubActionsToolHelper.prototype.getGithubRunId = function () { + return process.env['GITHUB_RUN_ID'] || ''; + }; + GithubActionsToolHelper.prototype.getGithubRunNumber = function () { + return process.env['GITHUB_RUN_NUMBER'] || ''; + }; + GithubActionsToolHelper.prototype.info = function (message) { + core.info(message); + }; + GithubActionsToolHelper.prototype.error = function (message) { + core.error(message); + }; + GithubActionsToolHelper.prototype.warning = function (message) { + core.warning(message); + }; + GithubActionsToolHelper.prototype.debug = function (message) { + core.debug(message); + }; + GithubActionsToolHelper.prototype.exec = function (commandLine, args, execOptions) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, exec.exec(commandLine, args, execOptions)]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + GithubActionsToolHelper.prototype.ExecOptions = function () { + return __awaiter(this, void 0, void 0, function () { + var stdout, stderr, options; + return __generator(this, function (_a) { + stdout = ''; + stderr = ''; + options = { + listeners: { + stdout: function (data) { + stdout += data.toString(); + }, + stderr: function (data) { + stderr += data.toString(); + } + } + }; + return [2 /*return*/, options]; + }); + }); + }; + GithubActionsToolHelper.prototype.getInput = function (name, options) { + return core.getInput(name, options); + }; + GithubActionsToolHelper.prototype.setFailed = function (message) { + core.setFailed(message); + }; + GithubActionsToolHelper.prototype.which = function (tool, check) { + return io.which(tool, check); + }; + GithubActionsToolHelper.prototype.getContainerAppName = function (containerAppName) { + containerAppName = "gh-action-app-" + this.getGithubRunId() + "-" + this.getGithubRunNumber(); + // Replace all '.' characters with '-' characters in the Container App name + containerAppName = containerAppName.replace(/\./gi, "-"); + this.info("Default Container App name: " + containerAppName); + return containerAppName; + }; + GithubActionsToolHelper.prototype.getTelemetryArg = function () { + return "CALLER_ID=github-actions-v1"; + }; + return GithubActionsToolHelper; +}()); +exports.GithubActionsToolHelper = GithubActionsToolHelper; + + +/***/ }), + +/***/ 7166: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -5478,9 +5596,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.TelemetryHelper = void 0; -var core = __nccwpck_require__(195); -var Utility_1 = __nccwpck_require__(135); -var io = __nccwpck_require__(529); +var Utility_1 = __nccwpck_require__(2135); +var GithubActionsToolHelper_1 = __nccwpck_require__(2153); var ORYX_CLI_IMAGE = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; var SUCCESSFUL_RESULT = "succeeded"; var FAILED_RESULT = "failed"; @@ -5488,6 +5605,7 @@ var BUILDER_SCENARIO = "used-builder"; var DOCKERFILE_SCENARIO = "used-dockerfile"; var IMAGE_SCENARIO = "used-image"; var util = new Utility_1.Utility(); +var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); var TelemetryHelper = /** @class */ (function () { function TelemetryHelper(disableTelemetry) { this.disableTelemetry = disableTelemetry; @@ -5535,7 +5653,7 @@ var TelemetryHelper = /** @class */ (function () { case 0: taskLengthMilliseconds = Date.now() - this.taskStartMilliseconds; if (!!this.disableTelemetry) return [3 /*break*/, 4]; - core.info("Telemetry enabled; logging metadata about task result, length and scenario targeted."); + githubActionsToolHelper.info("Telemetry enabled; logging metadata about task result, length and scenario targeted."); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5558,7 +5676,7 @@ var TelemetryHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_1 = _a.sent(); - core.warning("Skipping telemetry logging due to the following exception: " + err_1.message); + githubActionsToolHelper.warning("Skipping telemetry logging due to the following exception: " + err_1.message); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } @@ -5576,16 +5694,16 @@ var executeDockerCommand = function (args, continueOnError) { switch (_a.label) { case 0: _a.trys.push([0, 3, , 4]); - return [4 /*yield*/, io.which("docker", true)]; + return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; case 1: dockerTool = _a.sent(); - return [4 /*yield*/, new Utility_1.Utility().executeAndThrowIfError(dockerTool, args, continueOnError)]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, args, continueOnError)]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_2 = _a.sent(); - core.setFailed("Error: " + err_2.message); + githubActionsToolHelper.error("Error: " + err_2.message); throw err_2; // Re-throw the error case 4: return [2 /*return*/]; } @@ -5596,7 +5714,7 @@ var executeDockerCommand = function (args, continueOnError) { /***/ }), -/***/ 135: +/***/ 2135: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -5639,8 +5757,9 @@ var __generator = (this && this.__generator) || function (thisArg, body) { }; exports.__esModule = true; exports.Utility = void 0; -var core = __nccwpck_require__(195); -var exec = __nccwpck_require__(714); +// Note: This file is used to define utility functions that can be used across the project. +var GithubActionsToolHelper_1 = __nccwpck_require__(2153); +var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); var Utility = /** @class */ (function () { function Utility() { } @@ -5652,28 +5771,21 @@ var Utility = /** @class */ (function () { Utility.prototype.executeAndThrowIfError = function (commandLine, args, continueOnError) { if (continueOnError === void 0) { continueOnError = false; } return __awaiter(this, void 0, void 0, function () { - var stdout_1, stderr_1, options, exitCode_1, error_1; + var options, stderr_1, stdout_1, exitCode_1, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: - _a.trys.push([0, 2, , 3]); - stdout_1 = ''; - stderr_1 = ''; - options = { - listeners: { - stdout: function (data) { - stdout_1 += data.toString(); - }, - stderr: function (data) { - stderr_1 += data.toString(); - } - } - }; - return [4 /*yield*/, exec.exec(commandLine, args, options)]; + _a.trys.push([0, 3, , 4]); + return [4 /*yield*/, githubActionsToolHelper.ExecOptions()]; case 1: + options = _a.sent(); + stderr_1 = options.listeners.stderr.toString(); + stdout_1 = options.listeners.stdout.toString(); + return [4 /*yield*/, githubActionsToolHelper.exec(commandLine, args, options)]; + case 2: exitCode_1 = _a.sent(); if (!continueOnError && exitCode_1 !== 0) { - core.error("Command failed with exit code " + exitCode_1 + ". Error stream: " + stderr_1); + githubActionsToolHelper.error("Command failed with exit code " + exitCode_1 + ". Error stream: " + stderr_1); throw new Error("Command failed with exit code " + exitCode_1 + ". Error stream: " + stderr_1); } return [2 /*return*/, new Promise(function (resolve, reject) { @@ -5684,11 +5796,11 @@ var Utility = /** @class */ (function () { }; resolve(executionResult); })]; - case 2: + case 3: error_1 = _a.sent(); - core.setFailed("Error: " + error_1.message); + githubActionsToolHelper.error("Error: " + error_1.message); throw error_1; // Re-throw the error - case 3: return [2 /*return*/]; + case 4: return [2 /*return*/]; } }); }); @@ -5724,7 +5836,7 @@ exports.Utility = Utility; /***/ }), -/***/ 491: +/***/ 9491: /***/ ((module) => { "use strict"; @@ -5732,7 +5844,7 @@ module.exports = require("assert"); /***/ }), -/***/ 81: +/***/ 2081: /***/ ((module) => { "use strict"; @@ -5740,7 +5852,7 @@ module.exports = require("child_process"); /***/ }), -/***/ 113: +/***/ 6113: /***/ ((module) => { "use strict"; @@ -5748,7 +5860,7 @@ module.exports = require("crypto"); /***/ }), -/***/ 361: +/***/ 2361: /***/ ((module) => { "use strict"; @@ -5756,7 +5868,7 @@ module.exports = require("events"); /***/ }), -/***/ 147: +/***/ 7147: /***/ ((module) => { "use strict"; @@ -5764,7 +5876,7 @@ module.exports = require("fs"); /***/ }), -/***/ 685: +/***/ 3685: /***/ ((module) => { "use strict"; @@ -5772,7 +5884,7 @@ module.exports = require("http"); /***/ }), -/***/ 687: +/***/ 5687: /***/ ((module) => { "use strict"; @@ -5780,7 +5892,7 @@ module.exports = require("https"); /***/ }), -/***/ 808: +/***/ 1808: /***/ ((module) => { "use strict"; @@ -5788,7 +5900,7 @@ module.exports = require("net"); /***/ }), -/***/ 37: +/***/ 2037: /***/ ((module) => { "use strict"; @@ -5796,7 +5908,7 @@ module.exports = require("os"); /***/ }), -/***/ 822: +/***/ 1017: /***/ ((module) => { "use strict"; @@ -5804,7 +5916,7 @@ module.exports = require("path"); /***/ }), -/***/ 576: +/***/ 1576: /***/ ((module) => { "use strict"; @@ -5812,7 +5924,7 @@ module.exports = require("string_decoder"); /***/ }), -/***/ 512: +/***/ 9512: /***/ ((module) => { "use strict"; @@ -5820,7 +5932,7 @@ module.exports = require("timers"); /***/ }), -/***/ 404: +/***/ 4404: /***/ ((module) => { "use strict"; @@ -5828,7 +5940,7 @@ module.exports = require("tls"); /***/ }), -/***/ 837: +/***/ 3837: /***/ ((module) => { "use strict"; @@ -5878,7 +5990,7 @@ module.exports = require("util"); /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __nccwpck_require__(238); +/******/ var __webpack_exports__ = __nccwpck_require__(3238); /******/ module.exports = __webpack_exports__; /******/ /******/ })() diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 0a150fb1..7c3a8649 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -1,15 +1,15 @@ -import * as core from '@actions/core'; -import * as io from '@actions/io'; -import * as exec from '@actions/exec'; import * as path from 'path'; import * as os from 'os'; import { Utility } from './Utility'; +import { GithubActionsToolHelper } from './GithubActionsToolHelper'; import fs = require('fs'); const ORYX_CLI_IMAGE: string = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; const ORYX_BUILDER_IMAGE: string = 'mcr.microsoft.com/oryx/builder:20230208.1'; const IS_WINDOWS_AGENT: boolean = os.platform() == 'win32'; const PACK_CMD: string = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; +const githubActionsToolHelper = new GithubActionsToolHelper(); +const util = new Utility(); export class ContainerAppHelper { readonly disableTelemetry: boolean = false; @@ -32,15 +32,15 @@ export class ContainerAppHelper { environment: string, imageToDeploy: string, optionalCmdArgs: string[]) { - core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + githubActionsToolHelper.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -55,12 +55,12 @@ export class ContainerAppHelper { containerAppName: string, resourceGroup: string, yamlConfigPath: string) { - core.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + githubActionsToolHelper.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -77,16 +77,15 @@ export class ContainerAppHelper { resourceGroup: string, imageToDeploy: string, optionalCmdArgs: string[]) { - core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + githubActionsToolHelper.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -107,8 +106,7 @@ export class ContainerAppHelper { optionalCmdArgs: string[], ingress?: string, targetPort?: string) { - core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); - const util = new Utility(); + githubActionsToolHelper.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { let command = `containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { @@ -122,10 +120,9 @@ export class ContainerAppHelper { if (!util.isNullOrEmpty(targetPort)) { command += ` --target-port ${targetPort}`; } - - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -140,12 +137,12 @@ export class ContainerAppHelper { containerAppName: string, resourceGroup: string, yamlConfigPath: string) { - core.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + githubActionsToolHelper.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -157,13 +154,13 @@ export class ContainerAppHelper { * @returns true if the Container App exists, false otherwise */ public async doesContainerAppExist(containerAppName: string, resourceGroup: string): Promise { - core.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); + githubActionsToolHelper.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { let command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; - const exitCode = await exec.exec(`az`, command.split(' ')); - return exitCode === 0; + let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); + return executionResult.exitCode === 0; } catch (err) { - core.warning(err.message); + githubActionsToolHelper.warning(err.message); return false; } } @@ -175,13 +172,13 @@ export class ContainerAppHelper { * @returns true if the Container App Environment exists, false otherwise */ public async doesContainerAppEnvironmentExist(containerAppEnvironment: string, resourceGroup: string): Promise { - core.debug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); + githubActionsToolHelper.debug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { - const command = `containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; - const exitCode = await exec.exec(`az`, command.split(' ')); - return exitCode === 0; + let command = `containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; + let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); + return executionResult.exitCode === 0; } catch (err) { - core.warning(err.message); + githubActionsToolHelper.warning(err.message); return false; } } @@ -192,13 +189,13 @@ export class ContainerAppHelper { * @returns true if the resource group exists, false otherwise */ public async doesResourceGroupExist(resourceGroup: string): Promise { - core.debug(`Attempting to determine if resource group "${resourceGroup}" exists`); + githubActionsToolHelper.debug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { - const command = `group show -n ${resourceGroup} -o none`; - const exitCode = await exec.exec(`az`, command.split(' ')); - return exitCode === 0; + let command = `group show -n ${resourceGroup} -o none`; + let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); + return executionResult.exitCode === 0; } catch (err) { - core.warning(err.message); + githubActionsToolHelper.warning(err.message); return false; } } @@ -208,14 +205,14 @@ export class ContainerAppHelper { * @returns the default location if found, otherwise 'eastus2' */ public async getDefaultContainerAppLocation(): Promise { - core.debug(`Attempting to get the default location for the Container App service for the subscription.`); + githubActionsToolHelper.debug(`Attempting to get the default location for the Container App service for the subscription.`); try { let args = [`provider`, `show`, `-n`, `Microsoft.App`, `--query`, `resourceTypes[?resourceType=='containerApps'].locations[] | [0]`]; - const executionResult = await new Utility().executeAndThrowIfError(`az`, args); + let executionResult = await util.executeAndThrowIfError(`az`, args); // If successful, strip out double quotes, spaces and parentheses from the first location returned return !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { - core.warning(err.message); + githubActionsToolHelper.warning(err.message); return `eastus2`; } } @@ -226,12 +223,12 @@ export class ContainerAppHelper { * @param location - the location to create the resource group in */ public async createResourceGroup(name: string, location: string) { - core.debug(`Attempting to create resource group "${name}" in location "${location}"`); + githubActionsToolHelper.debug(`Attempting to create resource group "${name}" in location "${location}"`); try { - const command = `group create -n ${name} -l ${location}`; - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + let command = `group create -n ${name} -l ${location}`; + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -242,13 +239,13 @@ export class ContainerAppHelper { * @returns the name of the existing Container App Environment, null if none exists */ public async getExistingContainerAppEnvironment(resourceGroup: string) { - core.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); + githubActionsToolHelper.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { let args = [`containerapp`, `env`, `list`, `-g`, `${resourceGroup}`, `--query`, `[0].name`]; - const executionResult = await new Utility().executeAndThrowIfError(`az`, args); + let executionResult = await util.executeAndThrowIfError(`az`, args); return !executionResult.stderr ? executionResult.stdout : null; } catch (err) { - core.warning(err.message); + githubActionsToolHelper.warning(err.message); return null; } } @@ -261,15 +258,15 @@ export class ContainerAppHelper { */ public async createContainerAppEnvironment(name: string, resourceGroup: string, location?: string) { const util = new Utility(); - core.debug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); + githubActionsToolHelper.debug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); try { let args = [`containerapp`, `env`, `create`, `-n`, `${name}`, `-g`, `${resourceGroup}`]; if (!util.isNullOrEmpty(location)) { args.push(`-l`, `${location}`); } - await new Utility().executeAndThrowIfError(`az`, args); + await util.executeAndThrowIfError(`az`, args); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -280,12 +277,12 @@ export class ContainerAppHelper { * @param resourceGroup - the resource group that the Container App is found in */ public async disableContainerAppIngress(name: string, resourceGroup: string) { - core.debug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); + githubActionsToolHelper.debug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); try { - const command = `containerapp ingress disable -n ${name} -g ${resourceGroup}`; - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + let command = `containerapp ingress disable -n ${name} -g ${resourceGroup}`; + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -299,12 +296,12 @@ export class ContainerAppHelper { * @param acrPassword - the password used to authenticate with the Azure Container Registry */ public async updateContainerAppRegistryDetails(name: string, resourceGroup: string, acrName: string, acrUsername: string, acrPassword: string) { - core.debug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); + githubActionsToolHelper.debug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { - const command = `containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; - await new Utility().executeAndThrowIfError(`az`, command.split(' ')); + let command = `containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -319,15 +316,15 @@ export class ContainerAppHelper { imageToDeploy: string, appSourcePath: string, runtimeStack: string) { - core.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); + githubActionsToolHelper.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); try { - let telemetryArg = `CALLER_ID=github-actions-v1`; + let telemetryArg = githubActionsToolHelper.getTelemetryArg(); if (this.disableTelemetry) { telemetryArg = `ORYX_DISABLE_TELEMETRY=true`; } - await new Utility().executeAndThrowIfError(`${PACK_CMD}`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, '--env', `${telemetryArg}`]); + await util.executeAndThrowIfError(`${PACK_CMD}`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, '--env', `${telemetryArg}`]); } catch (err) { - core.error(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -343,13 +340,13 @@ export class ContainerAppHelper { imageToDeploy: string, appSourcePath: string, dockerfilePath: string) { - core.debug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + githubActionsToolHelper.debug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); try { - const dockerTool = await io.which("docker", true); - await new Utility().executeAndThrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); - core.debug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + let dockerTool = await githubActionsToolHelper.which("docker", true); + await util.executeAndThrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); + githubActionsToolHelper.debug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); } catch (err) { - core.setFailed(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -360,33 +357,33 @@ export class ContainerAppHelper { * @returns a string representing the runtime stack that can be used for the Oryx MCR runtime images */ public async determineRuntimeStackAsync(appSourcePath: string): Promise { - core.debug('Attempting to determine the runtime stack needed for the provided application source'); + githubActionsToolHelper.debug('Attempting to determine the runtime stack needed for the provided application source'); try { - const dockerTool: string = await io.which("docker", true); + let dockerTool: string = await githubActionsToolHelper.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - await new Utility().executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', `${appSourcePath}:/app`, `${ORYX_CLI_IMAGE}`, '/bin/bash', '-c', `oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt`]) + await util.executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', `${appSourcePath}:/app`, `${ORYX_CLI_IMAGE}`, '/bin/bash', '-c', `oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt`]) // Read the temp file to get the runtime stack into a variable - const oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); + let oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); - const runtimeStack = fs.promises.readFile(oryxRuntimeTxtPath, 'utf8').then((data) => { - const lines = data.split('\n'); + let runtimeStack = fs.promises.readFile(oryxRuntimeTxtPath, 'utf8').then((data) => { + let lines = data.split('\n'); return lines[0]; }).catch((err) => { - core.setFailed(err.message); + githubActionsToolHelper.error(err.message); throw err; }); // Delete the temp file fs.unlink(oryxRuntimeTxtPath, (err) => { if (err) { - core.warning(`Unable to delete the temporary file "${oryxRuntimeTxtPath}". Error: ${err.message}`); + githubActionsToolHelper.warning(`Unable to delete the temporary file "${oryxRuntimeTxtPath}". Error: ${err.message}`); } }); return runtimeStack; } catch (err) { - core.setFailed(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -396,12 +393,12 @@ export class ContainerAppHelper { * to no default builder set. */ public async setDefaultBuilder() { - core.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); + githubActionsToolHelper.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { - await new Utility().executeAndThrowIfError(`${PACK_CMD}`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); + await util.executeAndThrowIfError(`${PACK_CMD}`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); } catch (err) { - core.setFailed(err.message); + githubActionsToolHelper.error(err.message); throw err; } } @@ -411,28 +408,27 @@ export class ContainerAppHelper { * For more information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ */ public async installPackCliAsync() { - core.debug('Attempting to install the pack CLI'); + githubActionsToolHelper.debug('Attempting to install the pack CLI'); try { let command: string = ''; let commandLine = ''; let args: string[] = []; if (IS_WINDOWS_AGENT) { - const packZipDownloadUri: string = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; - const packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); + let packZipDownloadUri: string = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; + let packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); args = [`New-Item`, `-ItemType`, `Directory`, `-Path`, `${PACK_CMD}`, `-Force | Out-Null;`, `Invoke-WebRequest`, `-Uri`, `${packZipDownloadUri}`, `-OutFile`, `${packZipDownloadFilePath};`, `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`, `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`]; commandLine = 'pwsh'; } else { - const tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; + let tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; args = ['-c', command]; commandLine = 'bash'; } - await new Utility().executeAndThrowIfError(commandLine, args); + await util.executeAndThrowIfError(commandLine, args); } catch (err) { - core.error(`Unable to install the pack CLI. Error: ${err.message}`); - core.setFailed(err.message); + githubActionsToolHelper.error(`Unable to install the pack CLI. Error: ${err.message}`); throw err; } } diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 59fa4d77..e525aaba 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -1,8 +1,9 @@ -import * as core from '@actions/core'; -import * as exec from '@actions/exec'; -import * as io from '@actions/io'; import * as os from 'os'; import { Utility } from './Utility'; +import { GithubActionsToolHelper } from './GithubActionsToolHelper'; + +const githubActionsToolHelper = new GithubActionsToolHelper(); +const util = new Utility(); export class ContainerRegistryHelper { /** @@ -12,11 +13,11 @@ export class ContainerRegistryHelper { * @param acrPassword - the password for authentication */ public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { - core.debug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); + githubActionsToolHelper.debug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); try { - await exec.exec('docker', [`login`, `--password-stdin`, `--username`, `${acrUsername}`, `${acrName}.azurecr.io`], { input: Buffer.from(acrPassword) }); + await githubActionsToolHelper.exec('docker', [`login`, `--password-stdin`, `--username`, `${acrUsername}`, `${acrName}.azurecr.io`], { input: Buffer.from(acrPassword) }); } catch (err) { - core.error(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); + githubActionsToolHelper.error(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); throw err; } } @@ -27,13 +28,13 @@ export class ContainerRegistryHelper { * @param acrName - the name of the ACR instance to authenticate calls to. */ public async loginAcrWithAccessTokenAsync(acrName: string) { - core.debug(`Attempting to log in to ACR instance "${acrName}" with access token`); + githubActionsToolHelper.debug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { - const command: string = `CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`; - const shell = os.platform() === 'win32' ? 'pwsh' : 'bash'; - await exec.exec(shell, ['-c', command]); + let command: string = `CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`; + let commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; + await util.executeAndThrowIfError(commandLine, ['-c', command]); } catch (err) { - core.error(`Failed to log in to ACR instance "${acrName}" with access token`) + githubActionsToolHelper.error(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; } } @@ -43,13 +44,12 @@ export class ContainerRegistryHelper { * @param imageToPush - the name of the image to push to ACR */ public async pushImageToAcr(imageToPush: string) { - core.debug(`Attempting to push image "${imageToPush}" to ACR`); + githubActionsToolHelper.debug(`Attempting to push image "${imageToPush}" to ACR`); try { - const dockerTool: string = await io.which("docker", true); - await new Utility().executeAndThrowIfError(dockerTool, [`push`, `${imageToPush}`]); + let dockerTool: string = await githubActionsToolHelper.which("docker", true); + await util.executeAndThrowIfError(dockerTool, [`push`, `${imageToPush}`]); } catch (err) { - core.error(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); - core.setFailed(err.message); + githubActionsToolHelper.error(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); throw err; } } diff --git a/src/GithubActionsToolHelper.ts b/src/GithubActionsToolHelper.ts new file mode 100644 index 00000000..bf672c86 --- /dev/null +++ b/src/GithubActionsToolHelper.ts @@ -0,0 +1,75 @@ +import * as core from '@actions/core'; +import * as io from '@actions/io'; +import * as exec from '@actions/exec'; + +export class GithubActionsToolHelper { + + public getGithubRunId(): string { + return process.env['GITHUB_RUN_ID'] || ''; + } + + public getGithubRunNumber(): string { + return process.env['GITHUB_RUN_NUMBER'] || ''; + } + + public info(message: string): void { + core.info(message); + } + + public error(message: string): void { + core.error(message); + } + + public warning(message: string): void { + core.warning(message); + } + + public debug(message: string): void { + core.debug(message); + } + + public async exec(commandLine: string, args?: string[], execOptions?: exec.ExecOptions): Promise { + return await exec.exec(commandLine, args, execOptions); + } + + public async ExecOptions(): Promise { + let stdout = ''; + let stderr = ''; + + const options: exec.ExecOptions = { + listeners: { + stdout: (data: Buffer) => { + stdout += data.toString(); + }, + stderr: (data: Buffer) => { + stderr += data.toString(); + }, + }, + }; + return options; + } + + public getInput(name: string, options?: core.InputOptions): string { + return core.getInput(name, options); + } + + public setFailed(message: string): void { + core.setFailed(message); + } + + public which(tool: string, check?: boolean): Promise { + return io.which(tool, check); + } + + public getContainerAppName(containerAppName: string): string { + containerAppName = `gh-action-app-${this.getGithubRunId()}-${this.getGithubRunNumber()}`; + // Replace all '.' characters with '-' characters in the Container App name + containerAppName = containerAppName.replace(/\./gi, "-"); + this.info(`Default Container App name: ${containerAppName}`); + return containerAppName + } + + public getTelemetryArg(): string { + return `CALLER_ID=github-actions-v1`; + } +} \ No newline at end of file diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 167593b5..181bda89 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -1,6 +1,5 @@ -import * as core from '@actions/core'; import { Utility } from './Utility'; -import * as io from '@actions/io'; +import { GithubActionsToolHelper } from './GithubActionsToolHelper'; const ORYX_CLI_IMAGE: string = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; @@ -12,6 +11,7 @@ const DOCKERFILE_SCENARIO: string = "used-dockerfile"; const IMAGE_SCENARIO: string = "used-image"; const util = new Utility(); +const githubActionsToolHelper = new GithubActionsToolHelper(); export class TelemetryHelper { readonly disableTelemetry: boolean; @@ -66,9 +66,9 @@ export class TelemetryHelper { * If telemetry is enabled, uses the "oryx telemetry" command to log metadata about this task execution. */ public async sendLogs() { - const taskLengthMilliseconds: number = Date.now() - this.taskStartMilliseconds; + let taskLengthMilliseconds: number = Date.now() - this.taskStartMilliseconds; if (!this.disableTelemetry) { - core.info(`Telemetry enabled; logging metadata about task result, length and scenario targeted.`); + githubActionsToolHelper.info(`Telemetry enabled; logging metadata about task result, length and scenario targeted.`); try { let resultArg: string = ''; if (!util.isNullOrEmpty(this.result)) { @@ -86,10 +86,9 @@ export class TelemetryHelper { } let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name ContainerAppsGitHubActionV1 ` + `--processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`]; - await executeDockerCommand(args, true) } catch (err) { - core.warning(`Skipping telemetry logging due to the following exception: ${err.message}`); + githubActionsToolHelper.warning(`Skipping telemetry logging due to the following exception: ${err.message}`); } } } @@ -97,11 +96,11 @@ export class TelemetryHelper { const executeDockerCommand = async (args: string[], continueOnError: boolean = false): Promise => { try { - const dockerTool: string = await io.which("docker", true); - await new Utility().executeAndThrowIfError(dockerTool, args, continueOnError); + let dockerTool: string = await githubActionsToolHelper.which("docker", true); + await util.executeAndThrowIfError(dockerTool, args, continueOnError); } catch (err) { - core.setFailed(`Error: ${err.message}`); + githubActionsToolHelper.error(`Error: ${err.message}`); throw err; // Re-throw the error } } \ No newline at end of file diff --git a/src/Utility.ts b/src/Utility.ts index 7deba5c7..bd571550 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -1,5 +1,8 @@ -import * as core from '@actions/core'; -import * as exec from '@actions/exec'; +// Note: This file is used to define utility functions that can be used across the project. +import { GithubActionsToolHelper } from './GithubActionsToolHelper'; + +const githubActionsToolHelper = new GithubActionsToolHelper(); + export class Utility { /** * @param commandLine - the command to execute @@ -9,28 +12,18 @@ export class Utility { public async executeAndThrowIfError(commandLine: string, args: string[], continueOnError: boolean = false): Promise<{ exitCode: number, stdout: string, stderr: string }> { try { - let stdout = ''; - let stderr = ''; - - const options: exec.ExecOptions = { - listeners: { - stdout: (data: Buffer) => { - stdout += data.toString(); - }, - stderr: (data: Buffer) => { - stderr += data.toString(); - }, - }, - }; + let options = await githubActionsToolHelper.ExecOptions(); + let stderr = options.listeners.stderr.toString(); + let stdout = options.listeners.stdout.toString(); - const exitCode = await exec.exec(commandLine, args, options); + let exitCode = await githubActionsToolHelper.exec(commandLine, args, options); if (!continueOnError && exitCode !== 0) { - core.error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); + githubActionsToolHelper.error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); } return new Promise((resolve, reject) => { - const executionResult = { + let executionResult = { exitCode: exitCode, stdout: stdout, stderr: stderr @@ -38,7 +31,7 @@ export class Utility { resolve(executionResult); }); } catch (error) { - core.setFailed(`Error: ${error.message}`); + githubActionsToolHelper.error(`Error: ${error.message}`); throw error; // Re-throw the error } } From 17ceee926c46963f668c068282a7e2e3d0e45545 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Wed, 27 Sep 2023 17:22:54 -0700 Subject: [PATCH 20/42] Address PR comments --- azurecontainerapps.ts | 104 +++++---- dist/index.js | 406 ++++++++++++++++----------------- src/ContainerAppHelper.ts | 98 ++++---- src/ContainerRegistryHelper.ts | 21 +- src/GithubActionsToolHelper.ts | 48 ++-- src/TelemetryHelper.ts | 26 +-- src/Utility.ts | 27 +-- 7 files changed, 356 insertions(+), 374 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index bd74dd3d..2d2fb2ea 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -4,15 +4,15 @@ import { ContainerAppHelper } from './src/ContainerAppHelper'; import { ContainerRegistryHelper } from './src/ContainerRegistryHelper'; import { TelemetryHelper } from './src/TelemetryHelper'; import { Utility } from './src/Utility'; -import { GithubActionsToolHelper } from './src/GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './src/GithubActionsToolHelper'; const util = new Utility(); -const githubActionsToolHelper = new GithubActionsToolHelper(); +const toolHelper = new GitHubActionsToolHelper(); export class azurecontainerapps { public static async runMain(): Promise { - let disableTelemetry = githubActionsToolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; + let disableTelemetry = toolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; this.initializeHelpers(disableTelemetry); try { @@ -51,7 +51,7 @@ export class azurecontainerapps { // If telemetry is enabled, log that the task completed successfully this.telemetryHelper.setSuccessfulResult(); } catch (err) { - githubActionsToolHelper.setFailed(err.message); + toolHelper.setFailed(err.message); this.telemetryHelper.setFailedResult(err.message); } finally { // If telemetry is enabled, will log metadata for this task run @@ -60,8 +60,8 @@ export class azurecontainerapps { } // GitHub Action properties - private static githubRunId: string = githubActionsToolHelper.getGithubRunId(); - private static githubRunNumber: string = githubActionsToolHelper.getGithubRunNumber(); + private static buildId: string = toolHelper.getbuildId(); + private static buildNumber: string = toolHelper.getbuildNumber(); // Supported scenario properties private static appSourcePath: string; @@ -88,6 +88,8 @@ export class azurecontainerapps { private static telemetryHelper: TelemetryHelper; private static appHelper: ContainerAppHelper; private static registryHelper: ContainerRegistryHelper; + private static util: Utility; + private static toolHelper: GitHubActionsToolHelper; // Miscellaneous properties private static imageToBuild: string; @@ -109,6 +111,12 @@ export class azurecontainerapps { // Set up ContainerRegistryHelper for managing calls around ACR this.registryHelper = new ContainerRegistryHelper(); + + // Set up Utility for managing miscellaneous calls + this.util = new Utility(); + + // Set up toolHelper for managing calls to the GitHub Actions toolkit + this.toolHelper = new GitHubActionsToolHelper(); } /** @@ -118,27 +126,29 @@ export class azurecontainerapps { private static validateSupportedScenarioArguments() { // Get the path to the application source to build and run, if provided - this.appSourcePath = githubActionsToolHelper.getInput('appSourcePath', { required: false }); + this.appSourcePath = toolHelper.getInput('appSourcePath', { required: false }); // Get the name of the ACR instance to push images to, if provided - this.acrName = githubActionsToolHelper.getInput('acrName', { required: false }); + this.acrName = toolHelper.getInput('acrName', { required: false }); // Get the previously built image to deploy, if provided - this.imageToDeploy = githubActionsToolHelper.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = toolHelper.getInput('imageToDeploy', { required: false }); // Get the YAML configuration file, if provided - this.yamlConfigPath = githubActionsToolHelper.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = toolHelper.getInput('yamlConfigPath', { required: false }); // Ensure that acrName is also provided if appSourcePath is provided if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { - githubActionsToolHelper.error(`The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`); - throw Error(`The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`); + let missingAcrNameMessage = `The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`; + toolHelper.writeError(missingAcrNameMessage); + throw Error(missingAcrNameMessage); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { - githubActionsToolHelper.error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); - throw Error(`One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`); + let requiredArgumentMessage = `One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`; + toolHelper.writeError(requiredArgumentMessage); + throw Error(requiredArgumentMessage); } } @@ -179,13 +189,13 @@ export class azurecontainerapps { /** * Gets the name of the Container App to use for the task. If the 'containerAppName' argument is not provided, - * then a default name will be generated in the form 'gh-action-app--'. + * then a default name will be generated in the form 'gh-action-app--'. * @returns The name of the Container App to use for the task. */ private static getContainerAppName(): string { - let containerAppName: string = githubActionsToolHelper.getInput('containerAppName', { required: false }); + let containerAppName: string = toolHelper.getInput('containerAppName', { required: false }); if (util.isNullOrEmpty(containerAppName)) { - return githubActionsToolHelper.getContainerAppName(containerAppName); + return toolHelper.getDefaultContainerAppName(containerAppName); } return containerAppName; @@ -198,7 +208,7 @@ export class azurecontainerapps { */ private static async getLocation(): Promise { // Set deployment location, if provided - let location: string = githubActionsToolHelper.getInput('location', { required: false }); + let location: string = toolHelper.getInput('location', { required: false }); // If no location was provided, use the default location for the Container App service if (util.isNullOrEmpty(location)) { @@ -218,10 +228,10 @@ export class azurecontainerapps { */ private static async getOrCreateResourceGroup(containerAppName: string, location: string): Promise { // Get the resource group to deploy to if it was provided, or generate it from the Container App name - let resourceGroup: string = githubActionsToolHelper.getInput('resourceGroup', { required: false }); + let resourceGroup: string = toolHelper.getInput('resourceGroup', { required: false }); if (util.isNullOrEmpty(resourceGroup)) { resourceGroup = `${containerAppName}-rg`; - githubActionsToolHelper.info(`Default resource group name: ${resourceGroup}`); + toolHelper.writeInfo(`Default resource group name: ${resourceGroup}`); // Ensure that the resource group that the Container App will be created in exists const resourceGroupExists = await this.appHelper.doesResourceGroupExist(resourceGroup); @@ -248,13 +258,13 @@ export class azurecontainerapps { resourceGroup: string, location: string): Promise { // Get the Container App environment if it was provided - let containerAppEnvironment: string = githubActionsToolHelper.getInput('containerAppEnvironment', { required: false }); + let containerAppEnvironment: string = toolHelper.getInput('containerAppEnvironment', { required: false }); // See if we can reuse an existing Container App environment found in the resource group if (util.isNullOrEmpty(containerAppEnvironment)) { const existingContainerAppEnvironment: string = await this.appHelper.getExistingContainerAppEnvironment(resourceGroup); if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { - githubActionsToolHelper.info(`Existing Container App environment found in resource group: ${existingContainerAppEnvironment}`); + toolHelper.writeInfo(`Existing Container App environment found in resource group: ${existingContainerAppEnvironment}`); return existingContainerAppEnvironment } } @@ -262,7 +272,7 @@ export class azurecontainerapps { // Generate the Container App environment name if it was not provided if (util.isNullOrEmpty(containerAppEnvironment)) { containerAppEnvironment = `${containerAppName}-env`; - githubActionsToolHelper.info(`Default Container App environment name: ${containerAppEnvironment}`); + toolHelper.writeInfo(`Default Container App environment name: ${containerAppEnvironment}`); } // Determine if the Container App environment currently exists and create one if it doesn't @@ -278,15 +288,15 @@ export class azurecontainerapps { * Authenticates calls to the provided Azure Container Registry. */ private static async authenticateAzureContainerRegistryAsync() { - this.acrUsername = githubActionsToolHelper.getInput('acrUsername', { required: false }); - this.acrPassword = githubActionsToolHelper.getInput('acrPassword', { required: false }); + this.acrUsername = toolHelper.getInput('acrUsername', { required: false }); + this.acrPassword = toolHelper.getInput('acrPassword', { required: false }); // Login to ACR if credentials were provided if (!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword)) { - githubActionsToolHelper.info(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); + toolHelper.writeInfo(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); await this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword); } else { - githubActionsToolHelper.info(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); + toolHelper.writeInfo(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); await this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName); } } @@ -304,25 +314,25 @@ export class azurecontainerapps { */ private static async buildAndPushImageAsync() { // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = githubActionsToolHelper.getInput('imageToBuild', { required: false }); + this.imageToBuild = toolHelper.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.githubRunId}.${this.githubRunNumber}`; - githubActionsToolHelper.info(`Default image to build: ${this.imageToBuild}`); + this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.buildId}.${this.buildNumber}`; + toolHelper.writeInfo(`Default image to build: ${this.imageToBuild}`); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' if (util.isNullOrEmpty(this.imageToDeploy)) { this.imageToDeploy = this.imageToBuild; - githubActionsToolHelper.info(`Default image to deploy: ${this.imageToDeploy}`); + toolHelper.writeInfo(`Default image to deploy: ${this.imageToDeploy}`); } // Get Dockerfile to build, if provided, or check if one exists at the root of the provided application - let dockerfilePath: string = githubActionsToolHelper.getInput('dockerfilePath', { required: false }); + let dockerfilePath: string = toolHelper.getInput('dockerfilePath', { required: false }); if (util.isNullOrEmpty(dockerfilePath)) { - githubActionsToolHelper.info(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); + toolHelper.writeInfo(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); const rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); if (fs.existsSync(rootDockerfilePath)) { - githubActionsToolHelper.info(`Dockerfile found at root of application source.`) + toolHelper.writeInfo(`Dockerfile found at root of application source.`) dockerfilePath = rootDockerfilePath; } else { // No Dockerfile found or provided, build the image using the builder @@ -349,16 +359,16 @@ export class azurecontainerapps { private static async buildImageFromBuilderAsync(appSourcePath: string, imageToBuild: string) { // Install the pack CLI await this.appHelper.installPackCliAsync(); - githubActionsToolHelper.info(`Successfully installed the pack CLI.`) + toolHelper.writeInfo(`Successfully installed the pack CLI.`) // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = githubActionsToolHelper.getInput('runtimeStack', { required: false }); + this.runtimeStack = toolHelper.getInput('runtimeStack', { required: false }); if (util.isNullOrEmpty(this.runtimeStack)) { this.runtimeStack = await this.appHelper.determineRuntimeStackAsync(appSourcePath); - githubActionsToolHelper.info(`Runtime stack determined to be: ${this.runtimeStack}`); + toolHelper.writeInfo(`Runtime stack determined to be: ${this.runtimeStack}`); } - githubActionsToolHelper.info(`Building image "${imageToBuild}" using the Oryx++ Builder`); + toolHelper.writeInfo(`Building image "${imageToBuild}" using the Oryx++ Builder`); // Set the Oryx++ Builder as the default builder locally await this.appHelper.setDefaultBuilder(); @@ -377,7 +387,7 @@ export class azurecontainerapps { * @param imageToBuild - The name of the image to build. */ private static async builderImageFromDockerfile(appSourcePath: string, dockerfilePath: string, imageToBuild: string) { - githubActionsToolHelper.info(`Building image "${imageToBuild}" using the provided Dockerfile`); + toolHelper.writeInfo(`Building image "${imageToBuild}" using the provided Dockerfile`); await this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath); // If telemetry is enabled, log that the Dockerfile scenario was targeted for this task @@ -392,8 +402,8 @@ export class azurecontainerapps { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = githubActionsToolHelper.getInput('ingress', { required: false }); - this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); + this.ingress = toolHelper.getInput('ingress', { required: false }); + this.targetPort = toolHelper.getInput('targetPort', { required: false }); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. @@ -417,19 +427,19 @@ export class azurecontainerapps { // Set the ingress value to 'external' if it was not provided if (util.isNullOrEmpty(this.ingress)) { this.ingress = 'external'; - githubActionsToolHelper.info(`Default ingress value: ${this.ingress}`); + toolHelper.writeInfo(`Default ingress value: ${this.ingress}`); } // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' if (this.ingress == 'disabled') { this.ingressEnabled = false; - githubActionsToolHelper.info(`Ingress is disabled for this Container App.`); + toolHelper.writeInfo(`Ingress is disabled for this Container App.`); } // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); + this.targetPort = toolHelper.getInput('targetPort', { required: false }); if (util.isNullOrEmpty(this.targetPort)) { if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; @@ -437,13 +447,13 @@ export class azurecontainerapps { this.targetPort = '8080'; } - githubActionsToolHelper.info(`Default target port: ${this.targetPort}`); + toolHelper.writeInfo(`Default target port: ${this.targetPort}`); } // Set the target port to 80 if it was not provided or determined if (util.isNullOrEmpty(this.targetPort)) { this.targetPort = '80'; - githubActionsToolHelper.info(`Default target port: ${this.targetPort}`); + toolHelper.writeInfo(`Default target port: ${this.targetPort}`); } // Add the ingress value and target port to the optional arguments array @@ -453,7 +463,7 @@ export class azurecontainerapps { } } - const environmentVariables: string = githubActionsToolHelper.getInput('environmentVariables', { required: false }); + const environmentVariables: string = toolHelper.getInput('environmentVariables', { required: false }); // Add user-specified environment variables if (!util.isNullOrEmpty(environmentVariables)) { diff --git a/dist/index.js b/dist/index.js index 5729b38e..a8d686ac 100644 --- a/dist/index.js +++ b/dist/index.js @@ -52,7 +52,7 @@ var TelemetryHelper_1 = __nccwpck_require__(7166); var Utility_1 = __nccwpck_require__(2135); var GithubActionsToolHelper_1 = __nccwpck_require__(2153); var util = new Utility_1.Utility(); -var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); +var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); var azurecontainerapps = /** @class */ (function () { function azurecontainerapps() { } @@ -62,7 +62,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - disableTelemetry = githubActionsToolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; + disableTelemetry = toolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; this.initializeHelpers(disableTelemetry); _a.label = 1; case 1: @@ -109,7 +109,7 @@ var azurecontainerapps = /** @class */ (function () { return [3 /*break*/, 12]; case 9: err_1 = _a.sent(); - githubActionsToolHelper.setFailed(err_1.message); + toolHelper.setFailed(err_1.message); this.telemetryHelper.setFailedResult(err_1.message); return [3 /*break*/, 12]; case 10: @@ -135,6 +135,10 @@ var azurecontainerapps = /** @class */ (function () { this.appHelper = new ContainerAppHelper_1.ContainerAppHelper(disableTelemetry); // Set up ContainerRegistryHelper for managing calls around ACR this.registryHelper = new ContainerRegistryHelper_1.ContainerRegistryHelper(); + // Set up Utility for managing miscellaneous calls + this.util = new Utility_1.Utility(); + // Set up toolHelper for managing calls to the GitHub Actions toolkit + this.toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); }; /** * Validates the arguments provided to the task for supported scenarios. @@ -142,22 +146,24 @@ var azurecontainerapps = /** @class */ (function () { */ azurecontainerapps.validateSupportedScenarioArguments = function () { // Get the path to the application source to build and run, if provided - this.appSourcePath = githubActionsToolHelper.getInput('appSourcePath', { required: false }); + this.appSourcePath = toolHelper.getInput('appSourcePath', { required: false }); // Get the name of the ACR instance to push images to, if provided - this.acrName = githubActionsToolHelper.getInput('acrName', { required: false }); + this.acrName = toolHelper.getInput('acrName', { required: false }); // Get the previously built image to deploy, if provided - this.imageToDeploy = githubActionsToolHelper.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = toolHelper.getInput('imageToDeploy', { required: false }); // Get the YAML configuration file, if provided - this.yamlConfigPath = githubActionsToolHelper.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = toolHelper.getInput('yamlConfigPath', { required: false }); // Ensure that acrName is also provided if appSourcePath is provided if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { - githubActionsToolHelper.error("The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."); - throw Error("The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."); + var missingAcrNameMessage = "The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."; + toolHelper.writeError(missingAcrNameMessage); + throw Error(missingAcrNameMessage); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { - githubActionsToolHelper.error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); - throw Error("One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."); + var requiredArgumentMessage = "One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."; + toolHelper.writeError(requiredArgumentMessage); + throw Error(requiredArgumentMessage); } }; /** @@ -225,13 +231,13 @@ var azurecontainerapps = /** @class */ (function () { }; /** * Gets the name of the Container App to use for the task. If the 'containerAppName' argument is not provided, - * then a default name will be generated in the form 'gh-action-app--'. + * then a default name will be generated in the form 'gh-action-app--'. * @returns The name of the Container App to use for the task. */ azurecontainerapps.getContainerAppName = function () { - var containerAppName = githubActionsToolHelper.getInput('containerAppName', { required: false }); + var containerAppName = toolHelper.getInput('containerAppName', { required: false }); if (util.isNullOrEmpty(containerAppName)) { - return githubActionsToolHelper.getContainerAppName(containerAppName); + return toolHelper.getDefaultContainerAppName(containerAppName); } return containerAppName; }; @@ -246,7 +252,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - location = githubActionsToolHelper.getInput('location', { required: false }); + location = toolHelper.getInput('location', { required: false }); if (!util.isNullOrEmpty(location)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getDefaultContainerAppLocation()]; case 1: @@ -271,10 +277,10 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - resourceGroup = githubActionsToolHelper.getInput('resourceGroup', { required: false }); + resourceGroup = toolHelper.getInput('resourceGroup', { required: false }); if (!util.isNullOrEmpty(resourceGroup)) return [3 /*break*/, 3]; resourceGroup = containerAppName + "-rg"; - githubActionsToolHelper.info("Default resource group name: " + resourceGroup); + toolHelper.writeInfo("Default resource group name: " + resourceGroup); return [4 /*yield*/, this.appHelper.doesResourceGroupExist(resourceGroup)]; case 1: resourceGroupExists = _a.sent(); @@ -304,13 +310,13 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - containerAppEnvironment = githubActionsToolHelper.getInput('containerAppEnvironment', { required: false }); + containerAppEnvironment = toolHelper.getInput('containerAppEnvironment', { required: false }); if (!util.isNullOrEmpty(containerAppEnvironment)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getExistingContainerAppEnvironment(resourceGroup)]; case 1: existingContainerAppEnvironment = _a.sent(); if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { - githubActionsToolHelper.info("Existing Container App environment found in resource group: " + existingContainerAppEnvironment); + toolHelper.writeInfo("Existing Container App environment found in resource group: " + existingContainerAppEnvironment); return [2 /*return*/, existingContainerAppEnvironment]; } _a.label = 2; @@ -318,7 +324,7 @@ var azurecontainerapps = /** @class */ (function () { // Generate the Container App environment name if it was not provided if (util.isNullOrEmpty(containerAppEnvironment)) { containerAppEnvironment = containerAppName + "-env"; - githubActionsToolHelper.info("Default Container App environment name: " + containerAppEnvironment); + toolHelper.writeInfo("Default Container App environment name: " + containerAppEnvironment); } return [4 /*yield*/, this.appHelper.doesContainerAppEnvironmentExist(containerAppEnvironment, resourceGroup)]; case 3: @@ -341,16 +347,16 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - this.acrUsername = githubActionsToolHelper.getInput('acrUsername', { required: false }); - this.acrPassword = githubActionsToolHelper.getInput('acrPassword', { required: false }); + this.acrUsername = toolHelper.getInput('acrUsername', { required: false }); + this.acrPassword = toolHelper.getInput('acrPassword', { required: false }); if (!(!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 2]; - githubActionsToolHelper.info("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); + toolHelper.writeInfo("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); return [4 /*yield*/, this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword)]; case 1: _a.sent(); return [3 /*break*/, 4]; case 2: - githubActionsToolHelper.info("No ACR credentials provided; attempting to log in to ACR instance \"" + this.acrName + "\" with access token"); + toolHelper.writeInfo("No ACR credentials provided; attempting to log in to ACR instance \"" + this.acrName + "\" with access token"); return [4 /*yield*/, this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName)]; case 3: _a.sent(); @@ -377,22 +383,22 @@ var azurecontainerapps = /** @class */ (function () { switch (_a.label) { case 0: // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = githubActionsToolHelper.getInput('imageToBuild', { required: false }); + this.imageToBuild = toolHelper.getInput('imageToBuild', { required: false }); if (util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.githubRunId + "." + this.githubRunNumber; - githubActionsToolHelper.info("Default image to build: " + this.imageToBuild); + this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.buildId + "." + this.buildNumber; + toolHelper.writeInfo("Default image to build: " + this.imageToBuild); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' if (util.isNullOrEmpty(this.imageToDeploy)) { this.imageToDeploy = this.imageToBuild; - githubActionsToolHelper.info("Default image to deploy: " + this.imageToDeploy); + toolHelper.writeInfo("Default image to deploy: " + this.imageToDeploy); } - dockerfilePath = githubActionsToolHelper.getInput('dockerfilePath', { required: false }); + dockerfilePath = toolHelper.getInput('dockerfilePath', { required: false }); if (!util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 4]; - githubActionsToolHelper.info("No Dockerfile path provided; checking for Dockerfile at root of application source."); + toolHelper.writeInfo("No Dockerfile path provided; checking for Dockerfile at root of application source."); rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); if (!fs.existsSync(rootDockerfilePath)) return [3 /*break*/, 1]; - githubActionsToolHelper.info("Dockerfile found at root of application source."); + toolHelper.writeInfo("Dockerfile found at root of application source."); dockerfilePath = rootDockerfilePath; return [3 /*break*/, 3]; case 1: @@ -441,18 +447,18 @@ var azurecontainerapps = /** @class */ (function () { case 1: // Install the pack CLI _b.sent(); - githubActionsToolHelper.info("Successfully installed the pack CLI."); + toolHelper.writeInfo("Successfully installed the pack CLI."); // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = githubActionsToolHelper.getInput('runtimeStack', { required: false }); + this.runtimeStack = toolHelper.getInput('runtimeStack', { required: false }); if (!util.isNullOrEmpty(this.runtimeStack)) return [3 /*break*/, 3]; _a = this; return [4 /*yield*/, this.appHelper.determineRuntimeStackAsync(appSourcePath)]; case 2: _a.runtimeStack = _b.sent(); - githubActionsToolHelper.info("Runtime stack determined to be: " + this.runtimeStack); + toolHelper.writeInfo("Runtime stack determined to be: " + this.runtimeStack); _b.label = 3; case 3: - githubActionsToolHelper.info("Building image \"" + imageToBuild + "\" using the Oryx++ Builder"); + toolHelper.writeInfo("Building image \"" + imageToBuild + "\" using the Oryx++ Builder"); // Set the Oryx++ Builder as the default builder locally return [4 /*yield*/, this.appHelper.setDefaultBuilder()]; case 4: @@ -481,7 +487,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.info("Building image \"" + imageToBuild + "\" using the provided Dockerfile"); + toolHelper.writeInfo("Building image \"" + imageToBuild + "\" using the provided Dockerfile"); return [4 /*yield*/, this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath)]; case 1: _a.sent(); @@ -499,8 +505,8 @@ var azurecontainerapps = /** @class */ (function () { azurecontainerapps.setupContainerAppProperties = function () { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = githubActionsToolHelper.getInput('ingress', { required: false }); - this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); + this.ingress = toolHelper.getInput('ingress', { required: false }); + this.targetPort = toolHelper.getInput('targetPort', { required: false }); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. this.shouldUseUpdateCommand = this.containerAppExists && @@ -517,17 +523,17 @@ var azurecontainerapps = /** @class */ (function () { // Set the ingress value to 'external' if it was not provided if (util.isNullOrEmpty(this.ingress)) { this.ingress = 'external'; - githubActionsToolHelper.info("Default ingress value: " + this.ingress); + toolHelper.writeInfo("Default ingress value: " + this.ingress); } // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' if (this.ingress == 'disabled') { this.ingressEnabled = false; - githubActionsToolHelper.info("Ingress is disabled for this Container App."); + toolHelper.writeInfo("Ingress is disabled for this Container App."); } // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = githubActionsToolHelper.getInput('targetPort', { required: false }); + this.targetPort = toolHelper.getInput('targetPort', { required: false }); if (util.isNullOrEmpty(this.targetPort)) { if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; @@ -535,12 +541,12 @@ var azurecontainerapps = /** @class */ (function () { else { this.targetPort = '8080'; } - githubActionsToolHelper.info("Default target port: " + this.targetPort); + toolHelper.writeInfo("Default target port: " + this.targetPort); } // Set the target port to 80 if it was not provided or determined if (util.isNullOrEmpty(this.targetPort)) { this.targetPort = '80'; - githubActionsToolHelper.info("Default target port: " + this.targetPort); + toolHelper.writeInfo("Default target port: " + this.targetPort); } // Add the ingress value and target port to the optional arguments array // Note: this step should be skipped if we're updating an existing Container App (ingress is enabled via a separate command) @@ -548,7 +554,7 @@ var azurecontainerapps = /** @class */ (function () { this.commandLineArgs.push("--target-port " + this.targetPort); } } - var environmentVariables = githubActionsToolHelper.getInput('environmentVariables', { required: false }); + var environmentVariables = toolHelper.getInput('environmentVariables', { required: false }); // Add user-specified environment variables if (!util.isNullOrEmpty(environmentVariables)) { // The --replace-env-vars flag is only used for the 'update' command, @@ -626,8 +632,8 @@ var azurecontainerapps = /** @class */ (function () { }); }; // GitHub Action properties - azurecontainerapps.githubRunId = githubActionsToolHelper.getGithubRunId(); - azurecontainerapps.githubRunNumber = githubActionsToolHelper.getGithubRunNumber(); + azurecontainerapps.buildId = toolHelper.getbuildId(); + azurecontainerapps.buildNumber = toolHelper.getbuildNumber(); return azurecontainerapps; }()); exports.azurecontainerapps = azurecontainerapps; @@ -4640,7 +4646,7 @@ var ORYX_CLI_IMAGE = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208. var ORYX_BUILDER_IMAGE = 'mcr.microsoft.com/oryx/builder:20230208.1'; var IS_WINDOWS_AGENT = os.platform() == 'win32'; var PACK_CMD = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; -var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); +var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); var util = new Utility_1.Utility(); var ContainerAppHelper = /** @class */ (function () { function ContainerAppHelper(disableTelemetry) { @@ -4661,7 +4667,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + toolHelper.writeDebug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4675,7 +4681,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_1 = _a.sent(); - githubActionsToolHelper.error(err_1.message); + toolHelper.writeError(err_1.message); throw err_1; case 4: return [2 /*return*/]; } @@ -4694,7 +4700,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); + toolHelper.writeDebug("Attempting to create Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4705,7 +4711,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_2 = _a.sent(); - githubActionsToolHelper.error(err_2.message); + toolHelper.writeError(err_2.message); throw err_2; case 4: return [2 /*return*/]; } @@ -4725,7 +4731,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + toolHelper.writeDebug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4739,7 +4745,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_3 = _a.sent(); - githubActionsToolHelper.error(err_3.message); + toolHelper.writeError(err_3.message); throw err_3; case 4: return [2 /*return*/]; } @@ -4761,7 +4767,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); + toolHelper.writeDebug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" based from image \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4781,7 +4787,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_4 = _a.sent(); - githubActionsToolHelper.error(err_4.message); + toolHelper.writeError(err_4.message); throw err_4; case 4: return [2 /*return*/]; } @@ -4800,7 +4806,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); + toolHelper.writeDebug("Attempting to update Container App with name \"" + containerAppName + "\" in resource group \"" + resourceGroup + "\" from provided YAML \"" + yamlConfigPath + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4811,7 +4817,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_5 = _a.sent(); - githubActionsToolHelper.error(err_5.message); + toolHelper.writeError(err_5.message); throw err_5; case 4: return [2 /*return*/]; } @@ -4830,7 +4836,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to determine if Container App with name \"" + containerAppName + "\" exists in resource group \"" + resourceGroup + "\""); + toolHelper.writeDebug("Attempting to determine if Container App with name \"" + containerAppName + "\" exists in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4841,7 +4847,7 @@ var ContainerAppHelper = /** @class */ (function () { return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_6 = _a.sent(); - githubActionsToolHelper.warning(err_6.message); + toolHelper.writeWarning(err_6.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4860,7 +4866,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to determine if Container App Environment with name \"" + containerAppEnvironment + "\" exists in resource group \"" + resourceGroup + "\""); + toolHelper.writeDebug("Attempting to determine if Container App Environment with name \"" + containerAppEnvironment + "\" exists in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4871,7 +4877,7 @@ var ContainerAppHelper = /** @class */ (function () { return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_7 = _a.sent(); - githubActionsToolHelper.warning(err_7.message); + toolHelper.writeWarning(err_7.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4889,7 +4895,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to determine if resource group \"" + resourceGroup + "\" exists"); + toolHelper.writeDebug("Attempting to determine if resource group \"" + resourceGroup + "\" exists"); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4900,7 +4906,7 @@ var ContainerAppHelper = /** @class */ (function () { return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_8 = _a.sent(); - githubActionsToolHelper.warning(err_8.message); + toolHelper.writeWarning(err_8.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4917,7 +4923,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to get the default location for the Container App service for the subscription."); + toolHelper.writeDebug("Attempting to get the default location for the Container App service for the subscription."); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4926,10 +4932,10 @@ var ContainerAppHelper = /** @class */ (function () { case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return [2 /*return*/, !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; + return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; case 3: err_9 = _a.sent(); - githubActionsToolHelper.warning(err_9.message); + toolHelper.writeWarning(err_9.message); return [2 /*return*/, "eastus2"]; case 4: return [2 /*return*/]; } @@ -4947,7 +4953,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to create resource group \"" + name + "\" in location \"" + location + "\""); + toolHelper.writeDebug("Attempting to create resource group \"" + name + "\" in location \"" + location + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4958,7 +4964,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_10 = _a.sent(); - githubActionsToolHelper.error(err_10.message); + toolHelper.writeError(err_10.message); throw err_10; case 4: return [2 /*return*/]; } @@ -4976,7 +4982,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to get the existing Container App Environment in resource group \"" + resourceGroup + "\""); + toolHelper.writeDebug("Attempting to get the existing Container App Environment in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -4984,10 +4990,10 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, util.executeAndThrowIfError("az", args)]; case 2: executionResult = _a.sent(); - return [2 /*return*/, !executionResult.stderr ? executionResult.stdout : null]; + return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout : null]; case 3: err_11 = _a.sent(); - githubActionsToolHelper.warning(err_11.message); + toolHelper.writeWarning(err_11.message); return [2 /*return*/, null]; case 4: return [2 /*return*/]; } @@ -5007,7 +5013,7 @@ var ContainerAppHelper = /** @class */ (function () { switch (_a.label) { case 0: util = new Utility_1.Utility(); - githubActionsToolHelper.debug("Attempting to create Container App Environment with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + toolHelper.writeDebug("Attempting to create Container App Environment with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5021,7 +5027,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_12 = _a.sent(); - githubActionsToolHelper.error(err_12.message); + toolHelper.writeError(err_12.message); throw err_12; case 4: return [2 /*return*/]; } @@ -5039,7 +5045,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to disable ingress for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + toolHelper.writeDebug("Attempting to disable ingress for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5050,7 +5056,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_13 = _a.sent(); - githubActionsToolHelper.error(err_13.message); + toolHelper.writeError(err_13.message); throw err_13; case 4: return [2 /*return*/]; } @@ -5071,7 +5077,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to set the ACR details for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + toolHelper.writeDebug("Attempting to set the ACR details for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5082,7 +5088,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_14 = _a.sent(); - githubActionsToolHelper.error(err_14.message); + toolHelper.writeError(err_14.message); throw err_14; case 4: return [2 /*return*/]; } @@ -5101,11 +5107,11 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to create a runnable application image using the Oryx++ Builder with image name \"" + imageToDeploy + "\""); + toolHelper.writeDebug("Attempting to create a runnable application image using the Oryx++ Builder with image name \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - telemetryArg = githubActionsToolHelper.getTelemetryArg(); + telemetryArg = toolHelper.getTelemetryArg(); if (this.disableTelemetry) { telemetryArg = "ORYX_DISABLE_TELEMETRY=true"; } @@ -5115,7 +5121,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_15 = _a.sent(); - githubActionsToolHelper.error(err_15.message); + toolHelper.writeError(err_15.message); throw err_15; case 4: return [2 /*return*/]; } @@ -5135,21 +5141,21 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to create a runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); + toolHelper.writeDebug("Attempting to create a runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; + return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ['build', '--file', "" + dockerfilePath, "" + appSourcePath, '--tag', "" + imageToDeploy])]; case 3: _a.sent(); - githubActionsToolHelper.debug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); + toolHelper.writeDebug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); return [3 /*break*/, 5]; case 4: err_16 = _a.sent(); - githubActionsToolHelper.error(err_16.message); + toolHelper.writeError(err_16.message); throw err_16; case 5: return [2 /*return*/]; } @@ -5167,11 +5173,11 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug('Attempting to determine the runtime stack needed for the provided application source'); + toolHelper.writeDebug('Attempting to determine the runtime stack needed for the provided application source'); _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; + return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file @@ -5186,19 +5192,19 @@ var ContainerAppHelper = /** @class */ (function () { var lines = data.split('\n'); return lines[0]; })["catch"](function (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; }); // Delete the temp file fs.unlink(oryxRuntimeTxtPath_1, function (err) { if (err) { - githubActionsToolHelper.warning("Unable to delete the temporary file \"" + oryxRuntimeTxtPath_1 + "\". Error: " + err.message); + toolHelper.writeWarning("Unable to delete the temporary file \"" + oryxRuntimeTxtPath_1 + "\". Error: " + err.message); } }); return [2 /*return*/, runtimeStack]; case 4: err_17 = _a.sent(); - githubActionsToolHelper.error(err_17.message); + toolHelper.writeError(err_17.message); throw err_17; case 5: return [2 /*return*/]; } @@ -5215,7 +5221,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); + toolHelper.writeInfo('Setting the Oryx++ Builder as the default builder via the pack CLI'); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5225,7 +5231,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_18 = _a.sent(); - githubActionsToolHelper.error(err_18.message); + toolHelper.writeError(err_18.message); throw err_18; case 4: return [2 /*return*/]; } @@ -5234,7 +5240,7 @@ var ContainerAppHelper = /** @class */ (function () { }; /** * Installs the pack CLI that will be used to build a runnable application image. - * For more information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ + * For more Information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ */ ContainerAppHelper.prototype.installPackCliAsync = function () { return __awaiter(this, void 0, void 0, function () { @@ -5242,7 +5248,7 @@ var ContainerAppHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug('Attempting to install the pack CLI'); + toolHelper.writeDebug('Attempting to install the pack CLI'); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5269,7 +5275,7 @@ var ContainerAppHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_19 = _a.sent(); - githubActionsToolHelper.error("Unable to install the pack CLI. Error: " + err_19.message); + toolHelper.writeError("Unable to install the pack CLI. Error: " + err_19.message); throw err_19; case 4: return [2 /*return*/]; } @@ -5329,7 +5335,7 @@ exports.ContainerRegistryHelper = void 0; var os = __nccwpck_require__(2037); var Utility_1 = __nccwpck_require__(2135); var GithubActionsToolHelper_1 = __nccwpck_require__(2153); -var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); +var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); var util = new Utility_1.Utility(); var ContainerRegistryHelper = /** @class */ (function () { function ContainerRegistryHelper() { @@ -5342,23 +5348,26 @@ var ContainerRegistryHelper = /** @class */ (function () { */ ContainerRegistryHelper.prototype.loginAcrWithUsernamePassword = function (acrName, acrUsername, acrPassword) { return __awaiter(this, void 0, void 0, function () { - var err_1; + var dockerTool, err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + toolHelper.writeDebug("Attempting to log in to ACR instance \"" + acrName + "\" with username and password credentials"); _a.label = 1; case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, githubActionsToolHelper.exec('docker', ["login", "--password-stdin", "--username", "" + acrUsername, acrName + ".azurecr.io"], { input: Buffer.from(acrPassword) })]; + _a.trys.push([1, 4, , 5]); + return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: - _a.sent(); - return [3 /*break*/, 4]; + dockerTool = _a.sent(); + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ["login", "--username", "" + acrUsername, "--password", "" + acrPassword, acrName + ".azurecr.io"], Buffer.from(acrPassword))]; case 3: + _a.sent(); + return [3 /*break*/, 5]; + case 4: err_1 = _a.sent(); - githubActionsToolHelper.error("Failed to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + toolHelper.writeError("Failed to log in to ACR instance \"" + acrName + "\" with username and password credentials"); throw err_1; - case 4: return [2 /*return*/]; + case 5: return [2 /*return*/]; } }); }); @@ -5374,7 +5383,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to log in to ACR instance \"" + acrName + "\" with access token"); + toolHelper.writeDebug("Attempting to log in to ACR instance \"" + acrName + "\" with access token"); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5386,7 +5395,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_2 = _a.sent(); - githubActionsToolHelper.error("Failed to log in to ACR instance \"" + acrName + "\" with access token"); + toolHelper.writeError("Failed to log in to ACR instance \"" + acrName + "\" with access token"); throw err_2; case 4: return [2 /*return*/]; } @@ -5403,11 +5412,11 @@ var ContainerRegistryHelper = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - githubActionsToolHelper.debug("Attempting to push image \"" + imageToPush + "\" to ACR"); + toolHelper.writeDebug("Attempting to push image \"" + imageToPush + "\" to ACR"); _a.label = 1; case 1: _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; + return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ["push", "" + imageToPush])]; @@ -5416,7 +5425,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [3 /*break*/, 5]; case 4: err_3 = _a.sent(); - githubActionsToolHelper.error("Failed to push image \"" + imageToPush + "\" to ACR. Error: " + err_3.message); + toolHelper.writeError("Failed to push image \"" + imageToPush + "\" to ACR. Error: " + err_3.message); throw err_3; case 5: return [2 /*return*/]; } @@ -5472,83 +5481,95 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } }; exports.__esModule = true; -exports.GithubActionsToolHelper = void 0; +exports.GitHubActionsToolHelper = void 0; var core = __nccwpck_require__(3195); var io = __nccwpck_require__(9529); var exec = __nccwpck_require__(9714); -var GithubActionsToolHelper = /** @class */ (function () { - function GithubActionsToolHelper() { +var GitHubActionsToolHelper = /** @class */ (function () { + function GitHubActionsToolHelper() { } - GithubActionsToolHelper.prototype.getGithubRunId = function () { + GitHubActionsToolHelper.prototype.getbuildId = function () { return process.env['GITHUB_RUN_ID'] || ''; }; - GithubActionsToolHelper.prototype.getGithubRunNumber = function () { + GitHubActionsToolHelper.prototype.getbuildNumber = function () { return process.env['GITHUB_RUN_NUMBER'] || ''; }; - GithubActionsToolHelper.prototype.info = function (message) { + GitHubActionsToolHelper.prototype.writeInfo = function (message) { core.info(message); }; - GithubActionsToolHelper.prototype.error = function (message) { + GitHubActionsToolHelper.prototype.writeError = function (message) { core.error(message); }; - GithubActionsToolHelper.prototype.warning = function (message) { + GitHubActionsToolHelper.prototype.writeWarning = function (message) { core.warning(message); }; - GithubActionsToolHelper.prototype.debug = function (message) { + GitHubActionsToolHelper.prototype.writeDebug = function (message) { core.debug(message); }; - GithubActionsToolHelper.prototype.exec = function (commandLine, args, execOptions) { + GitHubActionsToolHelper.prototype.exec = function (commandLine, args, inputOptions) { return __awaiter(this, void 0, void 0, function () { + var stdout_1, stderr_1, options, exitCode_1, err_1; return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, exec.exec(commandLine, args, execOptions)]; - case 1: return [2 /*return*/, _a.sent()]; + case 0: + _a.trys.push([0, 2, , 3]); + stdout_1 = ''; + stderr_1 = ''; + options = { + listeners: { + stdout: function (data) { + stdout_1 += data.toString(); + }, + stderr: function (data) { + stderr_1 += data.toString(); + } + }, + input: inputOptions + }; + return [4 /*yield*/, exec.exec(commandLine, args, options)]; + case 1: + exitCode_1 = _a.sent(); + return [2 /*return*/, new Promise(function (resolve, reject) { + var executionResult = { + exitCode: exitCode_1, + stdout: stdout_1, + stderr: stderr_1 + }; + resolve(executionResult); + })]; + case 2: + err_1 = _a.sent(); + throw err_1; + case 3: return [2 /*return*/]; } }); }); }; - GithubActionsToolHelper.prototype.ExecOptions = function () { - return __awaiter(this, void 0, void 0, function () { - var stdout, stderr, options; - return __generator(this, function (_a) { - stdout = ''; - stderr = ''; - options = { - listeners: { - stdout: function (data) { - stdout += data.toString(); - }, - stderr: function (data) { - stderr += data.toString(); - } - } - }; - return [2 /*return*/, options]; - }); - }); - }; - GithubActionsToolHelper.prototype.getInput = function (name, options) { + GitHubActionsToolHelper.prototype.getInput = function (name, options) { return core.getInput(name, options); }; - GithubActionsToolHelper.prototype.setFailed = function (message) { + GitHubActionsToolHelper.prototype.setFailed = function (message) { core.setFailed(message); }; - GithubActionsToolHelper.prototype.which = function (tool, check) { + GitHubActionsToolHelper.prototype.which = function (tool, check) { return io.which(tool, check); }; - GithubActionsToolHelper.prototype.getContainerAppName = function (containerAppName) { - containerAppName = "gh-action-app-" + this.getGithubRunId() + "-" + this.getGithubRunNumber(); + GitHubActionsToolHelper.prototype.getDefaultContainerAppName = function (containerAppName) { + containerAppName = "gh-action-app-" + this.getbuildId() + "-" + this.getbuildNumber(); // Replace all '.' characters with '-' characters in the Container App name containerAppName = containerAppName.replace(/\./gi, "-"); - this.info("Default Container App name: " + containerAppName); + this.writeInfo("Default Container App name: " + containerAppName); return containerAppName; }; - GithubActionsToolHelper.prototype.getTelemetryArg = function () { + GitHubActionsToolHelper.prototype.getTelemetryArg = function () { return "CALLER_ID=github-actions-v1"; }; - return GithubActionsToolHelper; + GitHubActionsToolHelper.prototype.getEventName = function () { + return "ContainerAppsGitHubActionV1"; + }; + return GitHubActionsToolHelper; }()); -exports.GithubActionsToolHelper = GithubActionsToolHelper; +exports.GitHubActionsToolHelper = GitHubActionsToolHelper; /***/ }), @@ -5605,7 +5626,7 @@ var BUILDER_SCENARIO = "used-builder"; var DOCKERFILE_SCENARIO = "used-dockerfile"; var IMAGE_SCENARIO = "used-image"; var util = new Utility_1.Utility(); -var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); +var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); var TelemetryHelper = /** @class */ (function () { function TelemetryHelper(disableTelemetry) { this.disableTelemetry = disableTelemetry; @@ -5647,16 +5668,16 @@ var TelemetryHelper = /** @class */ (function () { */ TelemetryHelper.prototype.sendLogs = function () { return __awaiter(this, void 0, void 0, function () { - var taskLengthMilliseconds, resultArg, scenarioArg, errorMessageArg, args, err_1; + var taskLengthMilliseconds, resultArg, scenarioArg, errorMessageArg, eventName, args, dockerTool, err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: taskLengthMilliseconds = Date.now() - this.taskStartMilliseconds; - if (!!this.disableTelemetry) return [3 /*break*/, 4]; - githubActionsToolHelper.info("Telemetry enabled; logging metadata about task result, length and scenario targeted."); + if (!!this.disableTelemetry) return [3 /*break*/, 5]; + toolHelper.writeInfo("Telemetry enabled; logging metadata about task result, length and scenario targeted."); _a.label = 1; case 1: - _a.trys.push([1, 3, , 4]); + _a.trys.push([1, 4, , 5]); resultArg = ''; if (!util.isNullOrEmpty(this.result)) { resultArg = "--property result=" + this.result; @@ -5669,16 +5690,20 @@ var TelemetryHelper = /** @class */ (function () { if (!util.isNullOrEmpty(this.errorMessage)) { errorMessageArg = "--property errorMessage=" + this.errorMessage; } - args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name ContainerAppsGitHubActionV1 " + ("--processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; - return [4 /*yield*/, executeDockerCommand(args, true)]; + eventName = toolHelper.getEventName(); + args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name " + eventName + " " + ("--processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; + return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: - _a.sent(); - return [3 /*break*/, 4]; + dockerTool = _a.sent(); + return [4 /*yield*/, toolHelper.exec(dockerTool, args)]; case 3: + _a.sent(); + return [3 /*break*/, 5]; + case 4: err_1 = _a.sent(); - githubActionsToolHelper.warning("Skipping telemetry logging due to the following exception: " + err_1.message); - return [3 /*break*/, 4]; - case 4: return [2 /*return*/]; + toolHelper.writeWarning("Skipping telemetry logging due to the following exception: " + err_1.message); + return [3 /*break*/, 5]; + case 5: return [2 /*return*/]; } }); }); @@ -5686,30 +5711,6 @@ var TelemetryHelper = /** @class */ (function () { return TelemetryHelper; }()); exports.TelemetryHelper = TelemetryHelper; -var executeDockerCommand = function (args, continueOnError) { - if (continueOnError === void 0) { continueOnError = false; } - return __awaiter(void 0, void 0, void 0, function () { - var dockerTool, err_2; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - _a.trys.push([0, 3, , 4]); - return [4 /*yield*/, githubActionsToolHelper.which("docker", true)]; - case 1: - dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, args, continueOnError)]; - case 2: - _a.sent(); - return [3 /*break*/, 4]; - case 3: - err_2 = _a.sent(); - githubActionsToolHelper.error("Error: " + err_2.message); - throw err_2; // Re-throw the error - case 4: return [2 /*return*/]; - } - }); - }); -}; /***/ }), @@ -5759,7 +5760,7 @@ exports.__esModule = true; exports.Utility = void 0; // Note: This file is used to define utility functions that can be used across the project. var GithubActionsToolHelper_1 = __nccwpck_require__(2153); -var githubActionsToolHelper = new GithubActionsToolHelper_1.GithubActionsToolHelper(); +var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); var Utility = /** @class */ (function () { function Utility() { } @@ -5768,39 +5769,20 @@ var Utility = /** @class */ (function () { * @param args - the arguments to pass to the command * @param continueOnError - whether or not to continue execution if the command fails */ - Utility.prototype.executeAndThrowIfError = function (commandLine, args, continueOnError) { - if (continueOnError === void 0) { continueOnError = false; } + Utility.prototype.executeAndThrowIfError = function (commandLine, args, inputOptions) { return __awaiter(this, void 0, void 0, function () { - var options, stderr_1, stdout_1, exitCode_1, error_1; + var error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: - _a.trys.push([0, 3, , 4]); - return [4 /*yield*/, githubActionsToolHelper.ExecOptions()]; - case 1: - options = _a.sent(); - stderr_1 = options.listeners.stderr.toString(); - stdout_1 = options.listeners.stdout.toString(); - return [4 /*yield*/, githubActionsToolHelper.exec(commandLine, args, options)]; + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, toolHelper.exec(commandLine, args, inputOptions)]; + case 1: return [2 /*return*/, _a.sent()]; case 2: - exitCode_1 = _a.sent(); - if (!continueOnError && exitCode_1 !== 0) { - githubActionsToolHelper.error("Command failed with exit code " + exitCode_1 + ". Error stream: " + stderr_1); - throw new Error("Command failed with exit code " + exitCode_1 + ". Error stream: " + stderr_1); - } - return [2 /*return*/, new Promise(function (resolve, reject) { - var executionResult = { - exitCode: exitCode_1, - stdout: stdout_1, - stderr: stderr_1 - }; - resolve(executionResult); - })]; - case 3: error_1 = _a.sent(); - githubActionsToolHelper.error("Error: " + error_1.message); + toolHelper.writeError("Error: " + error_1.message); throw error_1; // Re-throw the error - case 4: return [2 /*return*/]; + case 3: return [2 /*return*/]; } }); }); diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 7c3a8649..f85a0cef 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -1,14 +1,14 @@ import * as path from 'path'; import * as os from 'os'; import { Utility } from './Utility'; -import { GithubActionsToolHelper } from './GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './GithubActionsToolHelper' import fs = require('fs'); const ORYX_CLI_IMAGE: string = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; const ORYX_BUILDER_IMAGE: string = 'mcr.microsoft.com/oryx/builder:20230208.1'; const IS_WINDOWS_AGENT: boolean = os.platform() == 'win32'; const PACK_CMD: string = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; -const githubActionsToolHelper = new GithubActionsToolHelper(); +const toolHelper = new GitHubActionsToolHelper(); const util = new Utility(); export class ContainerAppHelper { @@ -32,7 +32,7 @@ export class ContainerAppHelper { environment: string, imageToDeploy: string, optionalCmdArgs: string[]) { - githubActionsToolHelper.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; optionalCmdArgs.forEach(function (val: string) { @@ -40,7 +40,7 @@ export class ContainerAppHelper { }); await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -55,12 +55,12 @@ export class ContainerAppHelper { containerAppName: string, resourceGroup: string, yamlConfigPath: string) { - githubActionsToolHelper.debug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -77,7 +77,7 @@ export class ContainerAppHelper { resourceGroup: string, imageToDeploy: string, optionalCmdArgs: string[]) { - githubActionsToolHelper.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { @@ -85,7 +85,7 @@ export class ContainerAppHelper { }); await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -106,7 +106,7 @@ export class ContainerAppHelper { optionalCmdArgs: string[], ingress?: string, targetPort?: string) { - githubActionsToolHelper.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); + toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { let command = `containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { @@ -122,7 +122,7 @@ export class ContainerAppHelper { } await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -137,12 +137,12 @@ export class ContainerAppHelper { containerAppName: string, resourceGroup: string, yamlConfigPath: string) { - githubActionsToolHelper.debug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); + toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -154,13 +154,13 @@ export class ContainerAppHelper { * @returns true if the Container App exists, false otherwise */ public async doesContainerAppExist(containerAppName: string, resourceGroup: string): Promise { - githubActionsToolHelper.debug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); + toolHelper.writeDebug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { let command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); return executionResult.exitCode === 0; } catch (err) { - githubActionsToolHelper.warning(err.message); + toolHelper.writeWarning(err.message); return false; } } @@ -172,13 +172,13 @@ export class ContainerAppHelper { * @returns true if the Container App Environment exists, false otherwise */ public async doesContainerAppEnvironmentExist(containerAppEnvironment: string, resourceGroup: string): Promise { - githubActionsToolHelper.debug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); + toolHelper.writeDebug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { let command = `containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); return executionResult.exitCode === 0; } catch (err) { - githubActionsToolHelper.warning(err.message); + toolHelper.writeWarning(err.message); return false; } } @@ -189,13 +189,13 @@ export class ContainerAppHelper { * @returns true if the resource group exists, false otherwise */ public async doesResourceGroupExist(resourceGroup: string): Promise { - githubActionsToolHelper.debug(`Attempting to determine if resource group "${resourceGroup}" exists`); + toolHelper.writeDebug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { let command = `group show -n ${resourceGroup} -o none`; let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); return executionResult.exitCode === 0; } catch (err) { - githubActionsToolHelper.warning(err.message); + toolHelper.writeWarning(err.message); return false; } } @@ -205,14 +205,14 @@ export class ContainerAppHelper { * @returns the default location if found, otherwise 'eastus2' */ public async getDefaultContainerAppLocation(): Promise { - githubActionsToolHelper.debug(`Attempting to get the default location for the Container App service for the subscription.`); + toolHelper.writeDebug(`Attempting to get the default location for the Container App service for the subscription.`); try { let args = [`provider`, `show`, `-n`, `Microsoft.App`, `--query`, `resourceTypes[?resourceType=='containerApps'].locations[] | [0]`]; let executionResult = await util.executeAndThrowIfError(`az`, args); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return !executionResult.stderr ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; + return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { - githubActionsToolHelper.warning(err.message); + toolHelper.writeWarning(err.message); return `eastus2`; } } @@ -223,12 +223,12 @@ export class ContainerAppHelper { * @param location - the location to create the resource group in */ public async createResourceGroup(name: string, location: string) { - githubActionsToolHelper.debug(`Attempting to create resource group "${name}" in location "${location}"`); + toolHelper.writeDebug(`Attempting to create resource group "${name}" in location "${location}"`); try { let command = `group create -n ${name} -l ${location}`; await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -239,13 +239,13 @@ export class ContainerAppHelper { * @returns the name of the existing Container App Environment, null if none exists */ public async getExistingContainerAppEnvironment(resourceGroup: string) { - githubActionsToolHelper.debug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); + toolHelper.writeDebug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { let args = [`containerapp`, `env`, `list`, `-g`, `${resourceGroup}`, `--query`, `[0].name`]; let executionResult = await util.executeAndThrowIfError(`az`, args); - return !executionResult.stderr ? executionResult.stdout : null; + return executionResult.exitCode === 0 ? executionResult.stdout : null; } catch (err) { - githubActionsToolHelper.warning(err.message); + toolHelper.writeWarning(err.message); return null; } } @@ -258,7 +258,7 @@ export class ContainerAppHelper { */ public async createContainerAppEnvironment(name: string, resourceGroup: string, location?: string) { const util = new Utility(); - githubActionsToolHelper.debug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); + toolHelper.writeDebug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); try { let args = [`containerapp`, `env`, `create`, `-n`, `${name}`, `-g`, `${resourceGroup}`]; if (!util.isNullOrEmpty(location)) { @@ -266,7 +266,7 @@ export class ContainerAppHelper { } await util.executeAndThrowIfError(`az`, args); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -277,12 +277,12 @@ export class ContainerAppHelper { * @param resourceGroup - the resource group that the Container App is found in */ public async disableContainerAppIngress(name: string, resourceGroup: string) { - githubActionsToolHelper.debug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); + toolHelper.writeDebug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); try { let command = `containerapp ingress disable -n ${name} -g ${resourceGroup}`; await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -296,12 +296,12 @@ export class ContainerAppHelper { * @param acrPassword - the password used to authenticate with the Azure Container Registry */ public async updateContainerAppRegistryDetails(name: string, resourceGroup: string, acrName: string, acrUsername: string, acrPassword: string) { - githubActionsToolHelper.debug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); + toolHelper.writeDebug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { let command = `containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -316,15 +316,15 @@ export class ContainerAppHelper { imageToDeploy: string, appSourcePath: string, runtimeStack: string) { - githubActionsToolHelper.debug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); + toolHelper.writeDebug(`Attempting to create a runnable application image using the Oryx++ Builder with image name "${imageToDeploy}"`); try { - let telemetryArg = githubActionsToolHelper.getTelemetryArg(); + let telemetryArg = toolHelper.getTelemetryArg(); if (this.disableTelemetry) { telemetryArg = `ORYX_DISABLE_TELEMETRY=true`; } await util.executeAndThrowIfError(`${PACK_CMD}`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, '--env', `${telemetryArg}`]); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -340,13 +340,13 @@ export class ContainerAppHelper { imageToDeploy: string, appSourcePath: string, dockerfilePath: string) { - githubActionsToolHelper.debug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + toolHelper.writeDebug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); try { - let dockerTool = await githubActionsToolHelper.which("docker", true); + let dockerTool = await toolHelper.which("docker", true); await util.executeAndThrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); - githubActionsToolHelper.debug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); + toolHelper.writeDebug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -357,9 +357,9 @@ export class ContainerAppHelper { * @returns a string representing the runtime stack that can be used for the Oryx MCR runtime images */ public async determineRuntimeStackAsync(appSourcePath: string): Promise { - githubActionsToolHelper.debug('Attempting to determine the runtime stack needed for the provided application source'); + toolHelper.writeDebug('Attempting to determine the runtime stack needed for the provided application source'); try { - let dockerTool: string = await githubActionsToolHelper.which("docker", true); + let dockerTool: string = await toolHelper.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file await util.executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', `${appSourcePath}:/app`, `${ORYX_CLI_IMAGE}`, '/bin/bash', '-c', `oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt`]) @@ -370,20 +370,20 @@ export class ContainerAppHelper { let lines = data.split('\n'); return lines[0]; }).catch((err) => { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; }); // Delete the temp file fs.unlink(oryxRuntimeTxtPath, (err) => { if (err) { - githubActionsToolHelper.warning(`Unable to delete the temporary file "${oryxRuntimeTxtPath}". Error: ${err.message}`); + toolHelper.writeWarning(`Unable to delete the temporary file "${oryxRuntimeTxtPath}". Error: ${err.message}`); } }); return runtimeStack; } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } @@ -393,22 +393,22 @@ export class ContainerAppHelper { * to no default builder set. */ public async setDefaultBuilder() { - githubActionsToolHelper.info('Setting the Oryx++ Builder as the default builder via the pack CLI'); + toolHelper.writeInfo('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { await util.executeAndThrowIfError(`${PACK_CMD}`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); } catch (err) { - githubActionsToolHelper.error(err.message); + toolHelper.writeError(err.message); throw err; } } /** * Installs the pack CLI that will be used to build a runnable application image. - * For more information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ + * For more Information about the pack CLI can be found here: https://buildpacks.io/docs/tools/pack/ */ public async installPackCliAsync() { - githubActionsToolHelper.debug('Attempting to install the pack CLI'); + toolHelper.writeDebug('Attempting to install the pack CLI'); try { let command: string = ''; let commandLine = ''; @@ -428,7 +428,7 @@ export class ContainerAppHelper { } await util.executeAndThrowIfError(commandLine, args); } catch (err) { - githubActionsToolHelper.error(`Unable to install the pack CLI. Error: ${err.message}`); + toolHelper.writeError(`Unable to install the pack CLI. Error: ${err.message}`); throw err; } } diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index e525aaba..d5648d65 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -1,8 +1,8 @@ import * as os from 'os'; import { Utility } from './Utility'; -import { GithubActionsToolHelper } from './GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './GithubActionsToolHelper'; -const githubActionsToolHelper = new GithubActionsToolHelper(); +const toolHelper = new GitHubActionsToolHelper(); const util = new Utility(); export class ContainerRegistryHelper { @@ -13,11 +13,12 @@ export class ContainerRegistryHelper { * @param acrPassword - the password for authentication */ public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { - githubActionsToolHelper.debug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); + toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); try { - await githubActionsToolHelper.exec('docker', [`login`, `--password-stdin`, `--username`, `${acrUsername}`, `${acrName}.azurecr.io`], { input: Buffer.from(acrPassword) }); + let dockerTool = await toolHelper.which("docker", true); + await util.executeAndThrowIfError(dockerTool, [`login`, `--username`, `${acrUsername}`, `--password`, `${acrPassword}`, `${acrName}.azurecr.io`], Buffer.from(acrPassword)); } catch (err) { - githubActionsToolHelper.error(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); + toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); throw err; } } @@ -28,13 +29,13 @@ export class ContainerRegistryHelper { * @param acrName - the name of the ACR instance to authenticate calls to. */ public async loginAcrWithAccessTokenAsync(acrName: string) { - githubActionsToolHelper.debug(`Attempting to log in to ACR instance "${acrName}" with access token`); + toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { let command: string = `CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`; let commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; await util.executeAndThrowIfError(commandLine, ['-c', command]); } catch (err) { - githubActionsToolHelper.error(`Failed to log in to ACR instance "${acrName}" with access token`) + toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; } } @@ -44,12 +45,12 @@ export class ContainerRegistryHelper { * @param imageToPush - the name of the image to push to ACR */ public async pushImageToAcr(imageToPush: string) { - githubActionsToolHelper.debug(`Attempting to push image "${imageToPush}" to ACR`); + toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to ACR`); try { - let dockerTool: string = await githubActionsToolHelper.which("docker", true); + let dockerTool: string = await toolHelper.which("docker", true); await util.executeAndThrowIfError(dockerTool, [`push`, `${imageToPush}`]); } catch (err) { - githubActionsToolHelper.error(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); + toolHelper.writeError(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); throw err; } } diff --git a/src/GithubActionsToolHelper.ts b/src/GithubActionsToolHelper.ts index bf672c86..9edb204a 100644 --- a/src/GithubActionsToolHelper.ts +++ b/src/GithubActionsToolHelper.ts @@ -2,37 +2,34 @@ import * as core from '@actions/core'; import * as io from '@actions/io'; import * as exec from '@actions/exec'; -export class GithubActionsToolHelper { +export class GitHubActionsToolHelper { - public getGithubRunId(): string { + public getbuildId(): string { return process.env['GITHUB_RUN_ID'] || ''; } - public getGithubRunNumber(): string { + public getbuildNumber(): string { return process.env['GITHUB_RUN_NUMBER'] || ''; } - public info(message: string): void { + public writeInfo(message: string): void { core.info(message); } - public error(message: string): void { + public writeError(message: string): void { core.error(message); } - public warning(message: string): void { + public writeWarning(message: string): void { core.warning(message); } - public debug(message: string): void { + public writeDebug(message: string): void { core.debug(message); } - public async exec(commandLine: string, args?: string[], execOptions?: exec.ExecOptions): Promise { - return await exec.exec(commandLine, args, execOptions); - } - - public async ExecOptions(): Promise { + public async exec(commandLine: string, args?: string[], inputOptions?: Buffer): Promise<{ exitCode: number, stdout: string, stderr: string }> { + try{ let stdout = ''; let stderr = ''; @@ -45,8 +42,21 @@ export class GithubActionsToolHelper { stderr += data.toString(); }, }, + input: inputOptions }; - return options; + + let exitCode = await exec.exec(commandLine, args, options); + return new Promise((resolve, reject) => { + let executionResult = { + exitCode: exitCode, + stdout: stdout, + stderr: stderr + } + resolve(executionResult); + }); + }catch(err){ + throw err; + } } public getInput(name: string, options?: core.InputOptions): string { @@ -61,15 +71,19 @@ export class GithubActionsToolHelper { return io.which(tool, check); } - public getContainerAppName(containerAppName: string): string { - containerAppName = `gh-action-app-${this.getGithubRunId()}-${this.getGithubRunNumber()}`; + public getDefaultContainerAppName(containerAppName: string): string { + containerAppName = `gh-action-app-${this.getbuildId()}-${this.getbuildNumber()}`; // Replace all '.' characters with '-' characters in the Container App name containerAppName = containerAppName.replace(/\./gi, "-"); - this.info(`Default Container App name: ${containerAppName}`); - return containerAppName + this.writeInfo(`Default Container App name: ${containerAppName}`); + return containerAppName; } public getTelemetryArg(): string { return `CALLER_ID=github-actions-v1`; } + + public getEventName(): string { + return `ContainerAppsGitHubActionV1`; + } } \ No newline at end of file diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 181bda89..74151342 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -1,5 +1,5 @@ import { Utility } from './Utility'; -import { GithubActionsToolHelper } from './GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './GithubActionsToolHelper'; const ORYX_CLI_IMAGE: string = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; @@ -11,7 +11,7 @@ const DOCKERFILE_SCENARIO: string = "used-dockerfile"; const IMAGE_SCENARIO: string = "used-image"; const util = new Utility(); -const githubActionsToolHelper = new GithubActionsToolHelper(); +const toolHelper = new GitHubActionsToolHelper(); export class TelemetryHelper { readonly disableTelemetry: boolean; @@ -68,7 +68,7 @@ export class TelemetryHelper { public async sendLogs() { let taskLengthMilliseconds: number = Date.now() - this.taskStartMilliseconds; if (!this.disableTelemetry) { - githubActionsToolHelper.info(`Telemetry enabled; logging metadata about task result, length and scenario targeted.`); + toolHelper.writeInfo(`Telemetry enabled; logging metadata about task result, length and scenario targeted.`); try { let resultArg: string = ''; if (!util.isNullOrEmpty(this.result)) { @@ -85,22 +85,14 @@ export class TelemetryHelper { errorMessageArg = `--property errorMessage=${this.errorMessage}`; } - let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name ContainerAppsGitHubActionV1 ` + `--processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`]; - await executeDockerCommand(args, true) + let eventName = toolHelper.getEventName(); + let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name ${eventName} ` + `--processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`]; + let dockerTool: string = await toolHelper.which("docker", true); + + await toolHelper.exec(dockerTool, args); } catch (err) { - githubActionsToolHelper.warning(`Skipping telemetry logging due to the following exception: ${err.message}`); + toolHelper.writeWarning(`Skipping telemetry logging due to the following exception: ${err.message}`); } } } -} - -const executeDockerCommand = async (args: string[], continueOnError: boolean = false): Promise => { - try { - let dockerTool: string = await githubActionsToolHelper.which("docker", true); - await util.executeAndThrowIfError(dockerTool, args, continueOnError); - } - catch (err) { - githubActionsToolHelper.error(`Error: ${err.message}`); - throw err; // Re-throw the error - } } \ No newline at end of file diff --git a/src/Utility.ts b/src/Utility.ts index bd571550..9cd0df56 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -1,7 +1,7 @@ // Note: This file is used to define utility functions that can be used across the project. -import { GithubActionsToolHelper } from './GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './GithubActionsToolHelper'; -const githubActionsToolHelper = new GithubActionsToolHelper(); +const toolHelper = new GitHubActionsToolHelper(); export class Utility { /** @@ -10,28 +10,11 @@ export class Utility { * @param continueOnError - whether or not to continue execution if the command fails */ - public async executeAndThrowIfError(commandLine: string, args: string[], continueOnError: boolean = false): Promise<{ exitCode: number, stdout: string, stderr: string }> { + public async executeAndThrowIfError(commandLine: string, args: string[], inputOptions?:Buffer): Promise<{ exitCode: number, stdout: string, stderr: string }> { try { - let options = await githubActionsToolHelper.ExecOptions(); - let stderr = options.listeners.stderr.toString(); - let stdout = options.listeners.stdout.toString(); - - let exitCode = await githubActionsToolHelper.exec(commandLine, args, options); - - if (!continueOnError && exitCode !== 0) { - githubActionsToolHelper.error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); - throw new Error(`Command failed with exit code ${exitCode}. Error stream: ${stderr}`); - } - return new Promise((resolve, reject) => { - let executionResult = { - exitCode: exitCode, - stdout: stdout, - stderr: stderr - } - resolve(executionResult); - }); + return await toolHelper.exec(commandLine, args, inputOptions); } catch (error) { - githubActionsToolHelper.error(`Error: ${error.message}`); + toolHelper.writeError(`Error: ${error.message}`); throw error; // Re-throw the error } } From 1316d97e22dc2a48222973faed353a18d442875f Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Wed, 27 Sep 2023 21:15:11 -0700 Subject: [PATCH 21/42] Change comment for build-specific properties --- azurecontainerapps.ts | 6 +++--- dist/index.js | 10 +++++----- src/GithubActionsToolHelper.ts | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index 2d2fb2ea..cf0efd50 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -59,9 +59,9 @@ export class azurecontainerapps { } } - // GitHub Action properties - private static buildId: string = toolHelper.getbuildId(); - private static buildNumber: string = toolHelper.getbuildNumber(); + // Build-specific properties + private static buildId: string = toolHelper.getBuildId(); + private static buildNumber: string = toolHelper.getBuildNumber(); // Supported scenario properties private static appSourcePath: string; diff --git a/dist/index.js b/dist/index.js index a8d686ac..4d2b02be 100644 --- a/dist/index.js +++ b/dist/index.js @@ -631,9 +631,9 @@ var azurecontainerapps = /** @class */ (function () { }); }); }; - // GitHub Action properties - azurecontainerapps.buildId = toolHelper.getbuildId(); - azurecontainerapps.buildNumber = toolHelper.getbuildNumber(); + // Build-specific properties + azurecontainerapps.buildId = toolHelper.getBuildId(); + azurecontainerapps.buildNumber = toolHelper.getBuildNumber(); return azurecontainerapps; }()); exports.azurecontainerapps = azurecontainerapps; @@ -5488,10 +5488,10 @@ var exec = __nccwpck_require__(9714); var GitHubActionsToolHelper = /** @class */ (function () { function GitHubActionsToolHelper() { } - GitHubActionsToolHelper.prototype.getbuildId = function () { + GitHubActionsToolHelper.prototype.getBuildId = function () { return process.env['GITHUB_RUN_ID'] || ''; }; - GitHubActionsToolHelper.prototype.getbuildNumber = function () { + GitHubActionsToolHelper.prototype.getBuildNumber = function () { return process.env['GITHUB_RUN_NUMBER'] || ''; }; GitHubActionsToolHelper.prototype.writeInfo = function (message) { diff --git a/src/GithubActionsToolHelper.ts b/src/GithubActionsToolHelper.ts index 9edb204a..317a130a 100644 --- a/src/GithubActionsToolHelper.ts +++ b/src/GithubActionsToolHelper.ts @@ -4,11 +4,11 @@ import * as exec from '@actions/exec'; export class GitHubActionsToolHelper { - public getbuildId(): string { + public getBuildId(): string { return process.env['GITHUB_RUN_ID'] || ''; } - public getbuildNumber(): string { + public getBuildNumber(): string { return process.env['GITHUB_RUN_NUMBER'] || ''; } From 33f5847c666d4dd5e80eaeac8bbbb2587ca54c80 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Wed, 27 Sep 2023 21:26:27 -0700 Subject: [PATCH 22/42] Refactor default containerapp name --- dist/index.js | 2 +- src/GithubActionsToolHelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 4d2b02be..73122df0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5555,7 +5555,7 @@ var GitHubActionsToolHelper = /** @class */ (function () { return io.which(tool, check); }; GitHubActionsToolHelper.prototype.getDefaultContainerAppName = function (containerAppName) { - containerAppName = "gh-action-app-" + this.getbuildId() + "-" + this.getbuildNumber(); + containerAppName = "gh-action-app-" + this.getBuildId() + "-" + this.getBuildNumber(); // Replace all '.' characters with '-' characters in the Container App name containerAppName = containerAppName.replace(/\./gi, "-"); this.writeInfo("Default Container App name: " + containerAppName); diff --git a/src/GithubActionsToolHelper.ts b/src/GithubActionsToolHelper.ts index 317a130a..9da865f8 100644 --- a/src/GithubActionsToolHelper.ts +++ b/src/GithubActionsToolHelper.ts @@ -72,7 +72,7 @@ export class GitHubActionsToolHelper { } public getDefaultContainerAppName(containerAppName: string): string { - containerAppName = `gh-action-app-${this.getbuildId()}-${this.getbuildNumber()}`; + containerAppName = `gh-action-app-${this.getBuildId()}-${this.getBuildNumber()}`; // Replace all '.' characters with '-' characters in the Container App name containerAppName = containerAppName.replace(/\./gi, "-"); this.writeInfo(`Default Container App name: ${containerAppName}`); From 72a6e30129d8a23154d45884d55850f6606dc317 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Thu, 28 Sep 2023 14:45:30 -0700 Subject: [PATCH 23/42] Change command construction --- azurecontainerapps.ts | 170 +++++++++++---------- dist/index.js | 271 ++++++++++++++++----------------- src/ContainerAppHelper.ts | 58 +++---- src/ContainerRegistryHelper.ts | 9 +- src/TelemetryHelper.ts | 5 +- src/Utility.ts | 6 +- 6 files changed, 258 insertions(+), 261 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index cf0efd50..dd02e2fc 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -4,16 +4,12 @@ import { ContainerAppHelper } from './src/ContainerAppHelper'; import { ContainerRegistryHelper } from './src/ContainerRegistryHelper'; import { TelemetryHelper } from './src/TelemetryHelper'; import { Utility } from './src/Utility'; -import { GitHubActionsToolHelper } from './src/GithubActionsToolHelper'; - -const util = new Utility(); -const toolHelper = new GitHubActionsToolHelper(); +import { GitHubActionsToolHelper } from './src/GitHubActionsToolHelper'; export class azurecontainerapps { public static async runMain(): Promise { - let disableTelemetry = toolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; - this.initializeHelpers(disableTelemetry); + this.initializeHelpers(); try { // Validate that the arguments provided can be used for one of the supported scenarios @@ -26,22 +22,22 @@ export class azurecontainerapps { await this.setupResources(); // If an Azure Container Registry name was provided, try to authenticate against it - if (!util.isNullOrEmpty(this.acrName)) { + if (!this.util.isNullOrEmpty(this.acrName)) { await this.authenticateAzureContainerRegistryAsync(); } // If the application source was provided, build a runnable application image from it - if (!util.isNullOrEmpty(this.appSourcePath)) { + if (!this.util.isNullOrEmpty(this.appSourcePath)) { await this.buildAndPushImageAsync(); } // If no application source was provided, set up the scenario for deploying an existing image - if (util.isNullOrEmpty(this.appSourcePath)) { + if (this.util.isNullOrEmpty(this.appSourcePath)) { this.setupExistingImageScenario(); } // If no YAML configuration file was provided, set up the Container App properties - if (util.isNullOrEmpty(this.yamlConfigPath)) { + if (this.util.isNullOrEmpty(this.yamlConfigPath)) { this.setupContainerAppProperties(); } @@ -51,7 +47,7 @@ export class azurecontainerapps { // If telemetry is enabled, log that the task completed successfully this.telemetryHelper.setSuccessfulResult(); } catch (err) { - toolHelper.setFailed(err.message); + this.toolHelper.setFailed(err.message); this.telemetryHelper.setFailedResult(err.message); } finally { // If telemetry is enabled, will log metadata for this task run @@ -60,8 +56,8 @@ export class azurecontainerapps { } // Build-specific properties - private static buildId: string = toolHelper.getBuildId(); - private static buildNumber: string = toolHelper.getBuildNumber(); + private static buildId: string; + private static buildNumber: string; // Supported scenario properties private static appSourcePath: string; @@ -102,7 +98,21 @@ export class azurecontainerapps { * Initializes the helpers used by this task. * @param disableTelemetry - Whether or not to disable telemetry for this task. */ - private static initializeHelpers(disableTelemetry: boolean) { + private static initializeHelpers() { + // Set up Utility for managing miscellaneous calls + this.util = new Utility(); + + // Set up toolHelper for managing calls to the GitHub Actions toolkit + this.toolHelper = new GitHubActionsToolHelper(); + + let disableTelemetry = this.toolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; + + // Get buildId + this.buildId = this.toolHelper.getBuildId(); + + // Get buildNumber + this.buildNumber = this.toolHelper.getBuildNumber(); + // Set up TelemetryHelper for managing telemetry calls this.telemetryHelper = new TelemetryHelper(disableTelemetry); @@ -111,12 +121,6 @@ export class azurecontainerapps { // Set up ContainerRegistryHelper for managing calls around ACR this.registryHelper = new ContainerRegistryHelper(); - - // Set up Utility for managing miscellaneous calls - this.util = new Utility(); - - // Set up toolHelper for managing calls to the GitHub Actions toolkit - this.toolHelper = new GitHubActionsToolHelper(); } /** @@ -126,28 +130,28 @@ export class azurecontainerapps { private static validateSupportedScenarioArguments() { // Get the path to the application source to build and run, if provided - this.appSourcePath = toolHelper.getInput('appSourcePath', { required: false }); + this.appSourcePath = this.toolHelper.getInput('appSourcePath', { required: false }); // Get the name of the ACR instance to push images to, if provided - this.acrName = toolHelper.getInput('acrName', { required: false }); + this.acrName = this.toolHelper.getInput('acrName', { required: false }); // Get the previously built image to deploy, if provided - this.imageToDeploy = toolHelper.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', { required: false }); // Get the YAML configuration file, if provided - this.yamlConfigPath = toolHelper.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', { required: false }); // Ensure that acrName is also provided if appSourcePath is provided - if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { + if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName)) { let missingAcrNameMessage = `The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`; - toolHelper.writeError(missingAcrNameMessage); + this.toolHelper.writeError(missingAcrNameMessage); throw Error(missingAcrNameMessage); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided - if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { + if (this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.imageToDeploy) && this.util.isNullOrEmpty(this.yamlConfigPath)) { let requiredArgumentMessage = `One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'.`; - toolHelper.writeError(requiredArgumentMessage); + this.toolHelper.writeError(requiredArgumentMessage); throw Error(requiredArgumentMessage); } } @@ -158,7 +162,7 @@ export class azurecontainerapps { */ private static async setupAzureCli() { // Set the Azure CLI to dynamically install missing extensions - await util.setAzureCliDynamicInstall(); + await this.util.setAzureCliDynamicInstall(); } /** @@ -193,9 +197,9 @@ export class azurecontainerapps { * @returns The name of the Container App to use for the task. */ private static getContainerAppName(): string { - let containerAppName: string = toolHelper.getInput('containerAppName', { required: false }); - if (util.isNullOrEmpty(containerAppName)) { - return toolHelper.getDefaultContainerAppName(containerAppName); + let containerAppName: string = this.toolHelper.getInput('containerAppName', { required: false }); + if (this.util.isNullOrEmpty(containerAppName)) { + return this.toolHelper.getDefaultContainerAppName(containerAppName); } return containerAppName; @@ -208,10 +212,10 @@ export class azurecontainerapps { */ private static async getLocation(): Promise { // Set deployment location, if provided - let location: string = toolHelper.getInput('location', { required: false }); + let location: string = this.toolHelper.getInput('location', { required: false }); // If no location was provided, use the default location for the Container App service - if (util.isNullOrEmpty(location)) { + if (this.util.isNullOrEmpty(location)) { location = await this.appHelper.getDefaultContainerAppLocation(); } @@ -228,10 +232,10 @@ export class azurecontainerapps { */ private static async getOrCreateResourceGroup(containerAppName: string, location: string): Promise { // Get the resource group to deploy to if it was provided, or generate it from the Container App name - let resourceGroup: string = toolHelper.getInput('resourceGroup', { required: false }); - if (util.isNullOrEmpty(resourceGroup)) { + let resourceGroup: string = this.toolHelper.getInput('resourceGroup', { required: false }); + if (this.util.isNullOrEmpty(resourceGroup)) { resourceGroup = `${containerAppName}-rg`; - toolHelper.writeInfo(`Default resource group name: ${resourceGroup}`); + this.toolHelper.writeInfo(`Default resource group name: ${resourceGroup}`); // Ensure that the resource group that the Container App will be created in exists const resourceGroupExists = await this.appHelper.doesResourceGroupExist(resourceGroup); @@ -258,21 +262,21 @@ export class azurecontainerapps { resourceGroup: string, location: string): Promise { // Get the Container App environment if it was provided - let containerAppEnvironment: string = toolHelper.getInput('containerAppEnvironment', { required: false }); + let containerAppEnvironment: string = this.toolHelper.getInput('containerAppEnvironment', { required: false }); // See if we can reuse an existing Container App environment found in the resource group - if (util.isNullOrEmpty(containerAppEnvironment)) { + if (this.util.isNullOrEmpty(containerAppEnvironment)) { const existingContainerAppEnvironment: string = await this.appHelper.getExistingContainerAppEnvironment(resourceGroup); - if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { - toolHelper.writeInfo(`Existing Container App environment found in resource group: ${existingContainerAppEnvironment}`); + if (!this.util.isNullOrEmpty(existingContainerAppEnvironment)) { + this.toolHelper.writeInfo(`Existing Container App environment found in resource group: ${existingContainerAppEnvironment}`); return existingContainerAppEnvironment } } // Generate the Container App environment name if it was not provided - if (util.isNullOrEmpty(containerAppEnvironment)) { + if (this.util.isNullOrEmpty(containerAppEnvironment)) { containerAppEnvironment = `${containerAppName}-env`; - toolHelper.writeInfo(`Default Container App environment name: ${containerAppEnvironment}`); + this.toolHelper.writeInfo(`Default Container App environment name: ${containerAppEnvironment}`); } // Determine if the Container App environment currently exists and create one if it doesn't @@ -288,15 +292,15 @@ export class azurecontainerapps { * Authenticates calls to the provided Azure Container Registry. */ private static async authenticateAzureContainerRegistryAsync() { - this.acrUsername = toolHelper.getInput('acrUsername', { required: false }); - this.acrPassword = toolHelper.getInput('acrPassword', { required: false }); + this.acrUsername = this.toolHelper.getInput('acrUsername', { required: false }); + this.acrPassword = this.toolHelper.getInput('acrPassword', { required: false }); // Login to ACR if credentials were provided - if (!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword)) { - toolHelper.writeInfo(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); + if (!this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword)) { + this.toolHelper.writeInfo(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); await this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword); } else { - toolHelper.writeInfo(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); + this.toolHelper.writeInfo(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); await this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName); } } @@ -314,25 +318,25 @@ export class azurecontainerapps { */ private static async buildAndPushImageAsync() { // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = toolHelper.getInput('imageToBuild', { required: false }); - if (util.isNullOrEmpty(this.imageToBuild)) { + this.imageToBuild = this.toolHelper.getInput('imageToBuild', { required: false }); + if (this.util.isNullOrEmpty(this.imageToBuild)) { this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.buildId}.${this.buildNumber}`; - toolHelper.writeInfo(`Default image to build: ${this.imageToBuild}`); + this.toolHelper.writeInfo(`Default image to build: ${this.imageToBuild}`); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' - if (util.isNullOrEmpty(this.imageToDeploy)) { + if (this.util.isNullOrEmpty(this.imageToDeploy)) { this.imageToDeploy = this.imageToBuild; - toolHelper.writeInfo(`Default image to deploy: ${this.imageToDeploy}`); + this.toolHelper.writeInfo(`Default image to deploy: ${this.imageToDeploy}`); } // Get Dockerfile to build, if provided, or check if one exists at the root of the provided application - let dockerfilePath: string = toolHelper.getInput('dockerfilePath', { required: false }); - if (util.isNullOrEmpty(dockerfilePath)) { - toolHelper.writeInfo(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); + let dockerfilePath: string = this.toolHelper.getInput('dockerfilePath', { required: false }); + if (this.util.isNullOrEmpty(dockerfilePath)) { + this.toolHelper.writeInfo(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); const rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); if (fs.existsSync(rootDockerfilePath)) { - toolHelper.writeInfo(`Dockerfile found at root of application source.`) + this.toolHelper.writeInfo(`Dockerfile found at root of application source.`) dockerfilePath = rootDockerfilePath; } else { // No Dockerfile found or provided, build the image using the builder @@ -342,7 +346,7 @@ export class azurecontainerapps { dockerfilePath = path.join(this.appSourcePath, dockerfilePath); } - if (!util.isNullOrEmpty(dockerfilePath)) { + if (!this.util.isNullOrEmpty(dockerfilePath)) { // Build the image from the provided/discovered Dockerfile await this.builderImageFromDockerfile(this.appSourcePath, dockerfilePath, this.imageToBuild); } @@ -359,16 +363,16 @@ export class azurecontainerapps { private static async buildImageFromBuilderAsync(appSourcePath: string, imageToBuild: string) { // Install the pack CLI await this.appHelper.installPackCliAsync(); - toolHelper.writeInfo(`Successfully installed the pack CLI.`) + this.toolHelper.writeInfo(`Successfully installed the pack CLI.`) // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = toolHelper.getInput('runtimeStack', { required: false }); - if (util.isNullOrEmpty(this.runtimeStack)) { + this.runtimeStack = this.toolHelper.getInput('runtimeStack', { required: false }); + if (this.util.isNullOrEmpty(this.runtimeStack)) { this.runtimeStack = await this.appHelper.determineRuntimeStackAsync(appSourcePath); - toolHelper.writeInfo(`Runtime stack determined to be: ${this.runtimeStack}`); + this.toolHelper.writeInfo(`Runtime stack determined to be: ${this.runtimeStack}`); } - toolHelper.writeInfo(`Building image "${imageToBuild}" using the Oryx++ Builder`); + this.toolHelper.writeInfo(`Building image "${imageToBuild}" using the Oryx++ Builder`); // Set the Oryx++ Builder as the default builder locally await this.appHelper.setDefaultBuilder(); @@ -387,7 +391,7 @@ export class azurecontainerapps { * @param imageToBuild - The name of the image to build. */ private static async builderImageFromDockerfile(appSourcePath: string, dockerfilePath: string, imageToBuild: string) { - toolHelper.writeInfo(`Building image "${imageToBuild}" using the provided Dockerfile`); + this.toolHelper.writeInfo(`Building image "${imageToBuild}" using the provided Dockerfile`); await this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath); // If telemetry is enabled, log that the Dockerfile scenario was targeted for this task @@ -402,17 +406,17 @@ export class azurecontainerapps { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = toolHelper.getInput('ingress', { required: false }); - this.targetPort = toolHelper.getInput('targetPort', { required: false }); + this.ingress = this.toolHelper.getInput('ingress', { required: false }); + this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. this.shouldUseUpdateCommand = this.containerAppExists && - util.isNullOrEmpty(this.targetPort) && - (util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); + this.util.isNullOrEmpty(this.targetPort) && + (this.util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); // Pass the ACR credentials when creating a Container App or updating a Container App via the 'up' command - if (!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword) && + if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword) && (!this.containerAppExists || (this.containerAppExists && !this.shouldUseUpdateCommand))) { this.commandLineArgs.push( `--registry-server ${this.acrName}.azurecr.io`, @@ -425,35 +429,35 @@ export class azurecontainerapps { this.ingressEnabled = true; // Set the ingress value to 'external' if it was not provided - if (util.isNullOrEmpty(this.ingress)) { + if (this.util.isNullOrEmpty(this.ingress)) { this.ingress = 'external'; - toolHelper.writeInfo(`Default ingress value: ${this.ingress}`); + this.toolHelper.writeInfo(`Default ingress value: ${this.ingress}`); } // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' if (this.ingress == 'disabled') { this.ingressEnabled = false; - toolHelper.writeInfo(`Ingress is disabled for this Container App.`); + this.toolHelper.writeInfo(`Ingress is disabled for this Container App.`); } // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = toolHelper.getInput('targetPort', { required: false }); - if (util.isNullOrEmpty(this.targetPort)) { - if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { + this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); + if (this.util.isNullOrEmpty(this.targetPort)) { + if (!this.util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; } else { this.targetPort = '8080'; } - toolHelper.writeInfo(`Default target port: ${this.targetPort}`); + this.toolHelper.writeInfo(`Default target port: ${this.targetPort}`); } // Set the target port to 80 if it was not provided or determined - if (util.isNullOrEmpty(this.targetPort)) { + if (this.util.isNullOrEmpty(this.targetPort)) { this.targetPort = '80'; - toolHelper.writeInfo(`Default target port: ${this.targetPort}`); + this.toolHelper.writeInfo(`Default target port: ${this.targetPort}`); } // Add the ingress value and target port to the optional arguments array @@ -463,10 +467,10 @@ export class azurecontainerapps { } } - const environmentVariables: string = toolHelper.getInput('environmentVariables', { required: false }); + const environmentVariables: string = this.toolHelper.getInput('environmentVariables', { required: false }); // Add user-specified environment variables - if (!util.isNullOrEmpty(environmentVariables)) { + if (!this.util.isNullOrEmpty(environmentVariables)) { // The --replace-env-vars flag is only used for the 'update' command, // otherwise --env-vars is used for 'create' and 'up' if (this.shouldUseUpdateCommand) { @@ -482,7 +486,7 @@ export class azurecontainerapps { */ private static async createOrUpdateContainerApp() { if (!this.containerAppExists) { - if (!util.isNullOrEmpty(this.yamlConfigPath)) { + if (!this.util.isNullOrEmpty(this.yamlConfigPath)) { // Create the Container App from the YAML configuration file await this.appHelper.createContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath); } else { @@ -493,7 +497,7 @@ export class azurecontainerapps { return; } - if (!util.isNullOrEmpty(this.yamlConfigPath)) { + if (!this.util.isNullOrEmpty(this.yamlConfigPath)) { // Update the Container App from the YAML configuration file await this.appHelper.updateContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath); @@ -502,7 +506,7 @@ export class azurecontainerapps { if (this.shouldUseUpdateCommand) { // Update the ACR details on the existing Container App, if provided as an input - if (!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword)) { + if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword)) { await this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.acrName, this.acrUsername, this.acrPassword); } diff --git a/dist/index.js b/dist/index.js index 73122df0..b22c1d48 100644 --- a/dist/index.js +++ b/dist/index.js @@ -50,20 +50,17 @@ var ContainerAppHelper_1 = __nccwpck_require__(2929); var ContainerRegistryHelper_1 = __nccwpck_require__(4769); var TelemetryHelper_1 = __nccwpck_require__(7166); var Utility_1 = __nccwpck_require__(2135); -var GithubActionsToolHelper_1 = __nccwpck_require__(2153); -var util = new Utility_1.Utility(); -var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); +var GitHubActionsToolHelper_1 = __nccwpck_require__(3185); var azurecontainerapps = /** @class */ (function () { function azurecontainerapps() { } azurecontainerapps.runMain = function () { return __awaiter(this, void 0, void 0, function () { - var disableTelemetry, err_1; + var err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: - disableTelemetry = toolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; - this.initializeHelpers(disableTelemetry); + this.initializeHelpers(); _a.label = 1; case 1: _a.trys.push([1, 9, 10, 12]); @@ -79,24 +76,24 @@ var azurecontainerapps = /** @class */ (function () { case 3: // Set up the resources required to deploy a Container App _a.sent(); - if (!!util.isNullOrEmpty(this.acrName)) return [3 /*break*/, 5]; + if (!!this.util.isNullOrEmpty(this.acrName)) return [3 /*break*/, 5]; return [4 /*yield*/, this.authenticateAzureContainerRegistryAsync()]; case 4: _a.sent(); _a.label = 5; case 5: - if (!!util.isNullOrEmpty(this.appSourcePath)) return [3 /*break*/, 7]; + if (!!this.util.isNullOrEmpty(this.appSourcePath)) return [3 /*break*/, 7]; return [4 /*yield*/, this.buildAndPushImageAsync()]; case 6: _a.sent(); _a.label = 7; case 7: // If no application source was provided, set up the scenario for deploying an existing image - if (util.isNullOrEmpty(this.appSourcePath)) { + if (this.util.isNullOrEmpty(this.appSourcePath)) { this.setupExistingImageScenario(); } // If no YAML configuration file was provided, set up the Container App properties - if (util.isNullOrEmpty(this.yamlConfigPath)) { + if (this.util.isNullOrEmpty(this.yamlConfigPath)) { this.setupContainerAppProperties(); } // Create/update the Container App @@ -109,7 +106,7 @@ var azurecontainerapps = /** @class */ (function () { return [3 /*break*/, 12]; case 9: err_1 = _a.sent(); - toolHelper.setFailed(err_1.message); + this.toolHelper.setFailed(err_1.message); this.telemetryHelper.setFailedResult(err_1.message); return [3 /*break*/, 12]; case 10: @@ -128,17 +125,22 @@ var azurecontainerapps = /** @class */ (function () { * Initializes the helpers used by this task. * @param disableTelemetry - Whether or not to disable telemetry for this task. */ - azurecontainerapps.initializeHelpers = function (disableTelemetry) { + azurecontainerapps.initializeHelpers = function () { + // Set up Utility for managing miscellaneous calls + this.util = new Utility_1.Utility(); + // Set up toolHelper for managing calls to the GitHub Actions toolkit + this.toolHelper = new GitHubActionsToolHelper_1.GitHubActionsToolHelper(); + var disableTelemetry = this.toolHelper.getInput('disableTelemetry').toLowerCase() === 'true'; + // Get buildId + this.buildId = this.toolHelper.getBuildId(); + // Get buildNumber + this.buildNumber = this.toolHelper.getBuildNumber(); // Set up TelemetryHelper for managing telemetry calls this.telemetryHelper = new TelemetryHelper_1.TelemetryHelper(disableTelemetry); // Set up ContainerAppHelper for managing calls around the Container App this.appHelper = new ContainerAppHelper_1.ContainerAppHelper(disableTelemetry); // Set up ContainerRegistryHelper for managing calls around ACR this.registryHelper = new ContainerRegistryHelper_1.ContainerRegistryHelper(); - // Set up Utility for managing miscellaneous calls - this.util = new Utility_1.Utility(); - // Set up toolHelper for managing calls to the GitHub Actions toolkit - this.toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); }; /** * Validates the arguments provided to the task for supported scenarios. @@ -146,23 +148,23 @@ var azurecontainerapps = /** @class */ (function () { */ azurecontainerapps.validateSupportedScenarioArguments = function () { // Get the path to the application source to build and run, if provided - this.appSourcePath = toolHelper.getInput('appSourcePath', { required: false }); + this.appSourcePath = this.toolHelper.getInput('appSourcePath', { required: false }); // Get the name of the ACR instance to push images to, if provided - this.acrName = toolHelper.getInput('acrName', { required: false }); + this.acrName = this.toolHelper.getInput('acrName', { required: false }); // Get the previously built image to deploy, if provided - this.imageToDeploy = toolHelper.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', { required: false }); // Get the YAML configuration file, if provided - this.yamlConfigPath = toolHelper.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', { required: false }); // Ensure that acrName is also provided if appSourcePath is provided - if (!util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.acrName)) { + if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName)) { var missingAcrNameMessage = "The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."; - toolHelper.writeError(missingAcrNameMessage); + this.toolHelper.writeError(missingAcrNameMessage); throw Error(missingAcrNameMessage); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided - if (util.isNullOrEmpty(this.appSourcePath) && util.isNullOrEmpty(this.imageToDeploy) && util.isNullOrEmpty(this.yamlConfigPath)) { + if (this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.imageToDeploy) && this.util.isNullOrEmpty(this.yamlConfigPath)) { var requiredArgumentMessage = "One of the following arguments must be provided: 'appSourcePath', 'imageToDeploy', or 'yamlConfigPath'."; - toolHelper.writeError(requiredArgumentMessage); + this.toolHelper.writeError(requiredArgumentMessage); throw Error(requiredArgumentMessage); } }; @@ -176,7 +178,7 @@ var azurecontainerapps = /** @class */ (function () { switch (_a.label) { case 0: // Set the Azure CLI to dynamically install missing extensions - return [4 /*yield*/, util.setAzureCliDynamicInstall()]; + return [4 /*yield*/, this.util.setAzureCliDynamicInstall()]; case 1: // Set the Azure CLI to dynamically install missing extensions _a.sent(); @@ -235,9 +237,9 @@ var azurecontainerapps = /** @class */ (function () { * @returns The name of the Container App to use for the task. */ azurecontainerapps.getContainerAppName = function () { - var containerAppName = toolHelper.getInput('containerAppName', { required: false }); - if (util.isNullOrEmpty(containerAppName)) { - return toolHelper.getDefaultContainerAppName(containerAppName); + var containerAppName = this.toolHelper.getInput('containerAppName', { required: false }); + if (this.util.isNullOrEmpty(containerAppName)) { + return this.toolHelper.getDefaultContainerAppName(containerAppName); } return containerAppName; }; @@ -252,8 +254,8 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - location = toolHelper.getInput('location', { required: false }); - if (!util.isNullOrEmpty(location)) return [3 /*break*/, 2]; + location = this.toolHelper.getInput('location', { required: false }); + if (!this.util.isNullOrEmpty(location)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getDefaultContainerAppLocation()]; case 1: location = _a.sent(); @@ -277,10 +279,10 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - resourceGroup = toolHelper.getInput('resourceGroup', { required: false }); - if (!util.isNullOrEmpty(resourceGroup)) return [3 /*break*/, 3]; + resourceGroup = this.toolHelper.getInput('resourceGroup', { required: false }); + if (!this.util.isNullOrEmpty(resourceGroup)) return [3 /*break*/, 3]; resourceGroup = containerAppName + "-rg"; - toolHelper.writeInfo("Default resource group name: " + resourceGroup); + this.toolHelper.writeInfo("Default resource group name: " + resourceGroup); return [4 /*yield*/, this.appHelper.doesResourceGroupExist(resourceGroup)]; case 1: resourceGroupExists = _a.sent(); @@ -310,21 +312,21 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - containerAppEnvironment = toolHelper.getInput('containerAppEnvironment', { required: false }); - if (!util.isNullOrEmpty(containerAppEnvironment)) return [3 /*break*/, 2]; + containerAppEnvironment = this.toolHelper.getInput('containerAppEnvironment', { required: false }); + if (!this.util.isNullOrEmpty(containerAppEnvironment)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getExistingContainerAppEnvironment(resourceGroup)]; case 1: existingContainerAppEnvironment = _a.sent(); - if (!util.isNullOrEmpty(existingContainerAppEnvironment)) { - toolHelper.writeInfo("Existing Container App environment found in resource group: " + existingContainerAppEnvironment); + if (!this.util.isNullOrEmpty(existingContainerAppEnvironment)) { + this.toolHelper.writeInfo("Existing Container App environment found in resource group: " + existingContainerAppEnvironment); return [2 /*return*/, existingContainerAppEnvironment]; } _a.label = 2; case 2: // Generate the Container App environment name if it was not provided - if (util.isNullOrEmpty(containerAppEnvironment)) { + if (this.util.isNullOrEmpty(containerAppEnvironment)) { containerAppEnvironment = containerAppName + "-env"; - toolHelper.writeInfo("Default Container App environment name: " + containerAppEnvironment); + this.toolHelper.writeInfo("Default Container App environment name: " + containerAppEnvironment); } return [4 /*yield*/, this.appHelper.doesContainerAppEnvironmentExist(containerAppEnvironment, resourceGroup)]; case 3: @@ -347,16 +349,16 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - this.acrUsername = toolHelper.getInput('acrUsername', { required: false }); - this.acrPassword = toolHelper.getInput('acrPassword', { required: false }); - if (!(!util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 2]; - toolHelper.writeInfo("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); + this.acrUsername = this.toolHelper.getInput('acrUsername', { required: false }); + this.acrPassword = this.toolHelper.getInput('acrPassword', { required: false }); + if (!(!this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 2]; + this.toolHelper.writeInfo("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); return [4 /*yield*/, this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword)]; case 1: _a.sent(); return [3 /*break*/, 4]; case 2: - toolHelper.writeInfo("No ACR credentials provided; attempting to log in to ACR instance \"" + this.acrName + "\" with access token"); + this.toolHelper.writeInfo("No ACR credentials provided; attempting to log in to ACR instance \"" + this.acrName + "\" with access token"); return [4 /*yield*/, this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName)]; case 3: _a.sent(); @@ -383,22 +385,22 @@ var azurecontainerapps = /** @class */ (function () { switch (_a.label) { case 0: // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = toolHelper.getInput('imageToBuild', { required: false }); - if (util.isNullOrEmpty(this.imageToBuild)) { + this.imageToBuild = this.toolHelper.getInput('imageToBuild', { required: false }); + if (this.util.isNullOrEmpty(this.imageToBuild)) { this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.buildId + "." + this.buildNumber; - toolHelper.writeInfo("Default image to build: " + this.imageToBuild); + this.toolHelper.writeInfo("Default image to build: " + this.imageToBuild); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' - if (util.isNullOrEmpty(this.imageToDeploy)) { + if (this.util.isNullOrEmpty(this.imageToDeploy)) { this.imageToDeploy = this.imageToBuild; - toolHelper.writeInfo("Default image to deploy: " + this.imageToDeploy); + this.toolHelper.writeInfo("Default image to deploy: " + this.imageToDeploy); } - dockerfilePath = toolHelper.getInput('dockerfilePath', { required: false }); - if (!util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 4]; - toolHelper.writeInfo("No Dockerfile path provided; checking for Dockerfile at root of application source."); + dockerfilePath = this.toolHelper.getInput('dockerfilePath', { required: false }); + if (!this.util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 4]; + this.toolHelper.writeInfo("No Dockerfile path provided; checking for Dockerfile at root of application source."); rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); if (!fs.existsSync(rootDockerfilePath)) return [3 /*break*/, 1]; - toolHelper.writeInfo("Dockerfile found at root of application source."); + this.toolHelper.writeInfo("Dockerfile found at root of application source."); dockerfilePath = rootDockerfilePath; return [3 /*break*/, 3]; case 1: @@ -413,7 +415,7 @@ var azurecontainerapps = /** @class */ (function () { dockerfilePath = path.join(this.appSourcePath, dockerfilePath); _a.label = 5; case 5: - if (!!util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 7]; + if (!!this.util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 7]; // Build the image from the provided/discovered Dockerfile return [4 /*yield*/, this.builderImageFromDockerfile(this.appSourcePath, dockerfilePath, this.imageToBuild)]; case 6: @@ -447,18 +449,18 @@ var azurecontainerapps = /** @class */ (function () { case 1: // Install the pack CLI _b.sent(); - toolHelper.writeInfo("Successfully installed the pack CLI."); + this.toolHelper.writeInfo("Successfully installed the pack CLI."); // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = toolHelper.getInput('runtimeStack', { required: false }); - if (!util.isNullOrEmpty(this.runtimeStack)) return [3 /*break*/, 3]; + this.runtimeStack = this.toolHelper.getInput('runtimeStack', { required: false }); + if (!this.util.isNullOrEmpty(this.runtimeStack)) return [3 /*break*/, 3]; _a = this; return [4 /*yield*/, this.appHelper.determineRuntimeStackAsync(appSourcePath)]; case 2: _a.runtimeStack = _b.sent(); - toolHelper.writeInfo("Runtime stack determined to be: " + this.runtimeStack); + this.toolHelper.writeInfo("Runtime stack determined to be: " + this.runtimeStack); _b.label = 3; case 3: - toolHelper.writeInfo("Building image \"" + imageToBuild + "\" using the Oryx++ Builder"); + this.toolHelper.writeInfo("Building image \"" + imageToBuild + "\" using the Oryx++ Builder"); // Set the Oryx++ Builder as the default builder locally return [4 /*yield*/, this.appHelper.setDefaultBuilder()]; case 4: @@ -487,7 +489,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - toolHelper.writeInfo("Building image \"" + imageToBuild + "\" using the provided Dockerfile"); + this.toolHelper.writeInfo("Building image \"" + imageToBuild + "\" using the provided Dockerfile"); return [4 /*yield*/, this.appHelper.createRunnableAppImageFromDockerfile(imageToBuild, appSourcePath, dockerfilePath)]; case 1: _a.sent(); @@ -505,15 +507,15 @@ var azurecontainerapps = /** @class */ (function () { azurecontainerapps.setupContainerAppProperties = function () { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = toolHelper.getInput('ingress', { required: false }); - this.targetPort = toolHelper.getInput('targetPort', { required: false }); + this.ingress = this.toolHelper.getInput('ingress', { required: false }); + this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. this.shouldUseUpdateCommand = this.containerAppExists && - util.isNullOrEmpty(this.targetPort) && - (util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); + this.util.isNullOrEmpty(this.targetPort) && + (this.util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); // Pass the ACR credentials when creating a Container App or updating a Container App via the 'up' command - if (!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword) && + if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword) && (!this.containerAppExists || (this.containerAppExists && !this.shouldUseUpdateCommand))) { this.commandLineArgs.push("--registry-server " + this.acrName + ".azurecr.io", "--registry-username " + this.acrUsername, "--registry-password " + this.acrPassword); } @@ -521,32 +523,32 @@ var azurecontainerapps = /** @class */ (function () { if (!this.containerAppExists) { this.ingressEnabled = true; // Set the ingress value to 'external' if it was not provided - if (util.isNullOrEmpty(this.ingress)) { + if (this.util.isNullOrEmpty(this.ingress)) { this.ingress = 'external'; - toolHelper.writeInfo("Default ingress value: " + this.ingress); + this.toolHelper.writeInfo("Default ingress value: " + this.ingress); } // Set the value of ingressEnabled to 'false' if ingress was provided as 'disabled' if (this.ingress == 'disabled') { this.ingressEnabled = false; - toolHelper.writeInfo("Ingress is disabled for this Container App."); + this.toolHelper.writeInfo("Ingress is disabled for this Container App."); } // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = toolHelper.getInput('targetPort', { required: false }); - if (util.isNullOrEmpty(this.targetPort)) { - if (!util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { + this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); + if (this.util.isNullOrEmpty(this.targetPort)) { + if (!this.util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; } else { this.targetPort = '8080'; } - toolHelper.writeInfo("Default target port: " + this.targetPort); + this.toolHelper.writeInfo("Default target port: " + this.targetPort); } // Set the target port to 80 if it was not provided or determined - if (util.isNullOrEmpty(this.targetPort)) { + if (this.util.isNullOrEmpty(this.targetPort)) { this.targetPort = '80'; - toolHelper.writeInfo("Default target port: " + this.targetPort); + this.toolHelper.writeInfo("Default target port: " + this.targetPort); } // Add the ingress value and target port to the optional arguments array // Note: this step should be skipped if we're updating an existing Container App (ingress is enabled via a separate command) @@ -554,9 +556,9 @@ var azurecontainerapps = /** @class */ (function () { this.commandLineArgs.push("--target-port " + this.targetPort); } } - var environmentVariables = toolHelper.getInput('environmentVariables', { required: false }); + var environmentVariables = this.toolHelper.getInput('environmentVariables', { required: false }); // Add user-specified environment variables - if (!util.isNullOrEmpty(environmentVariables)) { + if (!this.util.isNullOrEmpty(environmentVariables)) { // The --replace-env-vars flag is only used for the 'update' command, // otherwise --env-vars is used for 'create' and 'up' if (this.shouldUseUpdateCommand) { @@ -576,7 +578,7 @@ var azurecontainerapps = /** @class */ (function () { switch (_a.label) { case 0: if (!!this.containerAppExists) return [3 /*break*/, 5]; - if (!!util.isNullOrEmpty(this.yamlConfigPath)) return [3 /*break*/, 2]; + if (!!this.util.isNullOrEmpty(this.yamlConfigPath)) return [3 /*break*/, 2]; // Create the Container App from the YAML configuration file return [4 /*yield*/, this.appHelper.createContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath)]; case 1: @@ -592,7 +594,7 @@ var azurecontainerapps = /** @class */ (function () { _a.label = 4; case 4: return [2 /*return*/]; case 5: - if (!!util.isNullOrEmpty(this.yamlConfigPath)) return [3 /*break*/, 7]; + if (!!this.util.isNullOrEmpty(this.yamlConfigPath)) return [3 /*break*/, 7]; // Update the Container App from the YAML configuration file return [4 /*yield*/, this.appHelper.updateContainerAppFromYaml(this.containerAppName, this.resourceGroup, this.yamlConfigPath)]; case 6: @@ -601,7 +603,7 @@ var azurecontainerapps = /** @class */ (function () { return [2 /*return*/]; case 7: if (!this.shouldUseUpdateCommand) return [3 /*break*/, 11]; - if (!(!util.isNullOrEmpty(this.acrName) && !util.isNullOrEmpty(this.acrUsername) && !util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 9]; + if (!(!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 9]; return [4 /*yield*/, this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.acrName, this.acrUsername, this.acrPassword)]; case 8: _a.sent(); @@ -631,9 +633,6 @@ var azurecontainerapps = /** @class */ (function () { }); }); }; - // Build-specific properties - azurecontainerapps.buildId = toolHelper.getBuildId(); - azurecontainerapps.buildNumber = toolHelper.getBuildNumber(); return azurecontainerapps; }()); exports.azurecontainerapps = azurecontainerapps; @@ -4640,13 +4639,13 @@ exports.ContainerAppHelper = void 0; var path = __nccwpck_require__(1017); var os = __nccwpck_require__(2037); var Utility_1 = __nccwpck_require__(2135); -var GithubActionsToolHelper_1 = __nccwpck_require__(2153); +var GitHubActionsToolHelper_1 = __nccwpck_require__(3185); var fs = __nccwpck_require__(7147); var ORYX_CLI_IMAGE = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; var ORYX_BUILDER_IMAGE = 'mcr.microsoft.com/oryx/builder:20230208.1'; var IS_WINDOWS_AGENT = os.platform() == 'win32'; var PACK_CMD = IS_WINDOWS_AGENT ? path.join(os.tmpdir(), 'pack') : 'pack'; -var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); +var toolHelper = new GitHubActionsToolHelper_1.GitHubActionsToolHelper(); var util = new Utility_1.Utility(); var ContainerAppHelper = /** @class */ (function () { function ContainerAppHelper(disableTelemetry) { @@ -4675,7 +4674,7 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError("az", command_1.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command_1 + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4705,7 +4704,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4739,7 +4738,7 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_2 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError("az", command_2.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command_2 + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4781,7 +4780,7 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(targetPort)) { command_3 += " --target-port " + targetPort; } - return [4 /*yield*/, util.executeAndThrowIfError("az", command_3.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command_3 + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4811,7 +4810,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4841,7 +4840,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; @@ -4871,7 +4870,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; @@ -4900,7 +4899,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "group show -n " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; @@ -4919,7 +4918,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getDefaultContainerAppLocation = function () { return __awaiter(this, void 0, void 0, function () { - var args, executionResult, err_9; + var executionResult, err_9; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4927,8 +4926,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - args = ["provider", "show", "-n", "Microsoft.App", "--query", "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"]; - return [4 /*yield*/, util.executeAndThrowIfError("az", args)]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\"")]; case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned @@ -4958,7 +4956,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "group create -n " + name + " -l " + location; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4978,7 +4976,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getExistingContainerAppEnvironment = function (resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var args, executionResult, err_11; + var executionResult, err_11; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4986,8 +4984,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - args = ["containerapp", "env", "list", "-g", "" + resourceGroup, "--query", "[0].name"]; - return [4 /*yield*/, util.executeAndThrowIfError("az", args)]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"containerapp env list -g " + resourceGroup + " --query [0].name\"")]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout : null]; @@ -5008,7 +5005,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.createContainerAppEnvironment = function (name, resourceGroup, location) { return __awaiter(this, void 0, void 0, function () { - var util, args, err_12; + var util, command, err_12; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5017,11 +5014,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - args = ["containerapp", "env", "create", "-n", "" + name, "-g", "" + resourceGroup]; + command = "containerapp env create -n " + name + " -g " + resourceGroup; if (!util.isNullOrEmpty(location)) { - args.push("-l", "" + location); + command += " -l " + location; } - return [4 /*yield*/, util.executeAndThrowIfError("az", args)]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5050,7 +5047,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp ingress disable -n " + name + " -g " + resourceGroup; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5082,7 +5079,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; - return [4 /*yield*/, util.executeAndThrowIfError("az", command.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5103,7 +5100,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.createRunnableAppImage = function (imageToDeploy, appSourcePath, runtimeStack) { return __awaiter(this, void 0, void 0, function () { - var telemetryArg, err_15; + var telemetryArg, command, err_15; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5115,7 +5112,8 @@ var ContainerAppHelper = /** @class */ (function () { if (this.disableTelemetry) { telemetryArg = "ORYX_DISABLE_TELEMETRY=true"; } - return [4 /*yield*/, util.executeAndThrowIfError("" + PACK_CMD, ['build', "" + imageToDeploy, '--path', "" + appSourcePath, '--builder', "" + ORYX_BUILDER_IMAGE, '--run-image', "mcr.microsoft.com/oryx/" + runtimeStack, '--env', "" + telemetryArg])]; + command = "build " + imageToDeploy + " --path " + appSourcePath + " --builder " + ORYX_BUILDER_IMAGE + " --run-image mcr.microsoft.com/oryx/" + runtimeStack + " --env " + telemetryArg; + return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5137,7 +5135,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.createRunnableAppImageFromDockerfile = function (imageToDeploy, appSourcePath, dockerfilePath) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, err_16; + var dockerTool, command, err_16; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5148,7 +5146,8 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ['build', '--file', "" + dockerfilePath, "" + appSourcePath, '--tag', "" + imageToDeploy])]; + command = "build --file " + dockerfilePath + " " + appSourcePath + " --tag " + imageToDeploy; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"" + command + "\"")]; case 3: _a.sent(); toolHelper.writeDebug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); @@ -5169,7 +5168,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.determineRuntimeStackAsync = function (appSourcePath) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, oryxRuntimeTxtPath_1, runtimeStack, err_17; + var dockerTool, oryxDockerfileCommand, command, oryxRuntimeTxtPath_1, runtimeStack, err_17; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5180,12 +5179,12 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', appSourcePath + ":/app", "" + ORYX_CLI_IMAGE, '/bin/bash', '-c', "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"]) + oryxDockerfileCommand = "oryx dockerfile " + appSourcePath + " | head -n 1 | sed 's/ARG RUNTIME=//' >> " + appSourcePath + "/oryx-runtime.txt"; + command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c " + oryxDockerfileCommand + "}"; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"" + command + "\"") // Read the temp file to get the runtime stack into a variable ]; case 3: - // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file _a.sent(); oryxRuntimeTxtPath_1 = path.join(appSourcePath, 'oryx-runtime.txt'); runtimeStack = fs.promises.readFile(oryxRuntimeTxtPath_1, 'utf8').then(function (data) { @@ -5217,7 +5216,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.setDefaultBuilder = function () { return __awaiter(this, void 0, void 0, function () { - var err_18; + var command, err_18; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5225,7 +5224,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.executeAndThrowIfError("" + PACK_CMD, ['config', 'default-builder', "" + ORYX_BUILDER_IMAGE])]; + command = "config default-builder " + ORYX_BUILDER_IMAGE; + return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5244,7 +5244,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.installPackCliAsync = function () { return __awaiter(this, void 0, void 0, function () { - var command, commandLine, args, packZipDownloadUri, packZipDownloadFilePath, tgzSuffix, err_19; + var command, commandLine, packZipDownloadUri, packZipDownloadFilePath, tgzSuffix, err_19; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5254,22 +5254,19 @@ var ContainerAppHelper = /** @class */ (function () { _a.trys.push([1, 3, , 4]); command = ''; commandLine = ''; - args = []; if (IS_WINDOWS_AGENT) { packZipDownloadUri = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; packZipDownloadFilePath = path.join(PACK_CMD, 'pack-windows.zip'); - args = ["New-Item", "-ItemType", "Directory", "-Path", "" + PACK_CMD, "-Force | Out-Null;", "Invoke-WebRequest", "-Uri", "" + packZipDownloadUri, "-OutFile", packZipDownloadFilePath + ";", "Expand-Archive", "-LiteralPath", "" + packZipDownloadFilePath, "-DestinationPath", PACK_CMD + ";", "Remove-Item", "-Path", "" + packZipDownloadFilePath, - "Expand-Archive", "-LiteralPath", "" + packZipDownloadFilePath, "-DestinationPath", PACK_CMD + ";", "Remove-Item", "-Path", "" + packZipDownloadFilePath]; + command = "New-Item -ItemType Directory -Path " + PACK_CMD + " -Force | Out-Null; Invoke-WebRequest -Uri " + packZipDownloadUri + " -OutFile " + packZipDownloadFilePath + "; Expand-Archive -LiteralPath " + packZipDownloadFilePath + " -DestinationPath " + PACK_CMD + "; Remove-Item -Path " + packZipDownloadFilePath; commandLine = 'pwsh'; } else { tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = "(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + + command = "-c (curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; - args = ['-c', command]; commandLine = 'bash'; } - return [4 /*yield*/, util.executeAndThrowIfError(commandLine, args)]; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5334,8 +5331,8 @@ exports.__esModule = true; exports.ContainerRegistryHelper = void 0; var os = __nccwpck_require__(2037); var Utility_1 = __nccwpck_require__(2135); -var GithubActionsToolHelper_1 = __nccwpck_require__(2153); -var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); +var GitHubActionsToolHelper_1 = __nccwpck_require__(3185); +var toolHelper = new GitHubActionsToolHelper_1.GitHubActionsToolHelper(); var util = new Utility_1.Utility(); var ContainerRegistryHelper = /** @class */ (function () { function ContainerRegistryHelper() { @@ -5359,7 +5356,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ["login", "--username", "" + acrUsername, "--password", "" + acrPassword, acrName + ".azurecr.io"], Buffer.from(acrPassword))]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io\"", [], Buffer.from(acrPassword))]; case 3: _a.sent(); return [3 /*break*/, 5]; @@ -5379,7 +5376,7 @@ var ContainerRegistryHelper = /** @class */ (function () { */ ContainerRegistryHelper.prototype.loginAcrWithAccessTokenAsync = function (acrName) { return __awaiter(this, void 0, void 0, function () { - var command, commandLine, err_2; + var commandLine, err_2; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5387,9 +5384,8 @@ var ContainerRegistryHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"; commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - return [4 /*yield*/, util.executeAndThrowIfError(commandLine, ['-c', command])]; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine + "\"-c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5419,7 +5415,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool, ["push", "" + imageToPush])]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"tag " + imageToPush + " " + imageToPush + "\"")]; case 3: _a.sent(); return [3 /*break*/, 5]; @@ -5439,7 +5435,7 @@ exports.ContainerRegistryHelper = ContainerRegistryHelper; /***/ }), -/***/ 2153: +/***/ 3185: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -5618,7 +5614,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { exports.__esModule = true; exports.TelemetryHelper = void 0; var Utility_1 = __nccwpck_require__(2135); -var GithubActionsToolHelper_1 = __nccwpck_require__(2153); +var GitHubActionsToolHelper_1 = __nccwpck_require__(3185); var ORYX_CLI_IMAGE = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; var SUCCESSFUL_RESULT = "succeeded"; var FAILED_RESULT = "failed"; @@ -5626,7 +5622,7 @@ var BUILDER_SCENARIO = "used-builder"; var DOCKERFILE_SCENARIO = "used-dockerfile"; var IMAGE_SCENARIO = "used-image"; var util = new Utility_1.Utility(); -var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); +var toolHelper = new GitHubActionsToolHelper_1.GitHubActionsToolHelper(); var TelemetryHelper = /** @class */ (function () { function TelemetryHelper(disableTelemetry) { this.disableTelemetry = disableTelemetry; @@ -5668,7 +5664,7 @@ var TelemetryHelper = /** @class */ (function () { */ TelemetryHelper.prototype.sendLogs = function () { return __awaiter(this, void 0, void 0, function () { - var taskLengthMilliseconds, resultArg, scenarioArg, errorMessageArg, eventName, args, dockerTool, err_1; + var taskLengthMilliseconds, resultArg, scenarioArg, errorMessageArg, eventName, dockerTool, err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5691,11 +5687,10 @@ var TelemetryHelper = /** @class */ (function () { errorMessageArg = "--property errorMessage=" + this.errorMessage; } eventName = toolHelper.getEventName(); - args = ["run", "--rm", "" + ORYX_CLI_IMAGE, "/bin/bash", "-c", "oryx telemetry --event-name " + eventName + " " + ("--processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, toolHelper.exec(dockerTool, args)]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; case 3: _a.sent(); return [3 /*break*/, 5]; @@ -5759,8 +5754,8 @@ var __generator = (this && this.__generator) || function (thisArg, body) { exports.__esModule = true; exports.Utility = void 0; // Note: This file is used to define utility functions that can be used across the project. -var GithubActionsToolHelper_1 = __nccwpck_require__(2153); -var toolHelper = new GithubActionsToolHelper_1.GitHubActionsToolHelper(); +var GitHubActionsToolHelper_1 = __nccwpck_require__(3185); +var toolHelper = new GitHubActionsToolHelper_1.GitHubActionsToolHelper(); var Utility = /** @class */ (function () { function Utility() { } @@ -5795,7 +5790,7 @@ var Utility = /** @class */ (function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, this.executeAndThrowIfError('az', ["config", "set", "extension.use_dynamic_install=yes_without_prompt"])]; + case 0: return [4 /*yield*/, this.executeAndThrowIfError("az \"config set extension.use_dynamic_install=yes_without_prompt\"")]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index f85a0cef..826db6cd 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import * as os from 'os'; import { Utility } from './Utility'; -import { GitHubActionsToolHelper } from './GithubActionsToolHelper' +import { GitHubActionsToolHelper } from './GitHubActionsToolHelper' import fs = require('fs'); const ORYX_CLI_IMAGE: string = 'mcr.microsoft.com/oryx/cli:builder-debian-buster-20230208.1'; @@ -38,7 +38,7 @@ export class ContainerAppHelper { optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -58,7 +58,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -83,7 +83,7 @@ export class ContainerAppHelper { optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -120,7 +120,7 @@ export class ContainerAppHelper { if (!util.isNullOrEmpty(targetPort)) { command += ` --target-port ${targetPort}`; } - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -140,7 +140,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -157,7 +157,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { let command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); + let executionResult = await util.executeAndThrowIfError(`az "${command}"`); return executionResult.exitCode === 0; } catch (err) { toolHelper.writeWarning(err.message); @@ -175,7 +175,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { let command = `containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); + let executionResult = await util.executeAndThrowIfError(`az "${command}"`); return executionResult.exitCode === 0; } catch (err) { toolHelper.writeWarning(err.message); @@ -192,7 +192,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { let command = `group show -n ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(`az`, command.split(' ')); + let executionResult = await util.executeAndThrowIfError(`az "${command}"`); return executionResult.exitCode === 0; } catch (err) { toolHelper.writeWarning(err.message); @@ -207,8 +207,7 @@ export class ContainerAppHelper { public async getDefaultContainerAppLocation(): Promise { toolHelper.writeDebug(`Attempting to get the default location for the Container App service for the subscription.`); try { - let args = [`provider`, `show`, `-n`, `Microsoft.App`, `--query`, `resourceTypes[?resourceType=='containerApps'].locations[] | [0]`]; - let executionResult = await util.executeAndThrowIfError(`az`, args); + let executionResult = await util.executeAndThrowIfError(`az "provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"`); // If successful, strip out double quotes, spaces and parentheses from the first location returned return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { @@ -226,7 +225,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to create resource group "${name}" in location "${location}"`); try { let command = `group create -n ${name} -l ${location}`; - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -241,8 +240,7 @@ export class ContainerAppHelper { public async getExistingContainerAppEnvironment(resourceGroup: string) { toolHelper.writeDebug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { - let args = [`containerapp`, `env`, `list`, `-g`, `${resourceGroup}`, `--query`, `[0].name`]; - let executionResult = await util.executeAndThrowIfError(`az`, args); + let executionResult = await util.executeAndThrowIfError(`az "containerapp env list -g ${resourceGroup} --query [0].name"`); return executionResult.exitCode === 0 ? executionResult.stdout : null; } catch (err) { toolHelper.writeWarning(err.message); @@ -260,11 +258,11 @@ export class ContainerAppHelper { const util = new Utility(); toolHelper.writeDebug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); try { - let args = [`containerapp`, `env`, `create`, `-n`, `${name}`, `-g`, `${resourceGroup}`]; + let command = `containerapp env create -n ${name} -g ${resourceGroup}`; if (!util.isNullOrEmpty(location)) { - args.push(`-l`, `${location}`); + command += ` -l ${location}`; } - await util.executeAndThrowIfError(`az`, args); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -280,7 +278,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); try { let command = `containerapp ingress disable -n ${name} -g ${resourceGroup}`; - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -299,7 +297,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { let command = `containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(`az "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -322,7 +320,8 @@ export class ContainerAppHelper { if (this.disableTelemetry) { telemetryArg = `ORYX_DISABLE_TELEMETRY=true`; } - await util.executeAndThrowIfError(`${PACK_CMD}`, ['build', `${imageToDeploy}`, '--path', `${appSourcePath}`, '--builder', `${ORYX_BUILDER_IMAGE}`, '--run-image', `mcr.microsoft.com/oryx/${runtimeStack}`, '--env', `${telemetryArg}`]); + let command = `build ${imageToDeploy} --path ${appSourcePath} --builder ${ORYX_BUILDER_IMAGE} --run-image mcr.microsoft.com/oryx/${runtimeStack} --env ${telemetryArg}`; + await util.executeAndThrowIfError(`${PACK_CMD} "${command}"`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -343,7 +342,8 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); try { let dockerTool = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(dockerTool, ['build', '--file', `${dockerfilePath}`, `${appSourcePath}`, '--tag', `${imageToDeploy}`]); + let command = `build --file ${dockerfilePath} ${appSourcePath} --tag ${imageToDeploy}`; + await util.executeAndThrowIfError(`${dockerTool} "${command}"`); toolHelper.writeDebug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); } catch (err) { toolHelper.writeError(err.message); @@ -361,7 +361,9 @@ export class ContainerAppHelper { try { let dockerTool: string = await toolHelper.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - await util.executeAndThrowIfError(dockerTool, ['run', '--rm', '-v', `${appSourcePath}:/app`, `${ORYX_CLI_IMAGE}`, '/bin/bash', '-c', `oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt`]) + let oryxDockerfileCommand = `oryx dockerfile ${appSourcePath} | head -n 1 | sed 's/ARG RUNTIME=//' >> ${appSourcePath}/oryx-runtime.txt` + let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c ${oryxDockerfileCommand}}` + await util.executeAndThrowIfError(`${dockerTool} "${command}"`) // Read the temp file to get the runtime stack into a variable let oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); @@ -395,7 +397,8 @@ export class ContainerAppHelper { public async setDefaultBuilder() { toolHelper.writeInfo('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { - await util.executeAndThrowIfError(`${PACK_CMD}`, ['config', 'default-builder', `${ORYX_BUILDER_IMAGE}`]); + let command = `config default-builder ${ORYX_BUILDER_IMAGE}` + await util.executeAndThrowIfError(`${PACK_CMD} "${command}"`); } catch (err) { toolHelper.writeError(err.message); @@ -412,21 +415,18 @@ export class ContainerAppHelper { try { let command: string = ''; let commandLine = ''; - let args: string[] = []; if (IS_WINDOWS_AGENT) { let packZipDownloadUri: string = 'https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-windows.zip'; let packZipDownloadFilePath: string = path.join(PACK_CMD, 'pack-windows.zip'); - args = [`New-Item`, `-ItemType`, `Directory`, `-Path`, `${PACK_CMD}`, `-Force | Out-Null;`, `Invoke-WebRequest`, `-Uri`, `${packZipDownloadUri}`, `-OutFile`, `${packZipDownloadFilePath};`, `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`, - `Expand-Archive`, `-LiteralPath`, `${packZipDownloadFilePath}`, `-DestinationPath`, `${PACK_CMD};`, `Remove-Item`, `-Path`, `${packZipDownloadFilePath}`]; + command = `New-Item -ItemType Directory -Path ${PACK_CMD} -Force | Out-Null; Invoke-WebRequest -Uri ${packZipDownloadUri} -OutFile ${packZipDownloadFilePath}; Expand-Archive -LiteralPath ${packZipDownloadFilePath} -DestinationPath ${PACK_CMD}; Remove-Item -Path ${packZipDownloadFilePath}`; commandLine = 'pwsh'; } else { let tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + + command = `-c (curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; - args = ['-c', command]; commandLine = 'bash'; } - await util.executeAndThrowIfError(commandLine, args); + await util.executeAndThrowIfError(`${commandLine} "${command}"`); } catch (err) { toolHelper.writeError(`Unable to install the pack CLI. Error: ${err.message}`); throw err; diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index d5648d65..783297b2 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -1,6 +1,6 @@ import * as os from 'os'; import { Utility } from './Utility'; -import { GitHubActionsToolHelper } from './GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './GitHubActionsToolHelper'; const toolHelper = new GitHubActionsToolHelper(); const util = new Utility(); @@ -16,7 +16,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); try { let dockerTool = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(dockerTool, [`login`, `--username`, `${acrUsername}`, `--password`, `${acrPassword}`, `${acrName}.azurecr.io`], Buffer.from(acrPassword)); + await util.executeAndThrowIfError(`${dockerTool} "login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io"`, [] , Buffer.from(acrPassword)); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); throw err; @@ -31,9 +31,8 @@ export class ContainerRegistryHelper { public async loginAcrWithAccessTokenAsync(acrName: string) { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { - let command: string = `CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`; let commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - await util.executeAndThrowIfError(commandLine, ['-c', command]); + await util.executeAndThrowIfError(`${commandLine}"-c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"`); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; @@ -48,7 +47,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to ACR`); try { let dockerTool: string = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(dockerTool, [`push`, `${imageToPush}`]); + await util.executeAndThrowIfError(`${dockerTool} "tag ${imageToPush} ${imageToPush}"`); } catch (err) { toolHelper.writeError(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); throw err; diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 74151342..55c2e4bf 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -1,5 +1,5 @@ import { Utility } from './Utility'; -import { GitHubActionsToolHelper } from './GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './GitHubActionsToolHelper'; const ORYX_CLI_IMAGE: string = "mcr.microsoft.com/oryx/cli:debian-buster-20230207.2"; @@ -86,10 +86,9 @@ export class TelemetryHelper { } let eventName = toolHelper.getEventName(); - let args: string[] = [`run`, `--rm`, `${ORYX_CLI_IMAGE}`, `/bin/bash`, `-c`, `oryx telemetry --event-name ${eventName} ` + `--processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`]; let dockerTool: string = await toolHelper.which("docker", true); - await toolHelper.exec(dockerTool, args); + await util.executeAndThrowIfError(`${dockerTool} "run --rm ${ORYX_CLI_IMAGE} /bin/bash -c oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}"`); } catch (err) { toolHelper.writeWarning(`Skipping telemetry logging due to the following exception: ${err.message}`); } diff --git a/src/Utility.ts b/src/Utility.ts index 9cd0df56..f1b1bdf5 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -1,5 +1,5 @@ // Note: This file is used to define utility functions that can be used across the project. -import { GitHubActionsToolHelper } from './GithubActionsToolHelper'; +import { GitHubActionsToolHelper } from './GitHubActionsToolHelper'; const toolHelper = new GitHubActionsToolHelper(); @@ -10,7 +10,7 @@ export class Utility { * @param continueOnError - whether or not to continue execution if the command fails */ - public async executeAndThrowIfError(commandLine: string, args: string[], inputOptions?:Buffer): Promise<{ exitCode: number, stdout: string, stderr: string }> { + public async executeAndThrowIfError(commandLine: string, args?: string[], inputOptions?:Buffer): Promise<{ exitCode: number, stdout: string, stderr: string }> { try { return await toolHelper.exec(commandLine, args, inputOptions); } catch (error) { @@ -24,7 +24,7 @@ export class Utility { * Azure Container Apps module being dynamically installed while it's still in preview. */ public async setAzureCliDynamicInstall() { - await this.executeAndThrowIfError('az', [`config`, `set`, `extension.use_dynamic_install=yes_without_prompt`]); + await this.executeAndThrowIfError(`az "config set extension.use_dynamic_install=yes_without_prompt"`); } /** From ef3a8d351b4a330a1ee50d7f53ba46eb81e03808 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 29 Sep 2023 00:07:06 -0700 Subject: [PATCH 24/42] Change command signature --- dist/index.js | 79 +++++++++++++++++----------------- src/ContainerAppHelper.ts | 67 ++++++++++++++-------------- src/ContainerRegistryHelper.ts | 6 +-- src/TelemetryHelper.ts | 2 +- src/Utility.ts | 2 +- 5 files changed, 79 insertions(+), 77 deletions(-) diff --git a/dist/index.js b/dist/index.js index b22c1d48..a3dd156e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4670,11 +4670,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_1 = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; + command_1 = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command_1 + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(command_1)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4703,8 +4703,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4734,11 +4734,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_2 = "containerapp update -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; + command_2 = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; optionalCmdArgs.forEach(function (val) { command_2 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command_2 + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(command_2)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4770,7 +4770,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_3 = "containerapp up -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; + command_3 = "az containerapp up -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; optionalCmdArgs.forEach(function (val) { command_3 += " " + val; }); @@ -4780,7 +4780,7 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(targetPort)) { command_3 += " --target-port " + targetPort; } - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command_3 + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(command_3)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4809,8 +4809,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4839,8 +4839,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; @@ -4869,8 +4869,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; @@ -4898,8 +4898,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "group show -n " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az group show -n " + resourceGroup + " -o none"; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; @@ -4918,7 +4918,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getDefaultContainerAppLocation = function () { return __awaiter(this, void 0, void 0, function () { - var executionResult, err_9; + var command, executionResult, err_9; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4926,7 +4926,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.executeAndThrowIfError("az \"provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\"")]; + command = "az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned @@ -4955,8 +4956,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "group create -n " + name + " -l " + location; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az group create -n " + name + " -l " + location; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4984,7 +4985,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.executeAndThrowIfError("az \"containerapp env list -g " + resourceGroup + " --query [0].name\"")]; + return [4 /*yield*/, util.executeAndThrowIfError("az containerapp env list -g " + resourceGroup + " --query [0].name")]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout : null]; @@ -5014,11 +5015,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp env create -n " + name + " -g " + resourceGroup; + command = "az containerapp env create -n " + name + " -g " + resourceGroup; if (!util.isNullOrEmpty(location)) { command += " -l " + location; } - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5046,8 +5047,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp ingress disable -n " + name + " -g " + resourceGroup; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az containerapp ingress disable -n " + name + " -g " + resourceGroup; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5078,8 +5079,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; - return [4 /*yield*/, util.executeAndThrowIfError("az \"" + command + "\"")]; + command = "az containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5113,7 +5114,7 @@ var ContainerAppHelper = /** @class */ (function () { telemetryArg = "ORYX_DISABLE_TELEMETRY=true"; } command = "build " + imageToDeploy + " --path " + appSourcePath + " --builder " + ORYX_BUILDER_IMAGE + " --run-image mcr.microsoft.com/oryx/" + runtimeStack + " --env " + telemetryArg; - return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " \"" + command + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " " + command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5147,7 +5148,7 @@ var ContainerAppHelper = /** @class */ (function () { case 2: dockerTool = _a.sent(); command = "build --file " + dockerfilePath + " " + appSourcePath + " --tag " + imageToDeploy; - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"" + command + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " " + command)]; case 3: _a.sent(); toolHelper.writeDebug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); @@ -5181,7 +5182,7 @@ var ContainerAppHelper = /** @class */ (function () { dockerTool = _a.sent(); oryxDockerfileCommand = "oryx dockerfile " + appSourcePath + " | head -n 1 | sed 's/ARG RUNTIME=//' >> " + appSourcePath + "/oryx-runtime.txt"; command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c " + oryxDockerfileCommand + "}"; - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"" + command + "\"") + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " " + command) // Read the temp file to get the runtime stack into a variable ]; case 3: @@ -5224,8 +5225,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "config default-builder " + ORYX_BUILDER_IMAGE; - return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " \"" + command + "\"")]; + command = "az config default-builder " + ORYX_BUILDER_IMAGE; + return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " " + command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5262,11 +5263,11 @@ var ContainerAppHelper = /** @class */ (function () { } else { tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = "-c (curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + + command = "(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } - return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " \"" + command + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5356,7 +5357,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io\"", [], Buffer.from(acrPassword))]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io", [], Buffer.from(acrPassword))]; case 3: _a.sent(); return [3 /*break*/, 5]; @@ -5385,7 +5386,7 @@ var ContainerRegistryHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - return [4 /*yield*/, util.executeAndThrowIfError(commandLine + "\"-c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c \"CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5415,7 +5416,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"tag " + imageToPush + " " + imageToPush + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " tag " + imageToPush + " " + imageToPush)]; case 3: _a.sent(); return [3 /*break*/, 5]; @@ -5690,7 +5691,7 @@ var TelemetryHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " \"run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; case 3: _a.sent(); return [3 /*break*/, 5]; @@ -5790,7 +5791,7 @@ var Utility = /** @class */ (function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, this.executeAndThrowIfError("az \"config set extension.use_dynamic_install=yes_without_prompt\"")]; + case 0: return [4 /*yield*/, this.executeAndThrowIfError("az config set extension.use_dynamic_install=yes_without_prompt")]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 826db6cd..537652e7 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -34,11 +34,11 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(`az "${command}"`); + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -57,8 +57,8 @@ export class ContainerAppHelper { yamlConfigPath: string) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await util.executeAndThrowIfError(`az "${command}"`); + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -79,11 +79,11 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(`az "${command}"`); + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -108,7 +108,7 @@ export class ContainerAppHelper { targetPort?: string) { toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + let command = `az containerapp up -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); @@ -120,7 +120,7 @@ export class ContainerAppHelper { if (!util.isNullOrEmpty(targetPort)) { command += ` --target-port ${targetPort}`; } - await util.executeAndThrowIfError(`az "${command}"`); + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -139,8 +139,8 @@ export class ContainerAppHelper { yamlConfigPath: string) { toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - let command = `containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await util.executeAndThrowIfError(`az "${command}"`); + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -156,8 +156,8 @@ export class ContainerAppHelper { public async doesContainerAppExist(containerAppName: string, resourceGroup: string): Promise { toolHelper.writeDebug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { - let command = `containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(`az "${command}"`); + let command = `az containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; + let executionResult = await util.executeAndThrowIfError(command); return executionResult.exitCode === 0; } catch (err) { toolHelper.writeWarning(err.message); @@ -174,8 +174,8 @@ export class ContainerAppHelper { public async doesContainerAppEnvironmentExist(containerAppEnvironment: string, resourceGroup: string): Promise { toolHelper.writeDebug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { - let command = `containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(`az "${command}"`); + let command = `az containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; + let executionResult = await util.executeAndThrowIfError(command); return executionResult.exitCode === 0; } catch (err) { toolHelper.writeWarning(err.message); @@ -191,8 +191,8 @@ export class ContainerAppHelper { public async doesResourceGroupExist(resourceGroup: string): Promise { toolHelper.writeDebug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { - let command = `group show -n ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(`az "${command}"`); + let command = `az group show -n ${resourceGroup} -o none`; + let executionResult = await util.executeAndThrowIfError(command); return executionResult.exitCode === 0; } catch (err) { toolHelper.writeWarning(err.message); @@ -207,7 +207,8 @@ export class ContainerAppHelper { public async getDefaultContainerAppLocation(): Promise { toolHelper.writeDebug(`Attempting to get the default location for the Container App service for the subscription.`); try { - let executionResult = await util.executeAndThrowIfError(`az "provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"`); + let command = `az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\"` + let executionResult = await util.executeAndThrowIfError(command); // If successful, strip out double quotes, spaces and parentheses from the first location returned return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { @@ -224,8 +225,8 @@ export class ContainerAppHelper { public async createResourceGroup(name: string, location: string) { toolHelper.writeDebug(`Attempting to create resource group "${name}" in location "${location}"`); try { - let command = `group create -n ${name} -l ${location}`; - await util.executeAndThrowIfError(`az "${command}"`); + let command = `az group create -n ${name} -l ${location}`; + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -240,7 +241,7 @@ export class ContainerAppHelper { public async getExistingContainerAppEnvironment(resourceGroup: string) { toolHelper.writeDebug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { - let executionResult = await util.executeAndThrowIfError(`az "containerapp env list -g ${resourceGroup} --query [0].name"`); + let executionResult = await util.executeAndThrowIfError(`az containerapp env list -g ${resourceGroup} --query [0].name`); return executionResult.exitCode === 0 ? executionResult.stdout : null; } catch (err) { toolHelper.writeWarning(err.message); @@ -258,11 +259,11 @@ export class ContainerAppHelper { const util = new Utility(); toolHelper.writeDebug(`Attempting to create Container App Environment with name "${name}" in resource group "${resourceGroup}"`); try { - let command = `containerapp env create -n ${name} -g ${resourceGroup}`; + let command = `az containerapp env create -n ${name} -g ${resourceGroup}`; if (!util.isNullOrEmpty(location)) { command += ` -l ${location}`; } - await util.executeAndThrowIfError(`az "${command}"`); + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -277,8 +278,8 @@ export class ContainerAppHelper { public async disableContainerAppIngress(name: string, resourceGroup: string) { toolHelper.writeDebug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); try { - let command = `containerapp ingress disable -n ${name} -g ${resourceGroup}`; - await util.executeAndThrowIfError(`az "${command}"`); + let command = `az containerapp ingress disable -n ${name} -g ${resourceGroup}`; + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -296,8 +297,8 @@ export class ContainerAppHelper { public async updateContainerAppRegistryDetails(name: string, resourceGroup: string, acrName: string, acrUsername: string, acrPassword: string) { toolHelper.writeDebug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { - let command = `containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; - await util.executeAndThrowIfError(`az "${command}"`); + let command = `az containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -321,7 +322,7 @@ export class ContainerAppHelper { telemetryArg = `ORYX_DISABLE_TELEMETRY=true`; } let command = `build ${imageToDeploy} --path ${appSourcePath} --builder ${ORYX_BUILDER_IMAGE} --run-image mcr.microsoft.com/oryx/${runtimeStack} --env ${telemetryArg}`; - await util.executeAndThrowIfError(`${PACK_CMD} "${command}"`); + await util.executeAndThrowIfError(`${PACK_CMD} ${command}`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -343,7 +344,7 @@ export class ContainerAppHelper { try { let dockerTool = await toolHelper.which("docker", true); let command = `build --file ${dockerfilePath} ${appSourcePath} --tag ${imageToDeploy}`; - await util.executeAndThrowIfError(`${dockerTool} "${command}"`); + await util.executeAndThrowIfError(`${dockerTool} ${command}`); toolHelper.writeDebug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); } catch (err) { toolHelper.writeError(err.message); @@ -363,7 +364,7 @@ export class ContainerAppHelper { // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file let oryxDockerfileCommand = `oryx dockerfile ${appSourcePath} | head -n 1 | sed 's/ARG RUNTIME=//' >> ${appSourcePath}/oryx-runtime.txt` let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c ${oryxDockerfileCommand}}` - await util.executeAndThrowIfError(`${dockerTool} "${command}"`) + await util.executeAndThrowIfError(`${dockerTool} ${command}`) // Read the temp file to get the runtime stack into a variable let oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); @@ -397,8 +398,8 @@ export class ContainerAppHelper { public async setDefaultBuilder() { toolHelper.writeInfo('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { - let command = `config default-builder ${ORYX_BUILDER_IMAGE}` - await util.executeAndThrowIfError(`${PACK_CMD} "${command}"`); + let command = `az config default-builder ${ORYX_BUILDER_IMAGE}` + await util.executeAndThrowIfError(`${PACK_CMD} ${command}`); } catch (err) { toolHelper.writeError(err.message); @@ -422,11 +423,11 @@ export class ContainerAppHelper { commandLine = 'pwsh'; } else { let tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = `-c (curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + + command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } - await util.executeAndThrowIfError(`${commandLine} "${command}"`); + await util.executeAndThrowIfError(`${commandLine} -c "${command}"`); } catch (err) { toolHelper.writeError(`Unable to install the pack CLI. Error: ${err.message}`); throw err; diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 783297b2..2a09fe84 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -16,7 +16,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); try { let dockerTool = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(`${dockerTool} "login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io"`, [] , Buffer.from(acrPassword)); + await util.executeAndThrowIfError(`${dockerTool} login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io`, [] , Buffer.from(acrPassword)); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); throw err; @@ -32,7 +32,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { let commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - await util.executeAndThrowIfError(`${commandLine}"-c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"`); + await util.executeAndThrowIfError(`${commandLine} -c "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"`); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; @@ -47,7 +47,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to ACR`); try { let dockerTool: string = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(`${dockerTool} "tag ${imageToPush} ${imageToPush}"`); + await util.executeAndThrowIfError(`${dockerTool} tag ${imageToPush} ${imageToPush}`); } catch (err) { toolHelper.writeError(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); throw err; diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 55c2e4bf..fbb92517 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -88,7 +88,7 @@ export class TelemetryHelper { let eventName = toolHelper.getEventName(); let dockerTool: string = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(`${dockerTool} "run --rm ${ORYX_CLI_IMAGE} /bin/bash -c oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}"`); + await util.executeAndThrowIfError(`${dockerTool} run --rm ${ORYX_CLI_IMAGE} /bin/bash -c oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`); } catch (err) { toolHelper.writeWarning(`Skipping telemetry logging due to the following exception: ${err.message}`); } diff --git a/src/Utility.ts b/src/Utility.ts index f1b1bdf5..03540885 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -24,7 +24,7 @@ export class Utility { * Azure Container Apps module being dynamically installed while it's still in preview. */ public async setAzureCliDynamicInstall() { - await this.executeAndThrowIfError(`az "config set extension.use_dynamic_install=yes_without_prompt"`); + await this.executeAndThrowIfError(`az config set extension.use_dynamic_install=yes_without_prompt`); } /** From 4e7f25a370e5870aea929b8da9bac26c2d8cb6e6 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 29 Sep 2023 00:29:37 -0700 Subject: [PATCH 25/42] Fix command to get runtime stack --- dist/index.js | 5 ++--- src/ContainerAppHelper.ts | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/dist/index.js b/dist/index.js index a3dd156e..13395e82 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5169,7 +5169,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.determineRuntimeStackAsync = function (appSourcePath) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, oryxDockerfileCommand, command, oryxRuntimeTxtPath_1, runtimeStack, err_17; + var dockerTool, command, oryxRuntimeTxtPath_1, runtimeStack, err_17; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -5180,8 +5180,7 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - oryxDockerfileCommand = "oryx dockerfile " + appSourcePath + " | head -n 1 | sed 's/ARG RUNTIME=//' >> " + appSourcePath + "/oryx-runtime.txt"; - command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c " + oryxDockerfileCommand + "}"; + command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c oryx dockerfile " + appSourcePath + " | head -n 1 | sed 's/ARG RUNTIME=//' >> " + appSourcePath + "/oryx-runtime.txt"; return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " " + command) // Read the temp file to get the runtime stack into a variable ]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 537652e7..cf614648 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -362,8 +362,7 @@ export class ContainerAppHelper { try { let dockerTool: string = await toolHelper.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - let oryxDockerfileCommand = `oryx dockerfile ${appSourcePath} | head -n 1 | sed 's/ARG RUNTIME=//' >> ${appSourcePath}/oryx-runtime.txt` - let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c ${oryxDockerfileCommand}}` + let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c oryx dockerfile ${appSourcePath} | head -n 1 | sed 's/ARG RUNTIME=//' >> ${appSourcePath}/oryx-runtime.txt` await util.executeAndThrowIfError(`${dockerTool} ${command}`) // Read the temp file to get the runtime stack into a variable From 84afe95e0ca1575839617ddee275e482b0bab5f9 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 29 Sep 2023 00:42:01 -0700 Subject: [PATCH 26/42] Fix oryx dockerfile command to get runtime stack --- dist/index.js | 2 +- src/ContainerAppHelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 13395e82..3a1e577c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5180,7 +5180,7 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c oryx dockerfile " + appSourcePath + " | head -n 1 | sed 's/ARG RUNTIME=//' >> " + appSourcePath + "/oryx-runtime.txt"; + command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"; return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " " + command) // Read the temp file to get the runtime stack into a variable ]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index cf614648..7216e154 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -362,7 +362,7 @@ export class ContainerAppHelper { try { let dockerTool: string = await toolHelper.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c oryx dockerfile ${appSourcePath} | head -n 1 | sed 's/ARG RUNTIME=//' >> ${appSourcePath}/oryx-runtime.txt` + let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt` await util.executeAndThrowIfError(`${dockerTool} ${command}`) // Read the temp file to get the runtime stack into a variable From c6376d94e3df59ac6bc8c77b86b87be793cc9933 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 29 Sep 2023 00:50:59 -0700 Subject: [PATCH 27/42] Fix oryx dockerfile command to get runtime stack --- dist/index.js | 2 +- src/ContainerAppHelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 3a1e577c..d2cb36ca 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5180,7 +5180,7 @@ var ContainerAppHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"; + command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\""; return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " " + command) // Read the temp file to get the runtime stack into a variable ]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 7216e154..72b60343 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -362,7 +362,7 @@ export class ContainerAppHelper { try { let dockerTool: string = await toolHelper.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt` + let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\"` await util.executeAndThrowIfError(`${dockerTool} ${command}`) // Read the temp file to get the runtime stack into a variable From 09f89917c7834ad33da66ce077baafab96ed8d29 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 29 Sep 2023 00:53:57 -0700 Subject: [PATCH 28/42] Fix command to set default builder --- dist/index.js | 2 +- src/ContainerAppHelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index d2cb36ca..62084a7d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5224,7 +5224,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az config default-builder " + ORYX_BUILDER_IMAGE; + command = "config default-builder " + ORYX_BUILDER_IMAGE; return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " " + command)]; case 2: _a.sent(); diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 72b60343..dfdf1415 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -397,7 +397,7 @@ export class ContainerAppHelper { public async setDefaultBuilder() { toolHelper.writeInfo('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { - let command = `az config default-builder ${ORYX_BUILDER_IMAGE}` + let command = `config default-builder ${ORYX_BUILDER_IMAGE}` await util.executeAndThrowIfError(`${PACK_CMD} ${command}`); } catch (err) { From dd0b8593c1e7d0fa1f77a9ee8f6e500409c8e9af Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sat, 30 Sep 2023 01:20:31 -0700 Subject: [PATCH 29/42] Test containerapp creation --- dist/index.js | 11 ++++++----- src/ContainerAppHelper.ts | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/dist/index.js b/dist/index.js index 62084a7d..692f0df2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4670,11 +4670,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_1 = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; + command_1 = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError(command_1)]; + return [4 /*yield*/, util.executeAndThrowIfError("az", command_1.split(' '))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4695,7 +4695,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.createContainerAppFromYaml = function (containerAppName, resourceGroup, yamlConfigPath) { return __awaiter(this, void 0, void 0, function () { - var command, err_2; + var err_2; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4703,9 +4703,10 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + // let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + return [4 /*yield*/, util.executeAndThrowIfError("az", ['containerapp', 'create', '-n', containerAppName, '-g', resourceGroup, '--yaml', yamlConfigPath])]; case 2: + // let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; _a.sent(); return [3 /*break*/, 4]; case 3: diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index dfdf1415..caca324d 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -34,11 +34,11 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; + let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(command); + await util.executeAndThrowIfError(`az`, command.split(' ')); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -57,8 +57,8 @@ export class ContainerAppHelper { yamlConfigPath: string) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await util.executeAndThrowIfError(command); + // let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await util.executeAndThrowIfError(`az`, ['containerapp', 'create', '-n', containerAppName, '-g', resourceGroup, '--yaml', yamlConfigPath]); } catch (err) { toolHelper.writeError(err.message); throw err; From 69e32ff85915351b8cdb93b976f555171e47f858 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sat, 30 Sep 2023 01:31:41 -0700 Subject: [PATCH 30/42] Hard code location and re-trigger pipeline --- dist/index.js | 13 ++++++------- src/ContainerAppHelper.ts | 11 ++++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dist/index.js b/dist/index.js index 692f0df2..856e9164 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4670,11 +4670,11 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_1 = "containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; + command_1 = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError("az", command_1.split(' '))]; + return [4 /*yield*/, util.executeAndThrowIfError(command_1)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4695,7 +4695,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.createContainerAppFromYaml = function (containerAppName, resourceGroup, yamlConfigPath) { return __awaiter(this, void 0, void 0, function () { - var err_2; + var command, err_2; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4703,10 +4703,9 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - // let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - return [4 /*yield*/, util.executeAndThrowIfError("az", ['containerapp', 'create', '-n', containerAppName, '-g', resourceGroup, '--yaml', yamlConfigPath])]; + command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: - // let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; _a.sent(); return [3 /*break*/, 4]; case 3: @@ -4932,7 +4931,7 @@ var ContainerAppHelper = /** @class */ (function () { case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; + return [2 /*return*/, "eastus2"]; case 3: err_9 = _a.sent(); toolHelper.writeWarning(err_9.message); diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index caca324d..795c4f11 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -34,11 +34,11 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(`az`, command.split(' ')); + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -57,8 +57,8 @@ export class ContainerAppHelper { yamlConfigPath: string) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - // let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; - await util.executeAndThrowIfError(`az`, ['containerapp', 'create', '-n', containerAppName, '-g', resourceGroup, '--yaml', yamlConfigPath]); + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -210,7 +210,8 @@ export class ContainerAppHelper { let command = `az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\"` let executionResult = await util.executeAndThrowIfError(command); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; + return `eastus2`; + // return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { toolHelper.writeWarning(err.message); return `eastus2`; From 79201adf45a845682ca9db08db713a04684e652e Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sat, 30 Sep 2023 02:21:07 -0700 Subject: [PATCH 31/42] Re-trigger pipeline and test --- dist/index.js | 19 ++++++++----------- src/ContainerAppHelper.ts | 8 +++----- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/dist/index.js b/dist/index.js index 856e9164..630e470d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4931,7 +4931,7 @@ var ContainerAppHelper = /** @class */ (function () { case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return [2 /*return*/, "eastus2"]; + return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; case 3: err_9 = _a.sent(); toolHelper.writeWarning(err_9.message); @@ -5136,28 +5136,25 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.createRunnableAppImageFromDockerfile = function (imageToDeploy, appSourcePath, dockerfilePath) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, command, err_16; + var command, err_16; return __generator(this, function (_a) { switch (_a.label) { case 0: toolHelper.writeDebug("Attempting to create a runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); _a.label = 1; case 1: - _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, toolHelper.which("docker", true)]; + _a.trys.push([1, 3, , 4]); + command = "docker build --file " + dockerfilePath + " " + appSourcePath + " --tag " + imageToDeploy; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: - dockerTool = _a.sent(); - command = "build --file " + dockerfilePath + " " + appSourcePath + " --tag " + imageToDeploy; - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " " + command)]; - case 3: _a.sent(); toolHelper.writeDebug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); - return [3 /*break*/, 5]; - case 4: + return [3 /*break*/, 4]; + case 3: err_16 = _a.sent(); toolHelper.writeError(err_16.message); throw err_16; - case 5: return [2 /*return*/]; + case 4: return [2 /*return*/]; } }); }); diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 795c4f11..a9c14609 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -210,8 +210,7 @@ export class ContainerAppHelper { let command = `az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\"` let executionResult = await util.executeAndThrowIfError(command); // If successful, strip out double quotes, spaces and parentheses from the first location returned - return `eastus2`; - // return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; + return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { toolHelper.writeWarning(err.message); return `eastus2`; @@ -343,9 +342,8 @@ export class ContainerAppHelper { dockerfilePath: string) { toolHelper.writeDebug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); try { - let dockerTool = await toolHelper.which("docker", true); - let command = `build --file ${dockerfilePath} ${appSourcePath} --tag ${imageToDeploy}`; - await util.executeAndThrowIfError(`${dockerTool} ${command}`); + let command = `docker build --file ${dockerfilePath} ${appSourcePath} --tag ${imageToDeploy}`; + await util.executeAndThrowIfError(command); toolHelper.writeDebug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); } catch (err) { toolHelper.writeError(err.message); From 356bfdb8d9ba8ae3b8cd3a540072fcda15a4f724 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Sat, 30 Sep 2023 02:33:48 -0700 Subject: [PATCH 32/42] Fix docker push command --- dist/index.js | 2 +- src/ContainerRegistryHelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 630e470d..3147ddae 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5412,7 +5412,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [4 /*yield*/, toolHelper.which("docker", true)]; case 2: dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " tag " + imageToPush + " " + imageToPush)]; + return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " push " + imageToPush)]; case 3: _a.sent(); return [3 /*break*/, 5]; diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 2a09fe84..b7fe6b4e 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -47,7 +47,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to ACR`); try { let dockerTool: string = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(`${dockerTool} tag ${imageToPush} ${imageToPush}`); + await util.executeAndThrowIfError(`${dockerTool} push ${imageToPush}`); } catch (err) { toolHelper.writeError(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); throw err; From 97ee27f26248be01c5bbf494d815a16b82e465c2 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Thu, 12 Oct 2023 00:03:41 -0700 Subject: [PATCH 33/42] Address PR comments --- azurecontainerapps.ts | 37 ++++----- dist/index.js | 136 ++++++++++++++++----------------- src/ContainerAppHelper.ts | 20 ++--- src/ContainerRegistryHelper.ts | 8 +- src/GithubActionsToolHelper.ts | 13 +++- src/TelemetryHelper.ts | 4 +- 6 files changed, 109 insertions(+), 109 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index dd02e2fc..58e3cb11 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -130,16 +130,16 @@ export class azurecontainerapps { private static validateSupportedScenarioArguments() { // Get the path to the application source to build and run, if provided - this.appSourcePath = this.toolHelper.getInput('appSourcePath', { required: false }); + this.appSourcePath = this.toolHelper.getInput('appSourcePath', false) as string; // Get the name of the ACR instance to push images to, if provided - this.acrName = this.toolHelper.getInput('acrName', { required: false }); + this.acrName = this.toolHelper.getInput('acrName', false) as string; // Get the previously built image to deploy, if provided - this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', false) as string; // Get the YAML configuration file, if provided - this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', false) as string; // Ensure that acrName is also provided if appSourcePath is provided if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName)) { @@ -197,7 +197,7 @@ export class azurecontainerapps { * @returns The name of the Container App to use for the task. */ private static getContainerAppName(): string { - let containerAppName: string = this.toolHelper.getInput('containerAppName', { required: false }); + let containerAppName: string = this.toolHelper.getInput('containerAppName', false); if (this.util.isNullOrEmpty(containerAppName)) { return this.toolHelper.getDefaultContainerAppName(containerAppName); } @@ -212,7 +212,7 @@ export class azurecontainerapps { */ private static async getLocation(): Promise { // Set deployment location, if provided - let location: string = this.toolHelper.getInput('location', { required: false }); + let location: string = this.toolHelper.getInput('location', false); // If no location was provided, use the default location for the Container App service if (this.util.isNullOrEmpty(location)) { @@ -232,7 +232,7 @@ export class azurecontainerapps { */ private static async getOrCreateResourceGroup(containerAppName: string, location: string): Promise { // Get the resource group to deploy to if it was provided, or generate it from the Container App name - let resourceGroup: string = this.toolHelper.getInput('resourceGroup', { required: false }); + let resourceGroup: string = this.toolHelper.getInput('resourceGroup', false); if (this.util.isNullOrEmpty(resourceGroup)) { resourceGroup = `${containerAppName}-rg`; this.toolHelper.writeInfo(`Default resource group name: ${resourceGroup}`); @@ -262,7 +262,7 @@ export class azurecontainerapps { resourceGroup: string, location: string): Promise { // Get the Container App environment if it was provided - let containerAppEnvironment: string = this.toolHelper.getInput('containerAppEnvironment', { required: false }); + let containerAppEnvironment: string = this.toolHelper.getInput('containerAppEnvironment', false); // See if we can reuse an existing Container App environment found in the resource group if (this.util.isNullOrEmpty(containerAppEnvironment)) { @@ -292,8 +292,8 @@ export class azurecontainerapps { * Authenticates calls to the provided Azure Container Registry. */ private static async authenticateAzureContainerRegistryAsync() { - this.acrUsername = this.toolHelper.getInput('acrUsername', { required: false }); - this.acrPassword = this.toolHelper.getInput('acrPassword', { required: false }); + this.acrUsername = this.toolHelper.getInput('acrUsername', false); + this.acrPassword = this.toolHelper.getInput('acrPassword', false); // Login to ACR if credentials were provided if (!this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword)) { @@ -318,9 +318,10 @@ export class azurecontainerapps { */ private static async buildAndPushImageAsync() { // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = this.toolHelper.getInput('imageToBuild', { required: false }); + this.imageToBuild = this.toolHelper.getInput('imageToBuild', false); if (this.util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = `${this.acrName}.azurecr.io/gh-action/container-app:${this.buildId}.${this.buildNumber}`; + const imageRepository = this.toolHelper.getDefaultImageRepository() + this.imageToBuild = `${this.acrName}.azurecr.io/${imageRepository}:${this.buildId}.${this.buildNumber}`; this.toolHelper.writeInfo(`Default image to build: ${this.imageToBuild}`); } @@ -331,7 +332,7 @@ export class azurecontainerapps { } // Get Dockerfile to build, if provided, or check if one exists at the root of the provided application - let dockerfilePath: string = this.toolHelper.getInput('dockerfilePath', { required: false }); + let dockerfilePath: string = this.toolHelper.getInput('dockerfilePath', false); if (this.util.isNullOrEmpty(dockerfilePath)) { this.toolHelper.writeInfo(`No Dockerfile path provided; checking for Dockerfile at root of application source.`); const rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); @@ -366,7 +367,7 @@ export class azurecontainerapps { this.toolHelper.writeInfo(`Successfully installed the pack CLI.`) // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = this.toolHelper.getInput('runtimeStack', { required: false }); + this.runtimeStack = this.toolHelper.getInput('runtimeStack', false); if (this.util.isNullOrEmpty(this.runtimeStack)) { this.runtimeStack = await this.appHelper.determineRuntimeStackAsync(appSourcePath); this.toolHelper.writeInfo(`Runtime stack determined to be: ${this.runtimeStack}`); @@ -406,8 +407,8 @@ export class azurecontainerapps { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = this.toolHelper.getInput('ingress', { required: false }); - this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); + this.ingress = this.toolHelper.getInput('ingress', false); + this.targetPort = this.toolHelper.getInput('targetPort', false); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. @@ -443,7 +444,7 @@ export class azurecontainerapps { // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); + this.targetPort = this.toolHelper.getInput('targetPort', false); if (this.util.isNullOrEmpty(this.targetPort)) { if (!this.util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; @@ -467,7 +468,7 @@ export class azurecontainerapps { } } - const environmentVariables: string = this.toolHelper.getInput('environmentVariables', { required: false }); + const environmentVariables: string = this.toolHelper.getInput('environmentVariables', false); // Add user-specified environment variables if (!this.util.isNullOrEmpty(environmentVariables)) { diff --git a/dist/index.js b/dist/index.js index 3147ddae..7b3d63ea 100644 --- a/dist/index.js +++ b/dist/index.js @@ -148,13 +148,13 @@ var azurecontainerapps = /** @class */ (function () { */ azurecontainerapps.validateSupportedScenarioArguments = function () { // Get the path to the application source to build and run, if provided - this.appSourcePath = this.toolHelper.getInput('appSourcePath', { required: false }); + this.appSourcePath = this.toolHelper.getInput('appSourcePath', false); // Get the name of the ACR instance to push images to, if provided - this.acrName = this.toolHelper.getInput('acrName', { required: false }); + this.acrName = this.toolHelper.getInput('acrName', false); // Get the previously built image to deploy, if provided - this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', { required: false }); + this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', false); // Get the YAML configuration file, if provided - this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', { required: false }); + this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', false); // Ensure that acrName is also provided if appSourcePath is provided if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName)) { var missingAcrNameMessage = "The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."; @@ -237,7 +237,7 @@ var azurecontainerapps = /** @class */ (function () { * @returns The name of the Container App to use for the task. */ azurecontainerapps.getContainerAppName = function () { - var containerAppName = this.toolHelper.getInput('containerAppName', { required: false }); + var containerAppName = this.toolHelper.getInput('containerAppName', false); if (this.util.isNullOrEmpty(containerAppName)) { return this.toolHelper.getDefaultContainerAppName(containerAppName); } @@ -254,7 +254,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - location = this.toolHelper.getInput('location', { required: false }); + location = this.toolHelper.getInput('location', false); if (!this.util.isNullOrEmpty(location)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getDefaultContainerAppLocation()]; case 1: @@ -279,7 +279,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - resourceGroup = this.toolHelper.getInput('resourceGroup', { required: false }); + resourceGroup = this.toolHelper.getInput('resourceGroup', false); if (!this.util.isNullOrEmpty(resourceGroup)) return [3 /*break*/, 3]; resourceGroup = containerAppName + "-rg"; this.toolHelper.writeInfo("Default resource group name: " + resourceGroup); @@ -312,7 +312,7 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - containerAppEnvironment = this.toolHelper.getInput('containerAppEnvironment', { required: false }); + containerAppEnvironment = this.toolHelper.getInput('containerAppEnvironment', false); if (!this.util.isNullOrEmpty(containerAppEnvironment)) return [3 /*break*/, 2]; return [4 /*yield*/, this.appHelper.getExistingContainerAppEnvironment(resourceGroup)]; case 1: @@ -349,8 +349,8 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - this.acrUsername = this.toolHelper.getInput('acrUsername', { required: false }); - this.acrPassword = this.toolHelper.getInput('acrPassword', { required: false }); + this.acrUsername = this.toolHelper.getInput('acrUsername', false); + this.acrPassword = this.toolHelper.getInput('acrPassword', false); if (!(!this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 2]; this.toolHelper.writeInfo("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); return [4 /*yield*/, this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword)]; @@ -380,14 +380,15 @@ var azurecontainerapps = /** @class */ (function () { */ azurecontainerapps.buildAndPushImageAsync = function () { return __awaiter(this, void 0, void 0, function () { - var dockerfilePath, rootDockerfilePath; + var imageRepository, dockerfilePath, rootDockerfilePath; return __generator(this, function (_a) { switch (_a.label) { case 0: // Get the name of the image to build if it was provided, or generate it from build variables - this.imageToBuild = this.toolHelper.getInput('imageToBuild', { required: false }); + this.imageToBuild = this.toolHelper.getInput('imageToBuild', false); if (this.util.isNullOrEmpty(this.imageToBuild)) { - this.imageToBuild = this.acrName + ".azurecr.io/gh-action/container-app:" + this.buildId + "." + this.buildNumber; + imageRepository = this.toolHelper.getDefaultImageRepository(); + this.imageToBuild = this.acrName + ".azurecr.io/" + imageRepository + ":" + this.buildId + "." + this.buildNumber; this.toolHelper.writeInfo("Default image to build: " + this.imageToBuild); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' @@ -395,7 +396,7 @@ var azurecontainerapps = /** @class */ (function () { this.imageToDeploy = this.imageToBuild; this.toolHelper.writeInfo("Default image to deploy: " + this.imageToDeploy); } - dockerfilePath = this.toolHelper.getInput('dockerfilePath', { required: false }); + dockerfilePath = this.toolHelper.getInput('dockerfilePath', false); if (!this.util.isNullOrEmpty(dockerfilePath)) return [3 /*break*/, 4]; this.toolHelper.writeInfo("No Dockerfile path provided; checking for Dockerfile at root of application source."); rootDockerfilePath = path.join(this.appSourcePath, 'Dockerfile'); @@ -451,7 +452,7 @@ var azurecontainerapps = /** @class */ (function () { _b.sent(); this.toolHelper.writeInfo("Successfully installed the pack CLI."); // Get the runtime stack if provided, or determine it using Oryx - this.runtimeStack = this.toolHelper.getInput('runtimeStack', { required: false }); + this.runtimeStack = this.toolHelper.getInput('runtimeStack', false); if (!this.util.isNullOrEmpty(this.runtimeStack)) return [3 /*break*/, 3]; _a = this; return [4 /*yield*/, this.appHelper.determineRuntimeStackAsync(appSourcePath)]; @@ -507,8 +508,8 @@ var azurecontainerapps = /** @class */ (function () { azurecontainerapps.setupContainerAppProperties = function () { this.commandLineArgs = []; // Get the ingress inputs - this.ingress = this.toolHelper.getInput('ingress', { required: false }); - this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); + this.ingress = this.toolHelper.getInput('ingress', false); + this.targetPort = this.toolHelper.getInput('targetPort', false); // If both ingress and target port were not provided for an existing Container App, or if ingress is to be disabled, // use the 'update' command, otherwise we should use the 'up' command that performs a PATCH operation on the ingress properties. this.shouldUseUpdateCommand = this.containerAppExists && @@ -535,7 +536,7 @@ var azurecontainerapps = /** @class */ (function () { // Handle setup for ingress values when enabled if (this.ingressEnabled) { // Get the target port if provided, or determine it based on the application type - this.targetPort = this.toolHelper.getInput('targetPort', { required: false }); + this.targetPort = this.toolHelper.getInput('targetPort', false); if (this.util.isNullOrEmpty(this.targetPort)) { if (!this.util.isNullOrEmpty(this.runtimeStack) && this.runtimeStack.startsWith('python:')) { this.targetPort = '80'; @@ -556,7 +557,7 @@ var azurecontainerapps = /** @class */ (function () { this.commandLineArgs.push("--target-port " + this.targetPort); } } - var environmentVariables = this.toolHelper.getInput('environmentVariables', { required: false }); + var environmentVariables = this.toolHelper.getInput('environmentVariables', false); // Add user-specified environment variables if (!this.util.isNullOrEmpty(environmentVariables)) { // The --replace-env-vars flag is only used for the 'update' command, @@ -4670,7 +4671,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_1 = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment; + command_1 = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --environment " + environment + " --output none"; optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); @@ -4703,7 +4704,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath + " --output none"; return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); @@ -4734,7 +4735,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command_2 = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy; + command_2 = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " -i " + imageToDeploy + " --output none"; optionalCmdArgs.forEach(function (val) { command_2 += " " + val; }); @@ -4809,7 +4810,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath; + command = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath + " --output none"; return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: _a.sent(); @@ -4926,7 +4927,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; + command = "az provider show -n Microsoft.App --query resourceTypes[?resourceType=='containerApps'].locations[] | [0]"; return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); @@ -4977,7 +4978,7 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.getExistingContainerAppEnvironment = function (resourceGroup) { return __awaiter(this, void 0, void 0, function () { - var executionResult, err_11; + var command, executionResult, err_11; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -4985,7 +4986,8 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.executeAndThrowIfError("az containerapp env list -g " + resourceGroup + " --query [0].name")]; + command = "az containerapp env list -g " + resourceGroup + " --query [0].name"; + return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout : null]; @@ -5166,22 +5168,19 @@ var ContainerAppHelper = /** @class */ (function () { */ ContainerAppHelper.prototype.determineRuntimeStackAsync = function (appSourcePath) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, command, oryxRuntimeTxtPath_1, runtimeStack, err_17; + var command, oryxRuntimeTxtPath_1, runtimeStack, err_17; return __generator(this, function (_a) { switch (_a.label) { case 0: toolHelper.writeDebug('Attempting to determine the runtime stack needed for the provided application source'); _a.label = 1; case 1: - _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, toolHelper.which("docker", true)]; - case 2: - dockerTool = _a.sent(); - command = "run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\""; - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " " + command) + _a.trys.push([1, 3, , 4]); + command = "docker run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"; + return [4 /*yield*/, util.executeAndThrowIfError(command) // Read the temp file to get the runtime stack into a variable ]; - case 3: + case 2: _a.sent(); oryxRuntimeTxtPath_1 = path.join(appSourcePath, 'oryx-runtime.txt'); runtimeStack = fs.promises.readFile(oryxRuntimeTxtPath_1, 'utf8').then(function (data) { @@ -5198,11 +5197,11 @@ var ContainerAppHelper = /** @class */ (function () { } }); return [2 /*return*/, runtimeStack]; - case 4: + case 3: err_17 = _a.sent(); toolHelper.writeError(err_17.message); throw err_17; - case 5: return [2 /*return*/]; + case 4: return [2 /*return*/]; } }); }); @@ -5259,7 +5258,7 @@ var ContainerAppHelper = /** @class */ (function () { } else { tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = "(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + + command = "(curl -sSL https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz | " + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } @@ -5342,26 +5341,23 @@ var ContainerRegistryHelper = /** @class */ (function () { */ ContainerRegistryHelper.prototype.loginAcrWithUsernamePassword = function (acrName, acrUsername, acrPassword) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, err_1; + var err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: toolHelper.writeDebug("Attempting to log in to ACR instance \"" + acrName + "\" with username and password credentials"); _a.label = 1; case 1: - _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, toolHelper.which("docker", true)]; + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, util.executeAndThrowIfError("docker login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io", [], Buffer.from(acrPassword))]; case 2: - dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io", [], Buffer.from(acrPassword))]; - case 3: _a.sent(); - return [3 /*break*/, 5]; - case 4: + return [3 /*break*/, 4]; + case 3: err_1 = _a.sent(); toolHelper.writeError("Failed to log in to ACR instance \"" + acrName + "\" with username and password credentials"); throw err_1; - case 5: return [2 /*return*/]; + case 4: return [2 /*return*/]; } }); }); @@ -5382,7 +5378,7 @@ var ContainerRegistryHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c \"CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1\"")]; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5401,26 +5397,23 @@ var ContainerRegistryHelper = /** @class */ (function () { */ ContainerRegistryHelper.prototype.pushImageToAcr = function (imageToPush) { return __awaiter(this, void 0, void 0, function () { - var dockerTool, err_3; + var err_3; return __generator(this, function (_a) { switch (_a.label) { case 0: toolHelper.writeDebug("Attempting to push image \"" + imageToPush + "\" to ACR"); _a.label = 1; case 1: - _a.trys.push([1, 4, , 5]); - return [4 /*yield*/, toolHelper.which("docker", true)]; + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, util.executeAndThrowIfError("docker push " + imageToPush)]; case 2: - dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " push " + imageToPush)]; - case 3: _a.sent(); - return [3 /*break*/, 5]; - case 4: + return [3 /*break*/, 4]; + case 3: err_3 = _a.sent(); toolHelper.writeError("Failed to push image \"" + imageToPush + "\" to ACR. Error: " + err_3.message); throw err_3; - case 5: return [2 /*return*/]; + case 4: return [2 /*return*/]; } }); }); @@ -5538,7 +5531,10 @@ var GitHubActionsToolHelper = /** @class */ (function () { }); }); }; - GitHubActionsToolHelper.prototype.getInput = function (name, options) { + GitHubActionsToolHelper.prototype.getInput = function (name, required) { + var options = { + required: required + }; return core.getInput(name, options); }; GitHubActionsToolHelper.prototype.setFailed = function (message) { @@ -5555,10 +5551,13 @@ var GitHubActionsToolHelper = /** @class */ (function () { return containerAppName; }; GitHubActionsToolHelper.prototype.getTelemetryArg = function () { - return "CALLER_ID=github-actions-v1"; + return "CALLER_ID=github-actions-v2"; }; GitHubActionsToolHelper.prototype.getEventName = function () { - return "ContainerAppsGitHubActionV1"; + return "ContainerAppsGitHubActionV2"; + }; + GitHubActionsToolHelper.prototype.getDefaultImageRepository = function () { + return "gh-action/container-app"; }; return GitHubActionsToolHelper; }()); @@ -5661,16 +5660,16 @@ var TelemetryHelper = /** @class */ (function () { */ TelemetryHelper.prototype.sendLogs = function () { return __awaiter(this, void 0, void 0, function () { - var taskLengthMilliseconds, resultArg, scenarioArg, errorMessageArg, eventName, dockerTool, err_1; + var taskLengthMilliseconds, resultArg, scenarioArg, errorMessageArg, eventName, err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: taskLengthMilliseconds = Date.now() - this.taskStartMilliseconds; - if (!!this.disableTelemetry) return [3 /*break*/, 5]; + if (!!this.disableTelemetry) return [3 /*break*/, 4]; toolHelper.writeInfo("Telemetry enabled; logging metadata about task result, length and scenario targeted."); _a.label = 1; case 1: - _a.trys.push([1, 4, , 5]); + _a.trys.push([1, 3, , 4]); resultArg = ''; if (!util.isNullOrEmpty(this.result)) { resultArg = "--property result=" + this.result; @@ -5684,18 +5683,15 @@ var TelemetryHelper = /** @class */ (function () { errorMessageArg = "--property errorMessage=" + this.errorMessage; } eventName = toolHelper.getEventName(); - return [4 /*yield*/, toolHelper.which("docker", true)]; + return [4 /*yield*/, util.executeAndThrowIfError("docker run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; case 2: - dockerTool = _a.sent(); - return [4 /*yield*/, util.executeAndThrowIfError(dockerTool + " run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; - case 3: _a.sent(); - return [3 /*break*/, 5]; - case 4: + return [3 /*break*/, 4]; + case 3: err_1 = _a.sent(); toolHelper.writeWarning("Skipping telemetry logging due to the following exception: " + err_1.message); - return [3 /*break*/, 5]; - case 5: return [2 /*return*/]; + return [3 /*break*/, 4]; + case 4: return [2 /*return*/]; } }); }); diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index a9c14609..773a43a5 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -34,7 +34,7 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment}`; + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --environment ${environment} --output none`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); @@ -57,7 +57,7 @@ export class ContainerAppHelper { yamlConfigPath: string) { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath} --output none`; await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); @@ -79,7 +79,7 @@ export class ContainerAppHelper { optionalCmdArgs: string[]) { toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" based from image "${imageToDeploy}"`); try { - let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy}`; + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} -i ${imageToDeploy} --output none`; optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); @@ -139,7 +139,7 @@ export class ContainerAppHelper { yamlConfigPath: string) { toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { - let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath}`; + let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath} --output none`; await util.executeAndThrowIfError(command); } catch (err) { toolHelper.writeError(err.message); @@ -207,7 +207,7 @@ export class ContainerAppHelper { public async getDefaultContainerAppLocation(): Promise { toolHelper.writeDebug(`Attempting to get the default location for the Container App service for the subscription.`); try { - let command = `az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\"` + let command = `az provider show -n Microsoft.App --query resourceTypes[?resourceType=='containerApps'].locations[] | [0]` let executionResult = await util.executeAndThrowIfError(command); // If successful, strip out double quotes, spaces and parentheses from the first location returned return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; @@ -241,7 +241,8 @@ export class ContainerAppHelper { public async getExistingContainerAppEnvironment(resourceGroup: string) { toolHelper.writeDebug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { - let executionResult = await util.executeAndThrowIfError(`az containerapp env list -g ${resourceGroup} --query [0].name`); + let command = `az containerapp env list -g ${resourceGroup} --query [0].name` + let executionResult = await util.executeAndThrowIfError(command); return executionResult.exitCode === 0 ? executionResult.stdout : null; } catch (err) { toolHelper.writeWarning(err.message); @@ -359,10 +360,9 @@ export class ContainerAppHelper { public async determineRuntimeStackAsync(appSourcePath: string): Promise { toolHelper.writeDebug('Attempting to determine the runtime stack needed for the provided application source'); try { - let dockerTool: string = await toolHelper.which("docker", true); // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - let command = `run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\"` - await util.executeAndThrowIfError(`${dockerTool} ${command}`) + let command = `docker run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt` + await util.executeAndThrowIfError(command) // Read the temp file to get the runtime stack into a variable let oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); @@ -421,7 +421,7 @@ export class ContainerAppHelper { commandLine = 'pwsh'; } else { let tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = `(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz\" | ` + + command = `(curl -sSL https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz | ` + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index b7fe6b4e..58d06281 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -15,8 +15,7 @@ export class ContainerRegistryHelper { public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); try { - let dockerTool = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(`${dockerTool} login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io`, [] , Buffer.from(acrPassword)); + await util.executeAndThrowIfError(`docker login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io`, [], Buffer.from(acrPassword)); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); throw err; @@ -32,7 +31,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { let commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - await util.executeAndThrowIfError(`${commandLine} -c "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"`); + await util.executeAndThrowIfError(`${commandLine} -c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; @@ -46,8 +45,7 @@ export class ContainerRegistryHelper { public async pushImageToAcr(imageToPush: string) { toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to ACR`); try { - let dockerTool: string = await toolHelper.which("docker", true); - await util.executeAndThrowIfError(`${dockerTool} push ${imageToPush}`); + await util.executeAndThrowIfError(`docker push ${imageToPush}`); } catch (err) { toolHelper.writeError(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); throw err; diff --git a/src/GithubActionsToolHelper.ts b/src/GithubActionsToolHelper.ts index 9da865f8..8dcfa03d 100644 --- a/src/GithubActionsToolHelper.ts +++ b/src/GithubActionsToolHelper.ts @@ -59,7 +59,10 @@ export class GitHubActionsToolHelper { } } - public getInput(name: string, options?: core.InputOptions): string { + public getInput(name: string, required?: boolean): string { + const options: core.InputOptions = { + required:required + } return core.getInput(name, options); } @@ -80,10 +83,14 @@ export class GitHubActionsToolHelper { } public getTelemetryArg(): string { - return `CALLER_ID=github-actions-v1`; + return `CALLER_ID=github-actions-v2`; } public getEventName(): string { - return `ContainerAppsGitHubActionV1`; + return `ContainerAppsGitHubActionV2`; + } + + public getDefaultImageRepository(): string { + return `gh-action/container-app`; } } \ No newline at end of file diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index fbb92517..711cee51 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -86,9 +86,7 @@ export class TelemetryHelper { } let eventName = toolHelper.getEventName(); - let dockerTool: string = await toolHelper.which("docker", true); - - await util.executeAndThrowIfError(`${dockerTool} run --rm ${ORYX_CLI_IMAGE} /bin/bash -c oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`); + await util.executeAndThrowIfError(`docker run --rm ${ORYX_CLI_IMAGE} /bin/bash -c oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`); } catch (err) { toolHelper.writeWarning(`Skipping telemetry logging due to the following exception: ${err.message}`); } From 6f4da9e218e99c334b85c6ac233b9dda70b55754 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Thu, 12 Oct 2023 00:16:58 -0700 Subject: [PATCH 34/42] Fix formating for oryx dockerfile command --- dist/index.js | 2 +- src/ContainerAppHelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 7b3d63ea..0bc3e65f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5176,7 +5176,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "docker run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"; + command = "docker run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\""; return [4 /*yield*/, util.executeAndThrowIfError(command) // Read the temp file to get the runtime stack into a variable ]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 773a43a5..5f391d9a 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -361,7 +361,7 @@ export class ContainerAppHelper { toolHelper.writeDebug('Attempting to determine the runtime stack needed for the provided application source'); try { // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - let command = `docker run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt` + let command = `docker run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\"` await util.executeAndThrowIfError(command) // Read the temp file to get the runtime stack into a variable From 2a212bcb1dcfc164b66f0d1aa7994f07e6f43264 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 13 Oct 2023 14:02:16 -0700 Subject: [PATCH 35/42] Add double quotes --- dist/index.js | 4 ++-- src/ContainerAppHelper.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dist/index.js b/dist/index.js index 0bc3e65f..075680f7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4927,7 +4927,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az provider show -n Microsoft.App --query resourceTypes[?resourceType=='containerApps'].locations[] | [0]"; + command = "az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); @@ -5258,7 +5258,7 @@ var ContainerAppHelper = /** @class */ (function () { } else { tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = "(curl -sSL https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz | " + + command = "(curl -sSL \"https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-" + tgzSuffix + ".tgz\" | " + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 5f391d9a..ecc970b0 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -207,7 +207,7 @@ export class ContainerAppHelper { public async getDefaultContainerAppLocation(): Promise { toolHelper.writeDebug(`Attempting to get the default location for the Container App service for the subscription.`); try { - let command = `az provider show -n Microsoft.App --query resourceTypes[?resourceType=='containerApps'].locations[] | [0]` + let command = `az provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"` let executionResult = await util.executeAndThrowIfError(command); // If successful, strip out double quotes, spaces and parentheses from the first location returned return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; @@ -361,7 +361,7 @@ export class ContainerAppHelper { toolHelper.writeDebug('Attempting to determine the runtime stack needed for the provided application source'); try { // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file - let command = `docker run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\"` + let command = `docker run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"` await util.executeAndThrowIfError(command) // Read the temp file to get the runtime stack into a variable @@ -421,7 +421,7 @@ export class ContainerAppHelper { commandLine = 'pwsh'; } else { let tgzSuffix = os.platform() == 'darwin' ? 'macos' : 'linux'; - command = `(curl -sSL https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz | ` + + command = `(curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.27.0/pack-v0.27.0-${tgzSuffix}.tgz" | ` + 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } From 49c550f40507a09c926b7de8e972e0560f6b3931 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 13 Oct 2023 14:09:47 -0700 Subject: [PATCH 36/42] Address PR comments --- dist/index.js | 6 +++--- src/ContainerAppHelper.ts | 2 +- src/ContainerRegistryHelper.ts | 2 +- src/TelemetryHelper.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index 075680f7..5d225aa1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4986,7 +4986,7 @@ var ContainerAppHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp env list -g " + resourceGroup + " --query [0].name"; + command = "az containerapp env list -g " + resourceGroup + " --query \"[0].name\""; return [4 /*yield*/, util.executeAndThrowIfError(command)]; case 2: executionResult = _a.sent(); @@ -5378,7 +5378,7 @@ var ContainerRegistryHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1")]; + return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c \"CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5683,7 +5683,7 @@ var TelemetryHelper = /** @class */ (function () { errorMessageArg = "--property errorMessage=" + this.errorMessage; } eventName = toolHelper.getEventName(); - return [4 /*yield*/, util.executeAndThrowIfError("docker run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg)]; + return [4 /*yield*/, util.executeAndThrowIfError("docker run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c \"oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index ecc970b0..8b81992a 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -241,7 +241,7 @@ export class ContainerAppHelper { public async getExistingContainerAppEnvironment(resourceGroup: string) { toolHelper.writeDebug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { - let command = `az containerapp env list -g ${resourceGroup} --query [0].name` + let command = `az containerapp env list -g ${resourceGroup} --query "[0].name"` let executionResult = await util.executeAndThrowIfError(command); return executionResult.exitCode === 0 ? executionResult.stdout : null; } catch (err) { diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 58d06281..0f805c4f 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -31,7 +31,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { let commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - await util.executeAndThrowIfError(`${commandLine} -c CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1`); + await util.executeAndThrowIfError(`${commandLine} -c "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"`); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index 711cee51..ad564987 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -86,7 +86,7 @@ export class TelemetryHelper { } let eventName = toolHelper.getEventName(); - await util.executeAndThrowIfError(`docker run --rm ${ORYX_CLI_IMAGE} /bin/bash -c oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}`); + await util.executeAndThrowIfError(`docker run --rm ${ORYX_CLI_IMAGE} /bin/bash -c "oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}"`); } catch (err) { toolHelper.writeWarning(`Skipping telemetry logging due to the following exception: ${err.message}`); } From 43a74c1caebd0d5a08fe1edd88b63a37a3deb992 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Fri, 13 Oct 2023 15:18:08 -0700 Subject: [PATCH 37/42] Change executeAndThrowIfError to execute --- dist/index.js | 70 +++++++++++++++------------------- src/ContainerAppHelper.ts | 48 +++++++++++------------ src/ContainerRegistryHelper.ts | 6 +-- src/TelemetryHelper.ts | 2 +- src/Utility.ts | 11 ++---- 5 files changed, 62 insertions(+), 75 deletions(-) diff --git a/dist/index.js b/dist/index.js index 5d225aa1..f2a244c8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -4675,7 +4675,7 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_1 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError(command_1)]; + return [4 /*yield*/, util.execute(command_1)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4705,7 +4705,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az containerapp create -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath + " --output none"; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4739,7 +4739,7 @@ var ContainerAppHelper = /** @class */ (function () { optionalCmdArgs.forEach(function (val) { command_2 += " " + val; }); - return [4 /*yield*/, util.executeAndThrowIfError(command_2)]; + return [4 /*yield*/, util.execute(command_2)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4781,7 +4781,7 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(targetPort)) { command_3 += " --target-port " + targetPort; } - return [4 /*yield*/, util.executeAndThrowIfError(command_3)]; + return [4 /*yield*/, util.execute(command_3)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4811,7 +4811,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az containerapp update -n " + containerAppName + " -g " + resourceGroup + " --yaml " + yamlConfigPath + " --output none"; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4841,13 +4841,13 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az containerapp show -n " + containerAppName + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_6 = _a.sent(); - toolHelper.writeWarning(err_6.message); + toolHelper.writeInfo(err_6.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4871,13 +4871,13 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az containerapp env show -n " + containerAppEnvironment + " -g " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_7 = _a.sent(); - toolHelper.writeWarning(err_7.message); + toolHelper.writeInfo(err_7.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4900,13 +4900,13 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az group show -n " + resourceGroup + " -o none"; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0]; case 3: err_8 = _a.sent(); - toolHelper.writeWarning(err_8.message); + toolHelper.writeInfo(err_8.message); return [2 /*return*/, false]; case 4: return [2 /*return*/]; } @@ -4928,14 +4928,14 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az provider show -n Microsoft.App --query \"resourceTypes[?resourceType=='containerApps'].locations[] | [0]\""; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: executionResult = _a.sent(); // If successful, strip out double quotes, spaces and parentheses from the first location returned return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : "eastus2"]; case 3: err_9 = _a.sent(); - toolHelper.writeWarning(err_9.message); + toolHelper.writeInfo(err_9.message); return [2 /*return*/, "eastus2"]; case 4: return [2 /*return*/]; } @@ -4958,7 +4958,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az group create -n " + name + " -l " + location; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -4987,13 +4987,13 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az containerapp env list -g " + resourceGroup + " --query \"[0].name\""; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: executionResult = _a.sent(); return [2 /*return*/, executionResult.exitCode === 0 ? executionResult.stdout : null]; case 3: err_11 = _a.sent(); - toolHelper.writeWarning(err_11.message); + toolHelper.writeInfo(err_11.message); return [2 /*return*/, null]; case 4: return [2 /*return*/]; } @@ -5021,7 +5021,7 @@ var ContainerAppHelper = /** @class */ (function () { if (!util.isNullOrEmpty(location)) { command += " -l " + location; } - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5050,7 +5050,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az containerapp ingress disable -n " + name + " -g " + resourceGroup; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5082,7 +5082,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "az containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5116,7 +5116,7 @@ var ContainerAppHelper = /** @class */ (function () { telemetryArg = "ORYX_DISABLE_TELEMETRY=true"; } command = "build " + imageToDeploy + " --path " + appSourcePath + " --builder " + ORYX_BUILDER_IMAGE + " --run-image mcr.microsoft.com/oryx/" + runtimeStack + " --env " + telemetryArg; - return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " " + command)]; + return [4 /*yield*/, util.execute(PACK_CMD + " " + command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5147,7 +5147,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "docker build --file " + dockerfilePath + " " + appSourcePath + " --tag " + imageToDeploy; - return [4 /*yield*/, util.executeAndThrowIfError(command)]; + return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); toolHelper.writeDebug("Successfully created runnable application image from the provided/found Dockerfile \"" + dockerfilePath + "\" with image name \"" + imageToDeploy + "\""); @@ -5177,7 +5177,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "docker run --rm -v " + appSourcePath + ":/app " + ORYX_CLI_IMAGE + " /bin/bash -c \"oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt\""; - return [4 /*yield*/, util.executeAndThrowIfError(command) + return [4 /*yield*/, util.execute(command) // Read the temp file to get the runtime stack into a variable ]; case 2: @@ -5221,7 +5221,7 @@ var ContainerAppHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); command = "config default-builder " + ORYX_BUILDER_IMAGE; - return [4 /*yield*/, util.executeAndThrowIfError(PACK_CMD + " " + command)]; + return [4 /*yield*/, util.execute(PACK_CMD + " " + command)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5262,7 +5262,7 @@ var ContainerAppHelper = /** @class */ (function () { 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } - return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c \"" + command + "\"")]; + return [4 /*yield*/, util.execute(commandLine + " -c \"" + command + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5349,7 +5349,7 @@ var ContainerRegistryHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.executeAndThrowIfError("docker login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io", [], Buffer.from(acrPassword))]; + return [4 /*yield*/, util.execute("docker login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io", [], Buffer.from(acrPassword))]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5378,7 +5378,7 @@ var ContainerRegistryHelper = /** @class */ (function () { case 1: _a.trys.push([1, 3, , 4]); commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - return [4 /*yield*/, util.executeAndThrowIfError(commandLine + " -c \"CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1\"")]; + return [4 /*yield*/, util.execute(commandLine + " -c \"CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name " + acrName + " --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login " + acrName + ".azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5405,7 +5405,7 @@ var ContainerRegistryHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.executeAndThrowIfError("docker push " + imageToPush)]; + return [4 /*yield*/, util.execute("docker push " + imageToPush)]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5683,7 +5683,7 @@ var TelemetryHelper = /** @class */ (function () { errorMessageArg = "--property errorMessage=" + this.errorMessage; } eventName = toolHelper.getEventName(); - return [4 /*yield*/, util.executeAndThrowIfError("docker run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c \"oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; + return [4 /*yield*/, util.execute("docker run --rm " + ORYX_CLI_IMAGE + " /bin/bash -c \"oryx telemetry --event-name " + eventName + " --processing-time " + taskLengthMilliseconds + " " + resultArg + " " + scenarioArg + " " + errorMessageArg + "\"")]; case 2: _a.sent(); return [3 /*break*/, 4]; @@ -5757,20 +5757,12 @@ var Utility = /** @class */ (function () { * @param args - the arguments to pass to the command * @param continueOnError - whether or not to continue execution if the command fails */ - Utility.prototype.executeAndThrowIfError = function (commandLine, args, inputOptions) { + Utility.prototype.execute = function (commandLine, args, inputOptions) { return __awaiter(this, void 0, void 0, function () { - var error_1; return __generator(this, function (_a) { switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - return [4 /*yield*/, toolHelper.exec(commandLine, args, inputOptions)]; + case 0: return [4 /*yield*/, toolHelper.exec(commandLine, args, inputOptions)]; case 1: return [2 /*return*/, _a.sent()]; - case 2: - error_1 = _a.sent(); - toolHelper.writeError("Error: " + error_1.message); - throw error_1; // Re-throw the error - case 3: return [2 /*return*/]; } }); }); @@ -5783,7 +5775,7 @@ var Utility = /** @class */ (function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { - case 0: return [4 /*yield*/, this.executeAndThrowIfError("az config set extension.use_dynamic_install=yes_without_prompt")]; + case 0: return [4 /*yield*/, this.execute("az config set extension.use_dynamic_install=yes_without_prompt")]; case 1: _a.sent(); return [2 /*return*/]; diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 8b81992a..4508ce6b 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -38,7 +38,7 @@ export class ContainerAppHelper { optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -58,7 +58,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to create Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `az containerapp create -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath} --output none`; - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -83,7 +83,7 @@ export class ContainerAppHelper { optionalCmdArgs.forEach(function (val: string) { command += ` ${val}`; }); - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -120,7 +120,7 @@ export class ContainerAppHelper { if (!util.isNullOrEmpty(targetPort)) { command += ` --target-port ${targetPort}`; } - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -140,7 +140,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to update Container App with name "${containerAppName}" in resource group "${resourceGroup}" from provided YAML "${yamlConfigPath}"`); try { let command = `az containerapp update -n ${containerAppName} -g ${resourceGroup} --yaml ${yamlConfigPath} --output none`; - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -157,10 +157,10 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to determine if Container App with name "${containerAppName}" exists in resource group "${resourceGroup}"`); try { let command = `az containerapp show -n ${containerAppName} -g ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(command); + let executionResult = await util.execute(command); return executionResult.exitCode === 0; } catch (err) { - toolHelper.writeWarning(err.message); + toolHelper.writeInfo(err.message); return false; } } @@ -175,10 +175,10 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to determine if Container App Environment with name "${containerAppEnvironment}" exists in resource group "${resourceGroup}"`); try { let command = `az containerapp env show -n ${containerAppEnvironment} -g ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(command); + let executionResult = await util.execute(command); return executionResult.exitCode === 0; } catch (err) { - toolHelper.writeWarning(err.message); + toolHelper.writeInfo(err.message); return false; } } @@ -192,10 +192,10 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to determine if resource group "${resourceGroup}" exists`); try { let command = `az group show -n ${resourceGroup} -o none`; - let executionResult = await util.executeAndThrowIfError(command); + let executionResult = await util.execute(command); return executionResult.exitCode === 0; } catch (err) { - toolHelper.writeWarning(err.message); + toolHelper.writeInfo(err.message); return false; } } @@ -208,11 +208,11 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to get the default location for the Container App service for the subscription.`); try { let command = `az provider show -n Microsoft.App --query "resourceTypes[?resourceType=='containerApps'].locations[] | [0]"` - let executionResult = await util.executeAndThrowIfError(command); + let executionResult = await util.execute(command); // If successful, strip out double quotes, spaces and parentheses from the first location returned return executionResult.exitCode === 0 ? executionResult.stdout.toLowerCase().replace(/["() ]/g, "").trim() : `eastus2`; } catch (err) { - toolHelper.writeWarning(err.message); + toolHelper.writeInfo(err.message); return `eastus2`; } } @@ -226,7 +226,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to create resource group "${name}" in location "${location}"`); try { let command = `az group create -n ${name} -l ${location}`; - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -242,10 +242,10 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to get the existing Container App Environment in resource group "${resourceGroup}"`); try { let command = `az containerapp env list -g ${resourceGroup} --query "[0].name"` - let executionResult = await util.executeAndThrowIfError(command); + let executionResult = await util.execute(command); return executionResult.exitCode === 0 ? executionResult.stdout : null; } catch (err) { - toolHelper.writeWarning(err.message); + toolHelper.writeInfo(err.message); return null; } } @@ -264,7 +264,7 @@ export class ContainerAppHelper { if (!util.isNullOrEmpty(location)) { command += ` -l ${location}`; } - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -280,7 +280,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to disable ingress for Container App with name "${name}" in resource group "${resourceGroup}"`); try { let command = `az containerapp ingress disable -n ${name} -g ${resourceGroup}`; - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -299,7 +299,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { let command = `az containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; - await util.executeAndThrowIfError(command); + await util.execute(command); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -323,7 +323,7 @@ export class ContainerAppHelper { telemetryArg = `ORYX_DISABLE_TELEMETRY=true`; } let command = `build ${imageToDeploy} --path ${appSourcePath} --builder ${ORYX_BUILDER_IMAGE} --run-image mcr.microsoft.com/oryx/${runtimeStack} --env ${telemetryArg}`; - await util.executeAndThrowIfError(`${PACK_CMD} ${command}`); + await util.execute(`${PACK_CMD} ${command}`); } catch (err) { toolHelper.writeError(err.message); throw err; @@ -344,7 +344,7 @@ export class ContainerAppHelper { toolHelper.writeDebug(`Attempting to create a runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); try { let command = `docker build --file ${dockerfilePath} ${appSourcePath} --tag ${imageToDeploy}`; - await util.executeAndThrowIfError(command); + await util.execute(command); toolHelper.writeDebug(`Successfully created runnable application image from the provided/found Dockerfile "${dockerfilePath}" with image name "${imageToDeploy}"`); } catch (err) { toolHelper.writeError(err.message); @@ -362,7 +362,7 @@ export class ContainerAppHelper { try { // Use 'oryx dockerfile' command to determine the runtime stack to use and write it to a temp file let command = `docker run --rm -v ${appSourcePath}:/app ${ORYX_CLI_IMAGE} /bin/bash -c "oryx dockerfile /app | head -n 1 | sed 's/ARG RUNTIME=//' >> /app/oryx-runtime.txt"` - await util.executeAndThrowIfError(command) + await util.execute(command) // Read the temp file to get the runtime stack into a variable let oryxRuntimeTxtPath = path.join(appSourcePath, 'oryx-runtime.txt'); @@ -397,7 +397,7 @@ export class ContainerAppHelper { toolHelper.writeInfo('Setting the Oryx++ Builder as the default builder via the pack CLI'); try { let command = `config default-builder ${ORYX_BUILDER_IMAGE}` - await util.executeAndThrowIfError(`${PACK_CMD} ${command}`); + await util.execute(`${PACK_CMD} ${command}`); } catch (err) { toolHelper.writeError(err.message); @@ -425,7 +425,7 @@ export class ContainerAppHelper { 'tar -C /usr/local/bin/ --no-same-owner -xzv pack)'; commandLine = 'bash'; } - await util.executeAndThrowIfError(`${commandLine} -c "${command}"`); + await util.execute(`${commandLine} -c "${command}"`); } catch (err) { toolHelper.writeError(`Unable to install the pack CLI. Error: ${err.message}`); throw err; diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 0f805c4f..329272e2 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -15,7 +15,7 @@ export class ContainerRegistryHelper { public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); try { - await util.executeAndThrowIfError(`docker login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io`, [], Buffer.from(acrPassword)); + await util.execute(`docker login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io`, [], Buffer.from(acrPassword)); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); throw err; @@ -31,7 +31,7 @@ export class ContainerRegistryHelper { toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with access token`); try { let commandLine = os.platform() === 'win32' ? 'pwsh' : 'bash'; - await util.executeAndThrowIfError(`${commandLine} -c "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"`); + await util.execute(`${commandLine} -c "CA_ADO_TASK_ACR_ACCESS_TOKEN=$(az acr login --name ${acrName} --output json --expose-token --only-show-errors | jq -r '.accessToken'); docker login ${acrName}.azurecr.io -u 00000000-0000-0000-0000-000000000000 -p $CA_ADO_TASK_ACR_ACCESS_TOKEN > /dev/null 2>&1"`); } catch (err) { toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with access token`) throw err; @@ -45,7 +45,7 @@ export class ContainerRegistryHelper { public async pushImageToAcr(imageToPush: string) { toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to ACR`); try { - await util.executeAndThrowIfError(`docker push ${imageToPush}`); + await util.execute(`docker push ${imageToPush}`); } catch (err) { toolHelper.writeError(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); throw err; diff --git a/src/TelemetryHelper.ts b/src/TelemetryHelper.ts index ad564987..141fbcf0 100644 --- a/src/TelemetryHelper.ts +++ b/src/TelemetryHelper.ts @@ -86,7 +86,7 @@ export class TelemetryHelper { } let eventName = toolHelper.getEventName(); - await util.executeAndThrowIfError(`docker run --rm ${ORYX_CLI_IMAGE} /bin/bash -c "oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}"`); + await util.execute(`docker run --rm ${ORYX_CLI_IMAGE} /bin/bash -c "oryx telemetry --event-name ${eventName} --processing-time ${taskLengthMilliseconds} ${resultArg} ${scenarioArg} ${errorMessageArg}"`); } catch (err) { toolHelper.writeWarning(`Skipping telemetry logging due to the following exception: ${err.message}`); } diff --git a/src/Utility.ts b/src/Utility.ts index 03540885..6c55c9b6 100644 --- a/src/Utility.ts +++ b/src/Utility.ts @@ -10,13 +10,8 @@ export class Utility { * @param continueOnError - whether or not to continue execution if the command fails */ - public async executeAndThrowIfError(commandLine: string, args?: string[], inputOptions?:Buffer): Promise<{ exitCode: number, stdout: string, stderr: string }> { - try { - return await toolHelper.exec(commandLine, args, inputOptions); - } catch (error) { - toolHelper.writeError(`Error: ${error.message}`); - throw error; // Re-throw the error - } + public async execute(commandLine: string, args?: string[], inputOptions?:Buffer): Promise<{ exitCode: number, stdout: string, stderr: string }> { + return await toolHelper.exec(commandLine, args, inputOptions); } /** @@ -24,7 +19,7 @@ export class Utility { * Azure Container Apps module being dynamically installed while it's still in preview. */ public async setAzureCliDynamicInstall() { - await this.executeAndThrowIfError(`az config set extension.use_dynamic_install=yes_without_prompt`); + await this.execute(`az config set extension.use_dynamic_install=yes_without_prompt`); } /** From be168f5360a7ccc29f1afa56c243cc09af825eec Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Mon, 16 Oct 2023 20:19:21 -0700 Subject: [PATCH 38/42] Support registry arguments --- azurecontainerapps.ts | 81 +++++++++++++++++++++++----------- src/ContainerAppHelper.ts | 14 +++--- src/ContainerRegistryHelper.ts | 26 +++++------ 3 files changed, 76 insertions(+), 45 deletions(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index 58e3cb11..ce861333 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -26,6 +26,11 @@ export class azurecontainerapps { await this.authenticateAzureContainerRegistryAsync(); } + // If a Container Registry URL was provided, try to authenticate against it + if (!this.util.isNullOrEmpty(this.registryUrl)) { + await this.authenticateContainerRegistryAsync(); + } + // If the application source was provided, build a runnable application image from it if (!this.util.isNullOrEmpty(this.appSourcePath)) { await this.buildAndPushImageAsync(); @@ -73,9 +78,10 @@ export class azurecontainerapps { private static containerAppEnvironment: string; private static ingressEnabled: boolean; - // ACR properties - private static acrUsername: string; - private static acrPassword: string; + // Container Registry properties + private static registryUsername: string; + private static registryPassword: string; + private static registryUrl: string; // Command line arguments private static commandLineArgs: string[]; @@ -119,7 +125,7 @@ export class azurecontainerapps { // Set up ContainerAppHelper for managing calls around the Container App this.appHelper = new ContainerAppHelper(disableTelemetry); - // Set up ContainerRegistryHelper for managing calls around ACR + // Set up ContainerRegistryHelper for managing calls around the Container Registry this.registryHelper = new ContainerRegistryHelper(); } @@ -135,17 +141,20 @@ export class azurecontainerapps { // Get the name of the ACR instance to push images to, if provided this.acrName = this.toolHelper.getInput('acrName', false) as string; + // Get the name of the RegistryUrl to push images to, if provided + this.registryUrl = this.toolHelper.getInput('registryUrl', false) as string; + // Get the previously built image to deploy, if provided this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', false) as string; // Get the YAML configuration file, if provided this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', false) as string; - // Ensure that acrName is also provided if appSourcePath is provided - if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName)) { - let missingAcrNameMessage = `The 'acrName' argument must be provided when the 'appSourcePath' argument is provided.`; - this.toolHelper.writeError(missingAcrNameMessage); - throw Error(missingAcrNameMessage); + // Ensure that acrName or registryUrl is also provided if appSourcePath is provided + if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName) && this.util.isNullOrEmpty(this.registryUrl)) { + let missingRegistryUrlMessage = `The 'acrName' or 'registryUrl' argument must be provided when the 'appSourcePath' argument is provided.`; + this.toolHelper.writeError(missingRegistryUrlMessage); + throw Error(missingRegistryUrlMessage); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided @@ -154,6 +163,13 @@ export class azurecontainerapps { this.toolHelper.writeError(requiredArgumentMessage); throw Error(requiredArgumentMessage); } + + // Ensure that an ACR name and registry URL are not both provided + if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.registryUrl)) { + let conflictingArgumentsMessage = `The 'acrName' and 'registryUrl' arguments cannot both be provided.`; + this.toolHelper.writeError(conflictingArgumentsMessage); + throw Error(conflictingArgumentsMessage); + } } /** @@ -292,19 +308,34 @@ export class azurecontainerapps { * Authenticates calls to the provided Azure Container Registry. */ private static async authenticateAzureContainerRegistryAsync() { - this.acrUsername = this.toolHelper.getInput('acrUsername', false); - this.acrPassword = this.toolHelper.getInput('acrPassword', false); + this.registryUsername = this.toolHelper.getInput('acrUsername', false); + this.registryPassword= this.toolHelper.getInput('acrPassword', false); + this.registryUrl = `${this.acrName}.azurecr.io`; // Login to ACR if credentials were provided - if (!this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword)) { + if (!this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword)) { this.toolHelper.writeInfo(`Logging in to ACR instance "${this.acrName}" with username and password credentials`); - await this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword); + await this.registryHelper.loginContainerRegistryWithUsernamePassword(this.registryUrl, this.registryUsername, this.registryPassword); } else { this.toolHelper.writeInfo(`No ACR credentials provided; attempting to log in to ACR instance "${this.acrName}" with access token`); await this.registryHelper.loginAcrWithAccessTokenAsync(this.acrName); } } + /** + * Authenticates calls to the provided Container Registry. + */ + private static async authenticateContainerRegistryAsync() { + this.registryUsername = this.toolHelper.getInput('registryUsername', false); + this.registryPassword = this.toolHelper.getInput('registryPassword', false); + + // Login to Container Registry if credentials were provided + if (!this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword)) { + this.toolHelper.writeInfo(`Logging in to Container Registry "${this.registryUrl}" with username and password credentials`); + await this.registryHelper.loginContainerRegistryWithUsernamePassword(this.registryUrl, this.registryUsername, this.registryPassword); + } + } + /** * Sets up the scenario where an existing image is used for the Container App. */ @@ -314,14 +345,14 @@ export class azurecontainerapps { } /** - * Builds a runnable application image using a Dockerfile or the builder and pushes it to ACR. + * Builds a runnable application image using a Dockerfile or the builder and pushes it to the Container Registry. */ private static async buildAndPushImageAsync() { // Get the name of the image to build if it was provided, or generate it from build variables this.imageToBuild = this.toolHelper.getInput('imageToBuild', false); if (this.util.isNullOrEmpty(this.imageToBuild)) { const imageRepository = this.toolHelper.getDefaultImageRepository() - this.imageToBuild = `${this.acrName}.azurecr.io/${imageRepository}:${this.buildId}.${this.buildNumber}`; + this.imageToBuild = `${this.registryUrl}/${imageRepository}:${this.buildId}.${this.buildNumber}`; this.toolHelper.writeInfo(`Default image to build: ${this.imageToBuild}`); } @@ -352,8 +383,8 @@ export class azurecontainerapps { await this.builderImageFromDockerfile(this.appSourcePath, dockerfilePath, this.imageToBuild); } - // Push the image to ACR - await this.registryHelper.pushImageToAcr(this.imageToBuild); + // Push the image to the Container Registry + await this.registryHelper.pushImageToContainerRegistry(this.imageToBuild); } /** @@ -416,13 +447,13 @@ export class azurecontainerapps { this.util.isNullOrEmpty(this.targetPort) && (this.util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); - // Pass the ACR credentials when creating a Container App or updating a Container App via the 'up' command - if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword) && + // Pass the Container Registry credentials when creating a Container App or updating a Container App via the 'up' command + if (!this.util.isNullOrEmpty(this.registryUrl) && !this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword) && (!this.containerAppExists || (this.containerAppExists && !this.shouldUseUpdateCommand))) { this.commandLineArgs.push( - `--registry-server ${this.acrName}.azurecr.io`, - `--registry-username ${this.acrUsername}`, - `--registry-password ${this.acrPassword}`); + `--registry-server ${this.registryUrl}`, + `--registry-username ${this.registryUsername}`, + `--registry-password ${this.registryPassword}`); } // Determine default values only for the 'create' scenario to avoid overriding existing values for the 'update' scenario @@ -506,9 +537,9 @@ export class azurecontainerapps { } if (this.shouldUseUpdateCommand) { - // Update the ACR details on the existing Container App, if provided as an input - if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword)) { - await this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.acrName, this.acrUsername, this.acrPassword); + // Update the Container Registry details on the existing Container App, if provided as an input + if (!this.util.isNullOrEmpty(this.registryUrl) && !this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword)) { + await this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.registryUrl, this.registryUsername, this.registryPassword); } // Update the Container App using the 'update' command diff --git a/src/ContainerAppHelper.ts b/src/ContainerAppHelper.ts index 4508ce6b..dc416ed2 100644 --- a/src/ContainerAppHelper.ts +++ b/src/ContainerAppHelper.ts @@ -288,17 +288,17 @@ export class ContainerAppHelper { } /** - * Updates the ACR details on an existing Container App. + * Updates the Container Registry details on an existing Container App. * @param name - the name of the Container App * @param resourceGroup - the resource group that the Container App is found in - * @param acrName - the name of the Azure Container Registry (without the .azurecr.io suffix) - * @param acrUsername - the username used to authenticate with the Azure Container Registry - * @param acrPassword - the password used to authenticate with the Azure Container Registry + * @param registryUrl - the name of the Container Registry + * @param registryUsername - the username used to authenticate with the Container Registry + * @param registryPassword - the password used to authenticate with the Container Registry */ - public async updateContainerAppRegistryDetails(name: string, resourceGroup: string, acrName: string, acrUsername: string, acrPassword: string) { - toolHelper.writeDebug(`Attempting to set the ACR details for Container App with name "${name}" in resource group "${resourceGroup}"`); + public async updateContainerAppRegistryDetails(name: string, resourceGroup: string, registryUrl: string, registryUsername: string, registryPassword: string) { + toolHelper.writeDebug(`Attempting to set the Container Registry details for Container App with name "${name}" in resource group "${resourceGroup}"`); try { - let command = `az containerapp registry set -n ${name} -g ${resourceGroup} --server ${acrName}.azurecr.io --username ${acrUsername} --password ${acrPassword}`; + let command = `az containerapp registry set -n ${name} -g ${resourceGroup} --server ${registryUrl} --username ${registryUsername} --password ${registryPassword}`; await util.execute(command); } catch (err) { toolHelper.writeError(err.message); diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 329272e2..43797347 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -7,17 +7,17 @@ const util = new Utility(); export class ContainerRegistryHelper { /** - * Authorizes Docker to make calls to the provided ACR instance using username and password. - * @param acrName - the name of the ACR instance to authenticate calls to - * @param acrUsername - the username for authentication - * @param acrPassword - the password for authentication + * Authorizes Docker to make calls to the provided Container Registry instance using username and password. + * @param registryUrl - the name of the Container Registry instance to authenticate calls to + * @param registryUsername - the username for authentication + * @param registryPassword - the password for authentication */ - public async loginAcrWithUsernamePassword(acrName: string, acrUsername: string, acrPassword: string) { - toolHelper.writeDebug(`Attempting to log in to ACR instance "${acrName}" with username and password credentials`); + public async loginContainerRegistryWithUsernamePassword(registryUrl: string, registryUsername: string, registryPassword: string) { + toolHelper.writeDebug(`Attempting to log in to Container Registry instance"${registryUrl}" with username and password credentials`); try { - await util.execute(`docker login --username ${acrUsername} --password ${acrPassword} ${acrName}.azurecr.io`, [], Buffer.from(acrPassword)); + await util.execute(`docker login --username ${registryUsername} --password ${registryPassword} ${registryUrl}`, [], Buffer.from(registryPassword)); } catch (err) { - toolHelper.writeError(`Failed to log in to ACR instance "${acrName}" with username and password credentials`); + toolHelper.writeError(`Failed to log in to Container Registry instance "${registryUrl}" with username and password credentials`); throw err; } } @@ -39,15 +39,15 @@ export class ContainerRegistryHelper { } /** - * Pushes an image to the ACR instance that was previously authenticated against. - * @param imageToPush - the name of the image to push to ACR + * Pushes an image to the Container Registry instance that was previously authenticated against. + * @param imageToPush - the name of the image to push to the Container Registry instance */ - public async pushImageToAcr(imageToPush: string) { - toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to ACR`); + public async pushImageToContainerRegistry(imageToPush: string) { + toolHelper.writeDebug(`Attempting to push image "${imageToPush}" to Container Registry`); try { await util.execute(`docker push ${imageToPush}`); } catch (err) { - toolHelper.writeError(`Failed to push image "${imageToPush}" to ACR. Error: ${err.message}`); + toolHelper.writeError(`Failed to push image "${imageToPush}" to Container Registry. Error: ${err.message}`); throw err; } } From ae78a4338c1f6ed8c3a821e6eec8d70b0da6762d Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Mon, 16 Oct 2023 23:59:35 -0700 Subject: [PATCH 39/42] Updated index.js --- dist/index.js | 136 ++++++++++++++++++++++++++++++----------------- dist/licenses.tx | 97 +++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 50 deletions(-) create mode 100644 dist/licenses.tx diff --git a/dist/index.js b/dist/index.js index f2a244c8..a9fdc12b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -63,7 +63,7 @@ var azurecontainerapps = /** @class */ (function () { this.initializeHelpers(); _a.label = 1; case 1: - _a.trys.push([1, 9, 10, 12]); + _a.trys.push([1, 11, 12, 14]); // Validate that the arguments provided can be used for one of the supported scenarios this.validateSupportedScenarioArguments(); // Set up the Azure CLI to be used for this task @@ -82,12 +82,18 @@ var azurecontainerapps = /** @class */ (function () { _a.sent(); _a.label = 5; case 5: - if (!!this.util.isNullOrEmpty(this.appSourcePath)) return [3 /*break*/, 7]; - return [4 /*yield*/, this.buildAndPushImageAsync()]; + if (!!this.util.isNullOrEmpty(this.registryUrl)) return [3 /*break*/, 7]; + return [4 /*yield*/, this.authenticateContainerRegistryAsync()]; case 6: _a.sent(); _a.label = 7; case 7: + if (!!this.util.isNullOrEmpty(this.appSourcePath)) return [3 /*break*/, 9]; + return [4 /*yield*/, this.buildAndPushImageAsync()]; + case 8: + _a.sent(); + _a.label = 9; + case 9: // If no application source was provided, set up the scenario for deploying an existing image if (this.util.isNullOrEmpty(this.appSourcePath)) { this.setupExistingImageScenario(); @@ -98,25 +104,25 @@ var azurecontainerapps = /** @class */ (function () { } // Create/update the Container App return [4 /*yield*/, this.createOrUpdateContainerApp()]; - case 8: + case 10: // Create/update the Container App _a.sent(); // If telemetry is enabled, log that the task completed successfully this.telemetryHelper.setSuccessfulResult(); - return [3 /*break*/, 12]; - case 9: + return [3 /*break*/, 14]; + case 11: err_1 = _a.sent(); this.toolHelper.setFailed(err_1.message); this.telemetryHelper.setFailedResult(err_1.message); - return [3 /*break*/, 12]; - case 10: + return [3 /*break*/, 14]; + case 12: // If telemetry is enabled, will log metadata for this task run return [4 /*yield*/, this.telemetryHelper.sendLogs()]; - case 11: + case 13: // If telemetry is enabled, will log metadata for this task run _a.sent(); return [7 /*endfinally*/]; - case 12: return [2 /*return*/]; + case 14: return [2 /*return*/]; } }); }); @@ -139,7 +145,7 @@ var azurecontainerapps = /** @class */ (function () { this.telemetryHelper = new TelemetryHelper_1.TelemetryHelper(disableTelemetry); // Set up ContainerAppHelper for managing calls around the Container App this.appHelper = new ContainerAppHelper_1.ContainerAppHelper(disableTelemetry); - // Set up ContainerRegistryHelper for managing calls around ACR + // Set up ContainerRegistryHelper for managing calls around the Container Registry this.registryHelper = new ContainerRegistryHelper_1.ContainerRegistryHelper(); }; /** @@ -151,15 +157,17 @@ var azurecontainerapps = /** @class */ (function () { this.appSourcePath = this.toolHelper.getInput('appSourcePath', false); // Get the name of the ACR instance to push images to, if provided this.acrName = this.toolHelper.getInput('acrName', false); + // Get the name of the RegistryUrl to push images to, if provided + this.registryUrl = this.toolHelper.getInput('registryUrl', false); // Get the previously built image to deploy, if provided this.imageToDeploy = this.toolHelper.getInput('imageToDeploy', false); // Get the YAML configuration file, if provided this.yamlConfigPath = this.toolHelper.getInput('yamlConfigPath', false); - // Ensure that acrName is also provided if appSourcePath is provided - if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName)) { - var missingAcrNameMessage = "The 'acrName' argument must be provided when the 'appSourcePath' argument is provided."; - this.toolHelper.writeError(missingAcrNameMessage); - throw Error(missingAcrNameMessage); + // Ensure that acrName or registryUrl is also provided if appSourcePath is provided + if (!this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.acrName) && this.util.isNullOrEmpty(this.registryUrl)) { + var missingRegistryUrlMessage = "The 'acrName' or 'registryUrl' argument must be provided when the 'appSourcePath' argument is provided."; + this.toolHelper.writeError(missingRegistryUrlMessage); + throw Error(missingRegistryUrlMessage); } // Ensure that one of appSourcePath, imageToDeploy, or yamlConfigPath is provided if (this.util.isNullOrEmpty(this.appSourcePath) && this.util.isNullOrEmpty(this.imageToDeploy) && this.util.isNullOrEmpty(this.yamlConfigPath)) { @@ -167,6 +175,12 @@ var azurecontainerapps = /** @class */ (function () { this.toolHelper.writeError(requiredArgumentMessage); throw Error(requiredArgumentMessage); } + // Ensure that an ACR name and registry URL are not both provided + if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.registryUrl)) { + var conflictingArgumentsMessage = "The 'acrName' and 'registryUrl' arguments cannot both be provided."; + this.toolHelper.writeError(conflictingArgumentsMessage); + throw Error(conflictingArgumentsMessage); + } }; /** * Sets up the Azure CLI to be used for this task by logging in to Azure with the provided service connection and @@ -349,11 +363,12 @@ var azurecontainerapps = /** @class */ (function () { return __generator(this, function (_a) { switch (_a.label) { case 0: - this.acrUsername = this.toolHelper.getInput('acrUsername', false); - this.acrPassword = this.toolHelper.getInput('acrPassword', false); - if (!(!this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 2]; + this.registryUsername = this.toolHelper.getInput('acrUsername', false); + this.registryPassword = this.toolHelper.getInput('acrPassword', false); + this.registryUrl = this.acrName + ".azurecr.io"; + if (!(!this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword))) return [3 /*break*/, 2]; this.toolHelper.writeInfo("Logging in to ACR instance \"" + this.acrName + "\" with username and password credentials"); - return [4 /*yield*/, this.registryHelper.loginAcrWithUsernamePassword(this.acrName, this.acrUsername, this.acrPassword)]; + return [4 /*yield*/, this.registryHelper.loginContainerRegistryWithUsernamePassword(this.registryUrl, this.registryUsername, this.registryPassword)]; case 1: _a.sent(); return [3 /*break*/, 4]; @@ -368,6 +383,27 @@ var azurecontainerapps = /** @class */ (function () { }); }); }; + /** + * Authenticates calls to the provided Container Registry. + */ + azurecontainerapps.authenticateContainerRegistryAsync = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.registryUsername = this.toolHelper.getInput('registryUsername', false); + this.registryPassword = this.toolHelper.getInput('registryPassword', false); + if (!(!this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword))) return [3 /*break*/, 2]; + this.toolHelper.writeInfo("Logging in to Container Registry \"" + this.registryUrl + "\" with username and password credentials"); + return [4 /*yield*/, this.registryHelper.loginContainerRegistryWithUsernamePassword(this.registryUrl, this.registryUsername, this.registryPassword)]; + case 1: + _a.sent(); + _a.label = 2; + case 2: return [2 /*return*/]; + } + }); + }); + }; /** * Sets up the scenario where an existing image is used for the Container App. */ @@ -376,7 +412,7 @@ var azurecontainerapps = /** @class */ (function () { this.telemetryHelper.setImageScenario(); }; /** - * Builds a runnable application image using a Dockerfile or the builder and pushes it to ACR. + * Builds a runnable application image using a Dockerfile or the builder and pushes it to the Container Registry. */ azurecontainerapps.buildAndPushImageAsync = function () { return __awaiter(this, void 0, void 0, function () { @@ -388,7 +424,7 @@ var azurecontainerapps = /** @class */ (function () { this.imageToBuild = this.toolHelper.getInput('imageToBuild', false); if (this.util.isNullOrEmpty(this.imageToBuild)) { imageRepository = this.toolHelper.getDefaultImageRepository(); - this.imageToBuild = this.acrName + ".azurecr.io/" + imageRepository + ":" + this.buildId + "." + this.buildNumber; + this.imageToBuild = this.registryUrl + "/" + imageRepository + ":" + this.buildId + "." + this.buildNumber; this.toolHelper.writeInfo("Default image to build: " + this.imageToBuild); } // Get the name of the image to deploy if it was provided, or set it to the value of 'imageToBuild' @@ -424,10 +460,10 @@ var azurecontainerapps = /** @class */ (function () { _a.sent(); _a.label = 7; case 7: - // Push the image to ACR - return [4 /*yield*/, this.registryHelper.pushImageToAcr(this.imageToBuild)]; + // Push the image to the Container Registry + return [4 /*yield*/, this.registryHelper.pushImageToContainerRegistry(this.imageToBuild)]; case 8: - // Push the image to ACR + // Push the image to the Container Registry _a.sent(); return [2 /*return*/]; } @@ -515,10 +551,10 @@ var azurecontainerapps = /** @class */ (function () { this.shouldUseUpdateCommand = this.containerAppExists && this.util.isNullOrEmpty(this.targetPort) && (this.util.isNullOrEmpty(this.ingress) || this.ingress == 'disabled'); - // Pass the ACR credentials when creating a Container App or updating a Container App via the 'up' command - if (!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword) && + // Pass the Container Registry credentials when creating a Container App or updating a Container App via the 'up' command + if (!this.util.isNullOrEmpty(this.registryUrl) && !this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword) && (!this.containerAppExists || (this.containerAppExists && !this.shouldUseUpdateCommand))) { - this.commandLineArgs.push("--registry-server " + this.acrName + ".azurecr.io", "--registry-username " + this.acrUsername, "--registry-password " + this.acrPassword); + this.commandLineArgs.push("--registry-server " + this.registryUrl, "--registry-username " + this.registryUsername, "--registry-password " + this.registryPassword); } // Determine default values only for the 'create' scenario to avoid overriding existing values for the 'update' scenario if (!this.containerAppExists) { @@ -604,8 +640,8 @@ var azurecontainerapps = /** @class */ (function () { return [2 /*return*/]; case 7: if (!this.shouldUseUpdateCommand) return [3 /*break*/, 11]; - if (!(!this.util.isNullOrEmpty(this.acrName) && !this.util.isNullOrEmpty(this.acrUsername) && !this.util.isNullOrEmpty(this.acrPassword))) return [3 /*break*/, 9]; - return [4 /*yield*/, this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.acrName, this.acrUsername, this.acrPassword)]; + if (!(!this.util.isNullOrEmpty(this.registryUrl) && !this.util.isNullOrEmpty(this.registryUsername) && !this.util.isNullOrEmpty(this.registryPassword))) return [3 /*break*/, 9]; + return [4 /*yield*/, this.appHelper.updateContainerAppRegistryDetails(this.containerAppName, this.resourceGroup, this.registryUrl, this.registryUsername, this.registryPassword)]; case 8: _a.sent(); _a.label = 9; @@ -5064,24 +5100,24 @@ var ContainerAppHelper = /** @class */ (function () { }); }; /** - * Updates the ACR details on an existing Container App. + * Updates the Container Registry details on an existing Container App. * @param name - the name of the Container App * @param resourceGroup - the resource group that the Container App is found in - * @param acrName - the name of the Azure Container Registry (without the .azurecr.io suffix) - * @param acrUsername - the username used to authenticate with the Azure Container Registry - * @param acrPassword - the password used to authenticate with the Azure Container Registry + * @param registryUrl - the name of the Container Registry + * @param registryUsername - the username used to authenticate with the Container Registry + * @param registryPassword - the password used to authenticate with the Container Registry */ - ContainerAppHelper.prototype.updateContainerAppRegistryDetails = function (name, resourceGroup, acrName, acrUsername, acrPassword) { + ContainerAppHelper.prototype.updateContainerAppRegistryDetails = function (name, resourceGroup, registryUrl, registryUsername, registryPassword) { return __awaiter(this, void 0, void 0, function () { var command, err_14; return __generator(this, function (_a) { switch (_a.label) { case 0: - toolHelper.writeDebug("Attempting to set the ACR details for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); + toolHelper.writeDebug("Attempting to set the Container Registry details for Container App with name \"" + name + "\" in resource group \"" + resourceGroup + "\""); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - command = "az containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + acrName + ".azurecr.io --username " + acrUsername + " --password " + acrPassword; + command = "az containerapp registry set -n " + name + " -g " + resourceGroup + " --server " + registryUrl + " --username " + registryUsername + " --password " + registryPassword; return [4 /*yield*/, util.execute(command)]; case 2: _a.sent(); @@ -5334,28 +5370,28 @@ var ContainerRegistryHelper = /** @class */ (function () { function ContainerRegistryHelper() { } /** - * Authorizes Docker to make calls to the provided ACR instance using username and password. - * @param acrName - the name of the ACR instance to authenticate calls to - * @param acrUsername - the username for authentication - * @param acrPassword - the password for authentication + * Authorizes Docker to make calls to the provided Container Registry instance using username and password. + * @param registryUrl - the name of the Container Registry instance to authenticate calls to + * @param registryUsername - the username for authentication + * @param registryPassword - the password for authentication */ - ContainerRegistryHelper.prototype.loginAcrWithUsernamePassword = function (acrName, acrUsername, acrPassword) { + ContainerRegistryHelper.prototype.loginContainerRegistryWithUsernamePassword = function (registryUrl, registryUsername, registryPassword) { return __awaiter(this, void 0, void 0, function () { var err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: - toolHelper.writeDebug("Attempting to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + toolHelper.writeDebug("Attempting to log in to Container Registry instance\"" + registryUrl + "\" with username and password credentials"); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.execute("docker login --username " + acrUsername + " --password " + acrPassword + " " + acrName + ".azurecr.io", [], Buffer.from(acrPassword))]; + return [4 /*yield*/, util.execute("docker login --username " + registryUsername + " --password " + registryPassword + " " + registryUrl, [], Buffer.from(registryPassword))]; case 2: _a.sent(); return [3 /*break*/, 4]; case 3: err_1 = _a.sent(); - toolHelper.writeError("Failed to log in to ACR instance \"" + acrName + "\" with username and password credentials"); + toolHelper.writeError("Failed to log in to Container Registry instance \"" + registryUrl + "\" with username and password credentials"); throw err_1; case 4: return [2 /*return*/]; } @@ -5392,16 +5428,16 @@ var ContainerRegistryHelper = /** @class */ (function () { }); }; /** - * Pushes an image to the ACR instance that was previously authenticated against. - * @param imageToPush - the name of the image to push to ACR + * Pushes an image to the Container Registry instance that was previously authenticated against. + * @param imageToPush - the name of the image to push to the Container Registry instance */ - ContainerRegistryHelper.prototype.pushImageToAcr = function (imageToPush) { + ContainerRegistryHelper.prototype.pushImageToContainerRegistry = function (imageToPush) { return __awaiter(this, void 0, void 0, function () { var err_3; return __generator(this, function (_a) { switch (_a.label) { case 0: - toolHelper.writeDebug("Attempting to push image \"" + imageToPush + "\" to ACR"); + toolHelper.writeDebug("Attempting to push image \"" + imageToPush + "\" to Container Registry"); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); @@ -5411,7 +5447,7 @@ var ContainerRegistryHelper = /** @class */ (function () { return [3 /*break*/, 4]; case 3: err_3 = _a.sent(); - toolHelper.writeError("Failed to push image \"" + imageToPush + "\" to ACR. Error: " + err_3.message); + toolHelper.writeError("Failed to push image \"" + imageToPush + "\" to Container Registry. Error: " + err_3.message); throw err_3; case 4: return [2 /*return*/]; } diff --git a/dist/licenses.tx b/dist/licenses.tx new file mode 100644 index 00000000..d7718469 --- /dev/null +++ b/dist/licenses.tx @@ -0,0 +1,97 @@ +@actions/core +MIT +The MIT License (MIT) + +Copyright 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@actions/exec +MIT +The MIT License (MIT) + +Copyright 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@actions/http-client +MIT +Actions Http Client for Node.js + +Copyright (c) GitHub, Inc. + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +@actions/io +MIT +The MIT License (MIT) + +Copyright 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +tunnel +MIT +The MIT License (MIT) + +Copyright (c) 2012 Koichi Kobayashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +uuid +MIT +The MIT License (MIT) + +Copyright (c) 2010-2020 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 18d1a4e318cd8631e6990f143b4d3999623e57b3 Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 17 Oct 2023 00:41:11 -0700 Subject: [PATCH 40/42] Fix docker login command --- dist/index.js | 2 +- src/ContainerRegistryHelper.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index a9fdc12b..ca53e666 100644 --- a/dist/index.js +++ b/dist/index.js @@ -5385,7 +5385,7 @@ var ContainerRegistryHelper = /** @class */ (function () { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, util.execute("docker login --username " + registryUsername + " --password " + registryPassword + " " + registryUrl, [], Buffer.from(registryPassword))]; + return [4 /*yield*/, util.execute("docker login --password-stdin --username " + registryUsername + " " + registryUrl, [], Buffer.from(registryPassword))]; case 2: _a.sent(); return [3 /*break*/, 4]; diff --git a/src/ContainerRegistryHelper.ts b/src/ContainerRegistryHelper.ts index 43797347..e6f7a136 100644 --- a/src/ContainerRegistryHelper.ts +++ b/src/ContainerRegistryHelper.ts @@ -15,7 +15,7 @@ export class ContainerRegistryHelper { public async loginContainerRegistryWithUsernamePassword(registryUrl: string, registryUsername: string, registryPassword: string) { toolHelper.writeDebug(`Attempting to log in to Container Registry instance"${registryUrl}" with username and password credentials`); try { - await util.execute(`docker login --username ${registryUsername} --password ${registryPassword} ${registryUrl}`, [], Buffer.from(registryPassword)); + await util.execute(`docker login --password-stdin --username ${registryUsername} ${registryUrl}`, [], Buffer.from(registryPassword)); } catch (err) { toolHelper.writeError(`Failed to log in to Container Registry instance "${registryUrl}" with username and password credentials`); throw err; From ea4b3ed93a79679ffddd4e450e624100875b41bb Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 17 Oct 2023 10:34:13 -0700 Subject: [PATCH 41/42] Re-order container registry authentication --- azurecontainerapps.ts | 10 ++--- dist/index.js | 8 ++-- dist/licenses.tx | 97 ------------------------------------------- 3 files changed, 9 insertions(+), 106 deletions(-) delete mode 100644 dist/licenses.tx diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index ce861333..f905675f 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -21,16 +21,16 @@ export class azurecontainerapps { // Set up the resources required to deploy a Container App await this.setupResources(); + // If a Container Registry URL was provided, try to authenticate against it + if (!this.util.isNullOrEmpty(this.registryUrl)) { + await this.authenticateContainerRegistryAsync(); + } + // If an Azure Container Registry name was provided, try to authenticate against it if (!this.util.isNullOrEmpty(this.acrName)) { await this.authenticateAzureContainerRegistryAsync(); } - // If a Container Registry URL was provided, try to authenticate against it - if (!this.util.isNullOrEmpty(this.registryUrl)) { - await this.authenticateContainerRegistryAsync(); - } - // If the application source was provided, build a runnable application image from it if (!this.util.isNullOrEmpty(this.appSourcePath)) { await this.buildAndPushImageAsync(); diff --git a/dist/index.js b/dist/index.js index ca53e666..0c21e002 100644 --- a/dist/index.js +++ b/dist/index.js @@ -76,14 +76,14 @@ var azurecontainerapps = /** @class */ (function () { case 3: // Set up the resources required to deploy a Container App _a.sent(); - if (!!this.util.isNullOrEmpty(this.acrName)) return [3 /*break*/, 5]; - return [4 /*yield*/, this.authenticateAzureContainerRegistryAsync()]; + if (!!this.util.isNullOrEmpty(this.registryUrl)) return [3 /*break*/, 5]; + return [4 /*yield*/, this.authenticateContainerRegistryAsync()]; case 4: _a.sent(); _a.label = 5; case 5: - if (!!this.util.isNullOrEmpty(this.registryUrl)) return [3 /*break*/, 7]; - return [4 /*yield*/, this.authenticateContainerRegistryAsync()]; + if (!!this.util.isNullOrEmpty(this.acrName)) return [3 /*break*/, 7]; + return [4 /*yield*/, this.authenticateAzureContainerRegistryAsync()]; case 6: _a.sent(); _a.label = 7; diff --git a/dist/licenses.tx b/dist/licenses.tx deleted file mode 100644 index d7718469..00000000 --- a/dist/licenses.tx +++ /dev/null @@ -1,97 +0,0 @@ -@actions/core -MIT -The MIT License (MIT) - -Copyright 2019 GitHub - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -@actions/exec -MIT -The MIT License (MIT) - -Copyright 2019 GitHub - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -@actions/http-client -MIT -Actions Http Client for Node.js - -Copyright (c) GitHub, Inc. - -All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -@actions/io -MIT -The MIT License (MIT) - -Copyright 2019 GitHub - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -tunnel -MIT -The MIT License (MIT) - -Copyright (c) 2012 Koichi Kobayashi - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -uuid -MIT -The MIT License (MIT) - -Copyright (c) 2010-2020 Robert Kieffer and other contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From e5b0ef04e22bb90a589ab3de1fb2ab4343aeb5fd Mon Sep 17 00:00:00 2001 From: snehapar9 Date: Tue, 17 Oct 2023 12:59:50 -0700 Subject: [PATCH 42/42] Add space --- azurecontainerapps.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurecontainerapps.ts b/azurecontainerapps.ts index f905675f..5180aaf8 100644 --- a/azurecontainerapps.ts +++ b/azurecontainerapps.ts @@ -309,7 +309,7 @@ export class azurecontainerapps { */ private static async authenticateAzureContainerRegistryAsync() { this.registryUsername = this.toolHelper.getInput('acrUsername', false); - this.registryPassword= this.toolHelper.getInput('acrPassword', false); + this.registryPassword = this.toolHelper.getInput('acrPassword', false); this.registryUrl = `${this.acrName}.azurecr.io`; // Login to ACR if credentials were provided