mirror of
https://github.com/azure/login.git
synced 2026-03-13 18:17:09 -04:00
Compare commits
147 Commits
users/aksm
...
v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb79c773a3 | ||
|
|
aeb0c3630a | ||
|
|
2d38cb8921 | ||
|
|
3f2bf91b4d | ||
|
|
b5038826b1 | ||
|
|
45c3280904 | ||
|
|
165d6877fd | ||
|
|
1b07ea9bb5 | ||
|
|
7c3c862a28 | ||
|
|
40935f9fb5 | ||
|
|
34b958dce7 | ||
|
|
e3b217c21b | ||
|
|
63a40ddd73 | ||
|
|
ed5636a770 | ||
|
|
0431fbf166 | ||
|
|
4e0edd18ae | ||
|
|
8bf3bdeba9 | ||
|
|
a00376ee0f | ||
|
|
5906929b67 | ||
|
|
b998d5ad47 | ||
|
|
d6cc2c8f90 | ||
|
|
4bba28a7f2 | ||
|
|
bed977350c | ||
|
|
990b22f2bc | ||
|
|
a354f8d8e8 | ||
|
|
41a42cd279 | ||
|
|
ef30cd425f | ||
|
|
6cb3cd651b | ||
|
|
ddfe2f4c73 | ||
|
|
b1db778a6a | ||
|
|
3a00f07ef2 | ||
|
|
ae34beef25 | ||
|
|
13cc38b514 | ||
|
|
1fe46a2c7b | ||
|
|
db0f4c9c27 | ||
|
|
28c2e2b810 | ||
|
|
a93d25c485 | ||
|
|
5d3578bb81 | ||
|
|
5425855167 | ||
|
|
32bfcb11b1 | ||
|
|
4b9ec184bd | ||
|
|
50f8249ba7 | ||
|
|
28576d9764 | ||
|
|
fb7f28b20f | ||
|
|
e486cf5b9b | ||
|
|
96c02d96d3 | ||
|
|
2402d47c47 | ||
|
|
a8ef87c8c0 | ||
|
|
df710979c3 | ||
|
|
7636f25e6b | ||
|
|
dc26b5279a | ||
|
|
9f262f3412 | ||
|
|
e3e9acc64c | ||
|
|
ec00cae078 | ||
|
|
fe9a855b8d | ||
|
|
68184fbd5a | ||
|
|
cc70402281 | ||
|
|
642a43caaa | ||
|
|
6453efca84 | ||
|
|
e6ca011ab7 | ||
|
|
c4459aba85 | ||
|
|
c09ca4f217 | ||
|
|
4443ffd660 | ||
|
|
b4a959b8bd | ||
|
|
5d09f4d5ca | ||
|
|
14a755a4e2 | ||
|
|
11ff950770 | ||
|
|
980d0f57a2 | ||
|
|
819ac8d2a9 | ||
|
|
63b39ef8c4 | ||
|
|
e021afe0dc | ||
|
|
85f8f21203 | ||
|
|
827604025b | ||
|
|
06f50cc138 | ||
|
|
23801eadd7 | ||
|
|
8f2def4beb | ||
|
|
412f48d98e | ||
|
|
c02223cd62 | ||
|
|
84519181a8 | ||
|
|
db989b3060 | ||
|
|
276f50e2dc | ||
|
|
25454e5e2d | ||
|
|
0dd02392d7 | ||
|
|
aa88e1ccbd | ||
|
|
c8bf401503 | ||
|
|
37a47ac753 | ||
|
|
298eef0366 | ||
|
|
4799d94391 | ||
|
|
bd43696425 | ||
|
|
3e6f6e7d1b | ||
|
|
38942de1a5 | ||
|
|
151a993723 | ||
|
|
fd4c9019e3 | ||
|
|
6bc1b5ecb9 | ||
|
|
f8979b3393 | ||
|
|
7f56506e21 | ||
|
|
0cf07a0171 | ||
|
|
c9dca98403 | ||
|
|
177ab1c8df | ||
|
|
5dc2a74a43 | ||
|
|
852ef9dc86 | ||
|
|
92605228cd | ||
|
|
49a928a08c | ||
|
|
b65105a723 | ||
|
|
a0110a77ec | ||
|
|
ed5c47a214 | ||
|
|
0d0ee46f76 | ||
|
|
114a8ef99d | ||
|
|
a78820d812 | ||
|
|
490d296e28 | ||
|
|
1a2f091d94 | ||
|
|
c590679de3 | ||
|
|
b6d623b57e | ||
|
|
bbbe7da52a | ||
|
|
799fd51bc6 | ||
|
|
a9a1dcd2f7 | ||
|
|
e7b36a5753 | ||
|
|
7f6ed87d4a | ||
|
|
c6b99d2720 | ||
|
|
5de298368f | ||
|
|
1ab2192eba | ||
|
|
80970a8c03 | ||
|
|
2e97c69135 | ||
|
|
a614f3cbd0 | ||
|
|
3e306521aa | ||
|
|
56641ce573 | ||
|
|
0d0c4a32af | ||
|
|
14b73ca9b5 | ||
|
|
2e72d699b0 | ||
|
|
ff610a161c | ||
|
|
c72b9ad43b | ||
|
|
9584e50c92 | ||
|
|
d773655321 | ||
|
|
de36370b39 | ||
|
|
bb5ee3d98d | ||
|
|
aa362ff93f | ||
|
|
80b45a252f | ||
|
|
14ff6a1af1 | ||
|
|
4440d80620 | ||
|
|
e7b230d17a | ||
|
|
21f0955fe4 | ||
|
|
45f2ccef11 | ||
|
|
807bb60301 | ||
|
|
8ea3fa2ba0 | ||
|
|
0bf4fdc1f9 | ||
|
|
ee83f1dbb6 | ||
|
|
513cdfa020 |
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
@kaverma @kanika1894 @BALAGA-GAYATRI @pulkitaggarwl
|
||||
10
.github/ISSUE_TEMPLATE/bug-report-feature-request.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/bug-report-feature-request.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Bug Report / Feature Request
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: need-to-triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
92
.github/workflows/azure-login-canary.yml
vendored
Normal file
92
.github/workflows/azure-login-canary.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
#This workflow is used to test azure login action for CLI edge build. Visit, https://github.com/Azure/azure-cli#edge-builds for more details.
|
||||
|
||||
name: Run Azure Login Canary Test
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: ' 0 8 * * *'
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
jobs:
|
||||
az-login-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name : Check Az version before installing
|
||||
run: az --version
|
||||
|
||||
- name: Installing Az CLI Edge build
|
||||
run: |
|
||||
cd ../..
|
||||
CWD="$(pwd)"
|
||||
python3 -m venv canary-venv
|
||||
. canary-venv/bin/activate
|
||||
echo "***********activated virual environment**********"
|
||||
python3 -m pip install --upgrade pip
|
||||
echo "***************started installing cli edge build******************"
|
||||
pip3 install -q --upgrade --pre azure-cli --extra-index-url https://azurecliprod.blob.core.windows.net/edge --no-cache-dir --upgrade-strategy=eager
|
||||
echo "***************installed cli Edge build*******************"
|
||||
echo "$CWD/canary-venv/bin" >> $GITHUB_PATH
|
||||
az --version
|
||||
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 'Az CLI login with subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
|
||||
- name: 'Az CLI login without subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
allow-no-subscriptions: true
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
|
||||
- name: 'Az CLI login with subscription OIDC'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENTID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANTID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
|
||||
- name: 'Az CLI login without subscription OIDC'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENTID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANTID }}
|
||||
allow-no-subscriptions: true
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
|
||||
slack-post-result:
|
||||
runs-on: ubuntu-latest
|
||||
# continue-on-error: true
|
||||
if: ${{ always() }}
|
||||
needs: [az-login-test]
|
||||
steps:
|
||||
- name: Create slack post
|
||||
id: slack_report
|
||||
run: |
|
||||
TITLE="Login action canary tests update - "
|
||||
DATEVAR=`date "+%d/%m/%YT%H:%M:%S"`
|
||||
TITLE="${TITLE}${DATEVAR}"
|
||||
REPORT="${TITLE}\r\nLink to run - https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\r\n"
|
||||
RUN_URL="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
|
||||
REPORT="${REPORT}\r\n"
|
||||
if [ ${{needs.az-login-test.result}} == 'success' ]; then REPORT="${REPORT}\r\n|✅|<${RUN_URL}|az-login-test>"; else REPORT="${REPORT}\r\n|❌|<${RUN_URL}|az-login-test>"; fi
|
||||
echo "report=$REPORT" >> $GITHUB_OUTPUT
|
||||
- name: Post to slack
|
||||
shell: bash
|
||||
run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}}
|
||||
|
||||
129
.github/workflows/azure-login-integration-tests.yml
vendored
Normal file
129
.github/workflows/azure-login-integration-tests.yml
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
name: Run Azure Login Integration Tests
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 */3 * * *'
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
|
||||
az-login-test-non-oidc:
|
||||
runs-on: ubuntu-latest
|
||||
# continue-on-error: true
|
||||
steps:
|
||||
- name: 'Az CLI login with subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: 'Az CLI login without subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
allow-no-subscriptions: true
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
|
||||
- name: 'Azure PowerShell login with subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- uses: azure/powershell@v1
|
||||
with:
|
||||
inlineScript: "(Get-AzContext).Environment.Name"
|
||||
azPSVersion: "latest"
|
||||
|
||||
- name: 'Azure PowerShell login without subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{secrets.AZURE_CREDENTIALS}}
|
||||
enable-AzPSSession: true
|
||||
allow-no-subscriptions: true
|
||||
|
||||
- uses: azure/powershell@v1
|
||||
with:
|
||||
inlineScript: "(Get-AzContext).Environment.Name"
|
||||
azPSVersion: "latest"
|
||||
|
||||
az-login-test-oidc:
|
||||
runs-on: ubuntu-latest
|
||||
# continue-on-error: true
|
||||
steps:
|
||||
- name: 'Az CLI login with subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENTID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANTID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: 'Az CLI login without subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENTID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANTID }}
|
||||
allow-no-subscriptions: true
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
|
||||
- name: 'Azure PowerShell login with subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENTID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANTID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- uses: azure/powershell@v1
|
||||
with:
|
||||
inlineScript: "(Get-AzContext).Environment.Name"
|
||||
azPSVersion: "latest"
|
||||
|
||||
- name: 'Azure PowerShell login without subscription'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENTID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANTID }}
|
||||
enable-AzPSSession: true
|
||||
allow-no-subscriptions: true
|
||||
|
||||
- uses: azure/powershell@v1
|
||||
with:
|
||||
inlineScript: "(Get-AzContext).Environment.Name"
|
||||
azPSVersion: "latest"
|
||||
|
||||
slack-post-result:
|
||||
runs-on: ubuntu-latest
|
||||
# continue-on-error: true
|
||||
if: ${{ always() }}
|
||||
needs: [az-login-test-non-oidc, az-login-test-oidc]
|
||||
steps:
|
||||
- name: Create slack post
|
||||
id: slack_report
|
||||
run: |
|
||||
TITLE="Login action OIDC flow tests update - "
|
||||
DATEVAR=`date "+%d/%m/%YT%H:%M:%S"`
|
||||
TITLE="${TITLE}${DATEVAR}"
|
||||
REPORT="${TITLE}\r\nLink to run - https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\r\n"
|
||||
RUN_URL="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
|
||||
REPORT="${REPORT}\r\n"
|
||||
if [ ${{needs.az-login-test-non-oidc.result}} == 'success' ]; then REPORT="${REPORT}\r\n|✅|<${RUN_URL}|az-login-test-non-oidc>"; else REPORT="${REPORT}\r\n|❌|<${RUN_URL}|az-login-test-non-oidc>"; fi
|
||||
if [ ${{needs.az-login-test-oidc.result}} == 'success' ]; then REPORT="${REPORT}\r\n|✅|<${RUN_URL}|az-login-test-oidc>"; else REPORT="${REPORT}\r\n|❌|<${RUN_URL}|az-login-test-oidc>"; fi
|
||||
echo "report=$REPORT" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Post to slack
|
||||
shell: bash
|
||||
run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}}
|
||||
368
.github/workflows/azure-login-negative.yml
vendored
Normal file
368
.github/workflows/azure-login-negative.yml
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
name: Azure Login Action Negative Test
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
PermissionTest:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: Automation test
|
||||
|
||||
steps:
|
||||
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Login with individual parameters
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
|
||||
# subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
id: cli_3
|
||||
continue-on-error: true
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.cli_3.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
id: ps_3
|
||||
continue-on-error: true
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
(Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
(Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG'
|
||||
(Get-AzVM).Count -gt 0
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.ps_3.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
ParameterTest:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: Automation test
|
||||
|
||||
steps:
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Login with creds, missing parameters in creds
|
||||
id: login_4
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP3_NO_Secret}}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_4.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with creds, wrong keys
|
||||
id: login_5
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP4_Wrong_Key}}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_5.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with creds, no creds or individual parameters
|
||||
id: login_6
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_6.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with individual parameters, only client-id, no tenant-id, subscription-id
|
||||
id: login_7
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_7.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with individual parameters, only tenant-id, subscription-id, no client-id
|
||||
id: login_8
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_8.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with creds, disable ps session
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
enable-AzPSSession: false
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
id: ps_8
|
||||
continue-on-error: true
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
(Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
(Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG'
|
||||
(Get-AzVM).Count -gt 0
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.ps_8.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with creds, wrong boolean value
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
enable-AzPSSession: notboolean
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
id: ps_9
|
||||
continue-on-error: true
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
(Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
(Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG'
|
||||
(Get-AzVM).Count -gt 0
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.ps_9.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with individual parameters, with a wrong audience
|
||||
id: login_10
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
|
||||
audience: "https://github.com/actions"
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_10.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with tenant-level account, without allow-no-subscriptions
|
||||
id: login_11
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_11.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
# SP1 is ignored and SP2 will be used for login, but it will fail since SP2 has no access to the given subscription
|
||||
- name: Login with both creds and individual parameters
|
||||
id: login_12
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_12.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login by OIDC with all info in creds
|
||||
id: login_13
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP2}}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_13.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with individual parameters, no subscription-id, no allow-no-subscriptions
|
||||
id: login_14
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_14.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
- name: Login with creds, no subscription-id, no allow-no-subscriptions
|
||||
id: login_15
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
creds: '{"clientId":"${{ secrets.OIDC_SP2_CLIENT_ID }}","clientSecret":"${{ secrets.SP2_CLIENT_SECRET }}","tenantId":"${{ secrets.OIDC_SP2_TENANT_ID }}"}'
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_15.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
|
||||
VMTest:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [self_linux, self_windows]
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: Automation test
|
||||
|
||||
steps:
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Login with system-assigned managed identity without auth-type
|
||||
id: login_14
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
|
||||
- name: Check Last step failed
|
||||
if: steps.login_14.outcome == 'success'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Last action should fail but not. Please check it.')
|
||||
362
.github/workflows/azure-login-positive.yml
vendored
Normal file
362
.github/workflows/azure-login-positive.yml
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
name: Azure Login Action Positive Test
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
BasicTest:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, self_linux, self_windows]
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: Automation test
|
||||
|
||||
steps:
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: 'Run L0 tests'
|
||||
run: |
|
||||
npm run test
|
||||
|
||||
- name: Login with creds
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
|
||||
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with individual parameters
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.SP1_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.SP1_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.SP1_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli again
|
||||
run: |
|
||||
az account show --output none
|
||||
|
||||
- name: Run Azure PowerShell again
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with explicit auth-type
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
auth-type: SERVICE_PRINCIPAL
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
|
||||
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
ParameterTest:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: Automation test
|
||||
|
||||
steps:
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Login with creds, disable ps session
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
enable-AzPSSession: false
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Login with creds, wrong boolean value
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
enable-AzPSSession: notboolean
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Login with creds, allow no subscription
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{secrets.SP1}}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
|
||||
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with individual parameters, allow no subscription
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.SP1_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.SP1_TENANT_ID}}
|
||||
subscription-id: ${{ secrets.SP1_SUBSCRIPTION_ID }}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli again
|
||||
run: |
|
||||
az account show --output none
|
||||
|
||||
- name: Run Azure PowerShell again
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with individual parameters, no subscription, allow no subscription
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
shell: pwsh
|
||||
run: |
|
||||
$checkResult = (az account list --output json | ConvertFrom-Json).Count -eq 2
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext -ListAvailable).Count -eq 2
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with creds, no subscription, allow no subscription
|
||||
uses: ./
|
||||
with:
|
||||
creds: '{"clientId":"${{ secrets.OIDC_SP2_CLIENT_ID }}","clientSecret":"${{ secrets.SP2_CLIENT_SECRET }}","tenantId":"${{ secrets.OIDC_SP2_TENANT_ID }}"}'
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
VMTest:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [self_linux, self_windows]
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: Automation test
|
||||
|
||||
steps:
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Login with system-assigned managed identity, no subscription-id
|
||||
uses: ./
|
||||
with:
|
||||
auth-type: IDENTITY
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with system-assigned managed identity, with subscription id
|
||||
uses: ./
|
||||
with:
|
||||
auth-type: IDENTITY
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
|
||||
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with tenant-level user-assigned managed identity with allow-no-subscriptions
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.UMI2_CLIENT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
auth-type: IDENTITY
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
- name: Login with user-assigned managed identity, subscription-id
|
||||
uses: ./
|
||||
with:
|
||||
client-id: ${{ secrets.UMI1_CLIENT_ID }}
|
||||
subscription-id: ${{ secrets.UMI1_SUBSCRIPTION_ID }}
|
||||
auth-type: IDENTITY
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Azure Cli
|
||||
run: |
|
||||
az account show --output none
|
||||
az group show --name GitHubAction_CI_RG --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
|
||||
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
|
||||
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
|
||||
if(-not $checkResult){
|
||||
throw "Not all checks passed!"
|
||||
}
|
||||
|
||||
71
.github/workflows/azure-login-pr-check.yml
vendored
Normal file
71
.github/workflows/azure-login-pr-check.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: pr-check
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
branches:
|
||||
- master
|
||||
- 'releases/*'
|
||||
jobs:
|
||||
az-login-test:
|
||||
environment: Automation test
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout from PR branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
# Using 16.x version as an example
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: installing node_modules
|
||||
run: npm install
|
||||
|
||||
- name: Build GitHub Action
|
||||
run: npm run build
|
||||
|
||||
- name: 'Az CLI login with subscription'
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
az vm list --output none
|
||||
|
||||
- name: 'Az CLI login without subscription'
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS_NO_SUB }}
|
||||
allow-no-subscriptions: true
|
||||
|
||||
- run: |
|
||||
az account show --output none
|
||||
# az vm list --output none
|
||||
|
||||
- name: 'Azure PowerShell login with subscription'
|
||||
uses: ./
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- uses: azure/powershell@v1
|
||||
with:
|
||||
inlineScript: "(Get-AzContext).Environment.Name"
|
||||
azPSVersion: "latest"
|
||||
|
||||
# - name: 'Azure PowerShell login without subscription'
|
||||
# uses: ./
|
||||
# with:
|
||||
# creds: ${{secrets.AZURE_CREDENTIALS_NO_SUB}}
|
||||
# enable-AzPSSession: true
|
||||
# allow-no-subscriptions: true
|
||||
|
||||
# - uses: azure/powershell@v1
|
||||
# with:
|
||||
# inlineScript: "Get-AzContext"
|
||||
# azPSVersion: "latest"
|
||||
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -1,3 +1,5 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
@@ -16,7 +18,12 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Node.js 16.x for GitHub Action
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
|
||||
22
.github/workflows/codeql.yml
vendored
22
.github/workflows/codeql.yml
vendored
@@ -14,28 +14,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: javascript
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -49,4 +39,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
48
.github/workflows/defaultLabels.yml
vendored
Normal file
48
.github/workflows/defaultLabels.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: setting-default-labels
|
||||
|
||||
# Controls when the action will run.
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0/3 * * *"
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
|
||||
- uses: actions/stale@v8
|
||||
name: Setting issue as idle
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
|
||||
stale-issue-label: 'idle'
|
||||
days-before-stale: 14
|
||||
days-before-close: -1
|
||||
operations-per-run: 100
|
||||
exempt-issue-labels: 'backlog'
|
||||
|
||||
- uses: actions/stale@v8
|
||||
name: Setting PR as idle
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
|
||||
stale-pr-label: 'idle'
|
||||
days-before-stale: 14
|
||||
days-before-close: -1
|
||||
operations-per-run: 100
|
||||
|
||||
- uses: actions/stale@v8
|
||||
name: Close issue with no feedback for 20 days
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
close-issue-message: 'This issue has been labeled as `needs-author-feedback` for 20 days with no activity. We will close it for now. If you require additional assistance, please feel free to reopen it with the required information.'
|
||||
days-before-stale: -1
|
||||
days-before-close: 20
|
||||
stale-issue-label: 'needs-author-feedback'
|
||||
only-issue-labels: 'needs-author-feedback'
|
||||
close-issue-reason: 'completed'
|
||||
operations-per-run: 100
|
||||
18
.github/workflows/markdownlint.yml
vendored
Normal file
18
.github/workflows/markdownlint.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Markdownlint
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
- name: Run Markdownlint
|
||||
run: |
|
||||
npm i -g markdownlint-cli2
|
||||
markdownlint-cli2 "**/*.md"
|
||||
371
.gitignore
vendored
371
.gitignore
vendored
@@ -1,330 +1,99 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
# Dependency directory
|
||||
node_modules
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
# Dependency directories
|
||||
jspm_packages/
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
# OS metadata
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
# Ignore built ts files
|
||||
__tests__/runner/*
|
||||
lib/**/*
|
||||
9
.markdownlint-cli2.jsonc
Normal file
9
.markdownlint-cli2.jsonc
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"config": {
|
||||
"default": true,
|
||||
"MD013": false
|
||||
},
|
||||
"ignores": [
|
||||
"SECURITY.md"
|
||||
]
|
||||
}
|
||||
619
README.md
619
README.md
@@ -1,54 +1,531 @@
|
||||
# GitHub Actions for deploying to Azure
|
||||
# Azure Login Action
|
||||
|
||||
## Automate your GitHub workflows using Azure Actions
|
||||
- [Azure Login Action](#azure-login-action)
|
||||
- [Input Parameters](#input-parameters)
|
||||
- [`client-id`](#client-id)
|
||||
- [`subscription-id`](#subscription-id)
|
||||
- [`tenant-id`](#tenant-id)
|
||||
- [`creds`](#creds)
|
||||
- [`enable-AzPSSession`](#enable-azpssession)
|
||||
- [`environment`](#environment)
|
||||
- [`allow-no-subscriptions`](#allow-no-subscriptions)
|
||||
- [`audience`](#audience)
|
||||
- [`auth-type`](#auth-type)
|
||||
- [Workflow Examples](#workflow-examples)
|
||||
- [Login With OpenID Connect (OIDC) \[Recommended\]](#login-with-openid-connect-oidc-recommended)
|
||||
- [Login With a Service Principal Secret](#login-with-a-service-principal-secret)
|
||||
- [Login With System-assigned Managed Identity](#login-with-system-assigned-managed-identity)
|
||||
- [Login With User-assigned Managed Identity](#login-with-user-assigned-managed-identity)
|
||||
- [Login to Azure US Government cloud](#login-to-azure-us-government-cloud)
|
||||
- [Login to Azure Stack Hub](#login-to-azure-stack-hub)
|
||||
- [Login without subscription](#login-without-subscription)
|
||||
- [Az logout and security hardening](#az-logout-and-security-hardening)
|
||||
- [Azure CLI dependency](#azure-cli-dependency)
|
||||
- [Reference](#reference)
|
||||
- [GitHub Action](#github-action)
|
||||
- [GitHub Actions for deploying to Azure](#github-actions-for-deploying-to-azure)
|
||||
- [Azure CLI Action](#azure-cli-action)
|
||||
- [Azure PowerShell Action](#azure-powershell-action)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
[GitHub Actions](https://help.github.com/en/articles/about-github-actions) gives you the flexibility to build an automated software development lifecycle workflow.
|
||||
With the [Azure Login Action](https://github.com/Azure/login), you can login to Azure and run [Azure CLI](https://learn.microsoft.com/cli/azure/) and [Azure PowerShell](https://learn.microsoft.com/powershell/azure) scripts.
|
||||
|
||||
With [GitHub Actions for Azure](https://github.com/Azure/actions/) you can create workflows that you can set up in your repository to build, test, package, release and **deploy** to Azure.
|
||||
Azure Login Action supports different ways of authentication with Azure.
|
||||
|
||||
NOTE: you must have write permissions to the repository in question. If you're using a sample repository from Microsoft, be sure to first fork the repository to your own GitHub account.
|
||||
- Login with OpenID Connect (OIDC)
|
||||
- Login with a Service Principal Secret
|
||||
- Login with System-assigned Managed Identity
|
||||
- Login with User-assigned Managed Identity
|
||||
|
||||
Get started today with a [free Azure account](https://azure.com/free/open-source).
|
||||
**We recommend using OIDC based authentication for increased security.**
|
||||
|
||||
# GitHub Action for Azure Login
|
||||
> [!WARNING]
|
||||
> By default, the output of Azure CLI commands is printed to the stdout stream. Without redirecting the stdout stream, contents in it will be stored in the build log of the action. Configure Azure CLI to _not_ show output in the console screen or print in the log by setting the environment variable `AZURE_CORE_OUTPUT` to `none`. If you need the output of a specific command, override the default setting using the argument `--output` with your format of choice. For more information on output options with the Azure CLI, see [Format output](https://learn.microsoft.com/cli/azure/format-output-azure-cli).
|
||||
|
||||
With the Azure login Action, you can automate your workflow to do an Azure login using [Azure service principal](https://docs.microsoft.com/azure/active-directory/develop/app-objects-and-service-principals) and run Azure CLI and Azure PowerShell scripts.
|
||||
** **
|
||||
|
||||
By default, the action only logs in with the Azure CLI (using the `az login` command). To log in with the Az PowerShell module, set `enable-AzPSSession` to true.
|
||||
> [!WARNING]
|
||||
> Avoid using managed identity login on self-hosted runners in public repositories. Managed identities enable secure authentication with Azure resources and obtain Microsoft Entra ID tokens without the need for explicit credential management. Any user can open pull requests against your repository and access your self-hosted runners without credentials. See more details in [self-hosted runner security](https://docs.github.com/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#self-hosted-runner-security).
|
||||
|
||||
This repository contains GitHub Action for [Azure Login](https://github.com/Azure/login/blob/master/action.yml).
|
||||
## Input Parameters
|
||||
|
||||
## Sample workflow that uses Azure login action to run az cli
|
||||
|Parameter Name|Required?|Type|Default Value|Description|
|
||||
|---|---|---|---|---|
|
||||
|client-id|false|UUID||the client id of a service principal or a user-assigned managed identity|
|
||||
|subscription-id|false|UUID||the login subscription id|
|
||||
|tenant-id|false|UUID||the login tenant id|
|
||||
|creds|false|string||a json string for login with an Azure service principal|
|
||||
|enable-AzPSSession|false|boolean|false|if Azure PowerShell login is enabled|
|
||||
|environment|false|string|azurecloud|the Azure Cloud environment|
|
||||
|allow-no-subscriptions|false|boolean|false|if login without subscription is allowed|
|
||||
|audience|false|string|api://AzureADTokenExchange|the audience to get the JWT ID token from GitHub OIDC provider|
|
||||
|auth-type|false|string|SERVICE_PRINCIPAL|the auth type|
|
||||
|
||||
### `client-id`
|
||||
|
||||
The input parameter `client-id` specifies the login client id. It could be the client id of a service principal or a user-assigned managed identity.
|
||||
|
||||
It's used in login with OpenID Connect (OIDC) and user-assigned managed identity.
|
||||
|
||||
It's better to create a GitHub Action secret for this parameter when using it. Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).
|
||||
|
||||
Refer to [Login With OpenID Connect (OIDC)](#login-with-openid-connect-oidc-recommended) and [Login With User-assigned Managed Identity](#login-with-user-assigned-managed-identity) for its usage.
|
||||
|
||||
### `subscription-id`
|
||||
|
||||
The input parameter `subscription-id` specifies the login subscription id.
|
||||
|
||||
It's used in login with OpenID Connect (OIDC) and managed identity.
|
||||
|
||||
It's better to create a GitHub Action secret for this parameter when using it. Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).
|
||||
|
||||
Refer to [Login With OpenID Connect (OIDC)](#login-with-openid-connect-oidc-recommended), [Login With System-assigned Managed Identity](#login-with-system-assigned-managed-identity) and [Login With User-assigned Managed Identity](#login-with-user-assigned-managed-identity) for its usage.
|
||||
|
||||
### `tenant-id`
|
||||
|
||||
The input parameter `tenant-id` specifies the login tenant id.
|
||||
|
||||
It's used in login with OpenID Connect (OIDC) and managed identity.
|
||||
|
||||
It's better to create a GitHub Action secret for this parameter when using it. Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).
|
||||
|
||||
Refer to [Login With OpenID Connect (OIDC)](#login-with-openid-connect-oidc-recommended), [Login With System-assigned Managed Identity](#login-with-system-assigned-managed-identity) and [Login With User-assigned Managed Identity](#login-with-user-assigned-managed-identity) for its usage.
|
||||
|
||||
### `creds`
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If one of `client-id` and `subscription-id` and `tenant-id` is set, `creds` will be ignored.
|
||||
|
||||
The value of input parameter `creds` is a string in json format, including the following values:
|
||||
|
||||
```json
|
||||
{
|
||||
"clientSecret": "******",
|
||||
"subscriptionId": "******",
|
||||
"tenantId": "******",
|
||||
"clientId": "******"
|
||||
}
|
||||
```
|
||||
|
||||
It's used in login with an Azure service principal.
|
||||
|
||||
It's better to create a GitHub Action secret for this parameter when using it. Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).
|
||||
|
||||
Refer to [Login With a Service Principal Secret](#login-with-a-service-principal-secret) for its usage.
|
||||
|
||||
### `enable-AzPSSession`
|
||||
|
||||
By default, Azure Login Action only logs in with the Azure CLI. To log in with the Azure PowerShell module, set `enable-AzPSSession` to true.
|
||||
|
||||
Refer to [Login With OpenID Connect (OIDC)](#login-with-openid-connect-oidc-recommended) for its usage.
|
||||
|
||||
### `environment`
|
||||
|
||||
By default, Azure Login Action connects to the Azure Public Cloud (`AzureCloud`).
|
||||
|
||||
To login to one of the Azure Government clouds or Azure Stack, set `environment` to one of the supported values `AzureUSGovernment` or `AzureChinaCloud` or `AzureGermanCloud` or `AzureStack`.
|
||||
|
||||
Refer to [Login to Azure US Government cloud](#login-to-azure-us-government-cloud) for its usage.
|
||||
|
||||
### `allow-no-subscriptions`
|
||||
|
||||
By default, Azure Login Action requires a `subscription-id`. To login to Azure tenants without any subscriptions, set `allow-no-subscriptions` to true.
|
||||
|
||||
Refer to [Login without subscription](#login-without-subscription) for its usage.
|
||||
|
||||
### `audience`
|
||||
|
||||
Azure Login Action gets the JWT ID token from GitHub OIDC provider when login with OIDC. The default `audience` is `api://AzureADTokenExchange`. Users can specify a custom `audience`.
|
||||
|
||||
### `auth-type`
|
||||
|
||||
The input parameter `auth-type` specifies the type of authentication. The default value is `SERVICE_PRINCIPAL`. Users can specify it as `IDENTITY` for login with Managed Identity.
|
||||
|
||||
Refer to [Login With System-assigned Managed Identity](#login-with-system-assigned-managed-identity) and [Login With User-assigned Managed Identity](#login-with-user-assigned-managed-identity) for its usage.
|
||||
|
||||
## Workflow Examples
|
||||
|
||||
### Login With OpenID Connect (OIDC) [Recommended]
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - Ensure the CLI version is 2.30 or above to support login with OIDC.
|
||||
> - By default, Azure access tokens issued during OIDC based login could have limited validity. Azure access token issued by Service Principal is expected to have an expiration of 1 hour by default. And with Managed Identities, it would be 24 hours. This expiration time is further configurable in Azure. Refer to [access-token lifetime](https://learn.microsoft.com/azure/active-directory/develop/access-tokens#access-token-lifetime) for more details.
|
||||
|
||||
Before you use Azure Login Action with OIDC, you need to configure a federated identity credential on an service principal or a managed identity.
|
||||
|
||||
- Prepare a service principal for Login with OIDC
|
||||
- [Create a service principal and assign a role to it](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal)
|
||||
- [Configure a federated identity credential on an service principal](https://learn.microsoft.com/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#github-actions)
|
||||
- Prepare a user-assigned managed identity for Login with OIDC
|
||||
- [Create a user-assigned managed identity and assign a role to it](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-manage-user-assigned-managed-identities?pivots=identity-mi-methods-azp#create-a-user-assigned-managed-identity)
|
||||
- [Configure a federated identity credential on a user-assigned managed identity](https://learn.microsoft.com/entra/workload-id/workload-identity-federation-create-trust-user-assigned-managed-identity?pivots=identity-wif-mi-methods-azp#github-actions-deploying-azure-resources)
|
||||
|
||||
After it, create GitHub Action secrets for following values: (Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).)
|
||||
|
||||
- AZURE_CLIENT_ID: the service principal client ID or user-assigned managed identity client ID
|
||||
- AZURE_SUBSCRIPTION_ID: the subscription ID
|
||||
- AZURE_TENANT_ID: the tenant ID
|
||||
|
||||
Now you can try the workflow to login with OIDC.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> In GitHub workflow, you should set `permissions:` with `id-token: write` at workflow level or job level based on whether the OIDC token is allowed be generated for all Jobs or a specific Job.
|
||||
|
||||
- **The workflow sample to only run Azure CLI**
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
name: Run Azure Login with OIDC
|
||||
on: [push]
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Azure login
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |
|
||||
az account show
|
||||
```
|
||||
|
||||
- **The workflow sample to run both Azure CLI and Azure PowerShell**
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
name: Run Azure Login with OIDC
|
||||
on: [push]
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Azure login
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |
|
||||
az account show
|
||||
|
||||
- name: Azure PowerShell script
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
Get-AzContext
|
||||
```
|
||||
|
||||
### Login With a Service Principal Secret
|
||||
|
||||
Before you login a service principal secret, you need to prepare a service principal with a secret.
|
||||
|
||||
- [Create a service principal and assign a role to it](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal)
|
||||
- [Create a new service principal client secret](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal#option-3-create-a-new-client-secret)
|
||||
|
||||
After it, create a GitHub Action secret `AZURE_CREDENTIALS` with the value like below: (Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).)
|
||||
|
||||
```json
|
||||
{
|
||||
"clientSecret": "******",
|
||||
"subscriptionId": "******",
|
||||
"tenantId": "******",
|
||||
"clientId": "******"
|
||||
}
|
||||
```
|
||||
|
||||
- clientSecret: the service principal client secret
|
||||
- subscriptionId: the subscription ID
|
||||
- tenantId: the tenant ID
|
||||
- clientId: the service principal client ID
|
||||
|
||||
Now you can try the workflow to login with a service principal secret.
|
||||
|
||||
- **The workflow sample to only run Azure CLI**
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: AzureLoginSample
|
||||
name: Run Azure Login With a Service Principal Secret
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
|
||||
- uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |
|
||||
az account show
|
||||
|
||||
- run: |
|
||||
az webapp list --query "[?state=='Running']"
|
||||
```
|
||||
|
||||
## Sample workflow that uses Azure login action to run Azure PowerShell
|
||||
- **The workflow sample to run both Azure CLI and Azure PowerShell**
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: AzurePowerShellSample
|
||||
name: Run Azure Login With a Service Principal Secret
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |
|
||||
az account show
|
||||
|
||||
- name: Azure PowerShell script
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
Get-AzWebApp
|
||||
```
|
||||
|
||||
If you want to pass subscription ID, tenant ID, client ID, and client secret as individual parameters instead of bundling them in a single JSON object to address the [security concerns](https://docs.github.com/actions/security-guides/encrypted-secrets), below snippet can help with the same.
|
||||
|
||||
```yaml
|
||||
- uses: Azure/login@v1
|
||||
with:
|
||||
creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'
|
||||
```
|
||||
|
||||
### Login With System-assigned Managed Identity
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> "Login With System-assigned Managed Identity" is only supported on GitHub self-hosted runners and the self-hosted runners need to be hosted by Azure virtual machines.
|
||||
|
||||
Before you login with system-assigned managed identity, you need to create an Azure virtual machine to host the GitHub self-hosted runner.
|
||||
|
||||
- Create an Azure virtual machine
|
||||
- [Create a Windows virtual machine](https://learn.microsoft.com/azure/virtual-machines/windows/quick-create-portal)
|
||||
- [Create a Linux virtual machine](https://learn.microsoft.com/azure/virtual-machines/linux/quick-create-portal?tabs=ubuntu)
|
||||
- [Configure system-assigned managed identity on the Azure virtual machine](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/qs-configure-portal-windows-vm#system-assigned-managed-identity)
|
||||
- Install required softwares on the Azure virtual machine
|
||||
- [Install PowerShell](https://learn.microsoft.com/powershell/scripting/install/installing-powershell)
|
||||
- [Install Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)
|
||||
- If you want to run Azure CLI Action, [Install Docker](https://docs.docker.com/engine/install/).
|
||||
- [Install Azure PowerShell](https://learn.microsoft.com/powershell/azure/install-azure-powershell)
|
||||
- [Configure the Azure virtual machine as a GitHub self-hosted runner](https://docs.github.com/actions/hosting-your-own-runners/managing-self-hosted-runners/adding-self-hosted-runners)
|
||||
|
||||
After it, create GitHub Action secrets for following values: (Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).)
|
||||
|
||||
- AZURE_SUBSCRIPTION_ID: the Subscription ID
|
||||
- AZURE_TENANT_ID: the Tenant ID
|
||||
|
||||
Now you can try the workflow to login with system-assigned managed identity.
|
||||
|
||||
- **The workflow sample to run both Azure CLI and Azure PowerShell**
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
name: Run Azure Login with System-assigned Managed Identity
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Azure login
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
auth-type: IDENTITY
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
# Azure CLI Action only supports linux self-hosted runners for now.
|
||||
# If you want to execute the Azure CLI script on a windows self-hosted runner, you can execute it directly in `run`.
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |
|
||||
az account show
|
||||
|
||||
- name: Azure PowerShell script
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
Get-AzContext
|
||||
Get-AzResourceGroup
|
||||
```
|
||||
|
||||
### Login With User-assigned Managed Identity
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> "Login With User-assigned Managed Identity" is only supported on GitHub self-hosted runners and the self-hosted runners need to be hosted by Azure virtual machines.
|
||||
|
||||
Before you login with User-assigned managed identity, you need to create an Azure virtual machine to host the GitHub self-hosted runner.
|
||||
|
||||
- Create an Azure virtual machine
|
||||
- [Create a Windows virtual machine](https://learn.microsoft.com/azure/virtual-machines/windows/quick-create-portal)
|
||||
- [Create a Linux virtual machine](https://learn.microsoft.com/azure/virtual-machines/linux/quick-create-portal?tabs=ubuntu)
|
||||
- [Create a user-assigned managed identity and assign a role to it](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-manage-user-assigned-managed-identities?pivots=identity-mi-methods-azp#create-a-user-assigned-managed-identity)
|
||||
- [Configure user-assigned managed identity on the Azure virtual machine](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/qs-configure-portal-windows-vm#user-assigned-managed-identity)
|
||||
- Install required softwares on the Azure virtual machine
|
||||
- [Install PowerShell](https://learn.microsoft.com/powershell/scripting/install/installing-powershell)
|
||||
- [Install Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)
|
||||
- If you want to run Azure CLI Action, [Install Docker](https://docs.docker.com/engine/install/).
|
||||
- [Install Azure PowerShell](https://learn.microsoft.com/powershell/azure/install-azure-powershell)
|
||||
- [Configure the Azure virtual machine as a GitHub self-hosted runner](https://docs.github.com/actions/hosting-your-own-runners/managing-self-hosted-runners/adding-self-hosted-runners)
|
||||
|
||||
After it, create GitHub Action secrets for following values: (Refer to [Using secrets in GitHub Actions](https://docs.github.com/actions/security-guides/using-secrets-in-github-actions).)
|
||||
|
||||
- AZURE_CLIENT_ID: the user-assigned managed identity client ID
|
||||
- AZURE_SUBSCRIPTION_ID: the subscription ID
|
||||
- AZURE_TENANT_ID: the tenant ID
|
||||
|
||||
Now you can try the workflow to login with user-assigned managed identity.
|
||||
|
||||
- **The workflow sample to run both Azure CLI and Azure PowerShell**
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
name: Run Azure Login with User-assigned Managed Identity
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Azure login
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
auth-type: IDENTITY
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
# Azure CLI Action only supports linux self-hosted runners for now.
|
||||
# If you want to execute the Azure CLI script on a windows self-hosted runner, you can execute it directly in `run`.
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |
|
||||
az account show
|
||||
|
||||
- name: Azure PowerShell script
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
Get-AzContext
|
||||
```
|
||||
|
||||
### Login to Azure US Government cloud
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: Login to Azure US Government cloud
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
environment: 'AzureUSGovernment'
|
||||
enable-AzPSSession: true
|
||||
|
||||
```
|
||||
|
||||
### Login to Azure Stack Hub
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: Login to Azure Stack Hub cloud
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
environment: 'AzureStack'
|
||||
enable-AzPSSession: true
|
||||
|
||||
```
|
||||
|
||||
Refer to the [Azure Stack Hub Login Action Tutorial](https://learn.microsoft.com/azure-stack/user/ci-cd-github-action-login-cli) for more detailed instructions.
|
||||
|
||||
### Login without subscription
|
||||
|
||||
Capability has been added to support access to tenants without subscriptions for both OIDC and non-OIDC. This can be useful to run tenant level commands, such as `az ad`. The action accepts an optional parameter `allow-no-subscriptions` which is `false` by default.
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: Run Azure Login without subscription
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -56,84 +533,86 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Login via Az module
|
||||
- name: Azure Login
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{secrets.AZURE_CREDENTIALS}}
|
||||
enable-AzPSSession: true
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Az CLI script
|
||||
run: |
|
||||
az webapp list --query "[?state=='Running']"
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |
|
||||
az account show
|
||||
|
||||
- name: Run Azure PowerShell script
|
||||
- name: Run Azure PowerShell
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: '3.1.0'
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
Get-AzVM -ResourceGroupName "ActionsDemo"
|
||||
Get-AzContext
|
||||
```
|
||||
|
||||
Refer to the [Azure PowerShell](https://github.com/azure/powershell) Github action to run your Azure PowerShell scripts.
|
||||
## Az logout and security hardening
|
||||
|
||||
## Configure deployment credentials:
|
||||
This action doesn't implement ```az logout``` by default at the end of execution. However, there is no way to tamper with the credentials or account information because the GitHub-hosted runner is on a VM that will get re-imaged for every customer run, which deletes everything. But if the runner is self-hosted (not provided by GitHub), it is recommended to manually log out at the end of the workflow, as shown below. More details on security of the runners can be found [here](https://docs.github.com/actions/learn-github-actions/security-hardening-for-github-actions#hardening-for-self-hosted-runners).
|
||||
|
||||
The previous sample workflows depend on a [secrets](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets) named `AZURE_CREDENTIALS` in your repository. The value of this secret is expected to be a JSON object that represents a service principal (an identifer for an application or process) that authenticates the workflow with Azure.
|
||||
> [!WARNING]
|
||||
> When using self hosted runners it is possible to have multiple runners on a single VM. Currently if your runners share a single user on the VM each runner will share the same credentials. That means in detail that each runner is able to change the permissions of another run. As a workaround we propose to use one single VM user per runner. If you start the runner as a service, do not forget to add the [optional user argument](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service#installing-the-service)
|
||||
|
||||
To function correctly, this service principal must be assigned the [Contributor]((https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#contributor)) role for the web app or the resource group that contains the web app.
|
||||
```yaml
|
||||
- name: Azure CLI script
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
inlineScript: |
|
||||
az logout
|
||||
az cache purge
|
||||
az account clear
|
||||
|
||||
The following steps describe how to create the service principal, assign the role, and create a secret in your repository with the resulting credentials.
|
||||
- name: Azure PowerShell script
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: "latest"
|
||||
inlineScript: |
|
||||
Clear-AzContext -Scope Process
|
||||
Clear-AzContext -Scope CurrentUser
|
||||
```
|
||||
|
||||
1. Open the Azure Cloud Shell at [https://shell.azure.com](https://shell.azure.com). You can alternately use the [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest) if you've installed it locally. (For more information on Cloud Shell, see the [Cloud Shell Overview](https://docs.microsoft.com/azure/cloud-shell/overview).)
|
||||
|
||||
2. Use the [az ad sp create-for-rbac](https://docs.microsoft.com/cli/azure/ad/sp?view=azure-cli-latest#az_ad_sp_create_for_rbac) command to create a service principal and assign a Contributor role:
|
||||
## Azure CLI dependency
|
||||
|
||||
```azurecli
|
||||
az ad sp create-for-rbac --name "{sp-name}" --sdk-auth --role contributor \
|
||||
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name}
|
||||
```
|
||||
Internally in this action, we use azure CLI and execute `az login` with the credentials provided through secrets. In order to validate the new azure CLI releases for this action, [canary test workflow](.github/workflows/azure-login-canary.yml) is written which will execute the action on [azure CLI's edge build](https://github.com/Azure/azure-cli#edge-builds) which will fail incase of any breaking change is being introduced in the new upcoming release. The test results can be posted on a slack or teams channel using the corresponding integrations. Incase of a failure, the concern will be raised to [azure-cli](https://github.com/Azure/azure-cli) for taking a necessary action and also the latest CLI installation will be postponed in [Runner VMs](https://github.com/actions/virtual-environments) as well for hosted runner to prevent the workflows failing due to the new CLI changes.
|
||||
|
||||
Replace the following:
|
||||
* `{sp-name}` with a suitable name for your service principal, such as the name of the app itself. The name must be unique within your organization.
|
||||
* `{subscription-id}` with the subscription you want to use
|
||||
* `{resource-group}` the resource group containing the web app.
|
||||
* `{app-name}` with the name of the web app.
|
||||
## Reference
|
||||
|
||||
This command invokes Azure Active Directory (via the `ad` part of the command) to create a service principal (via `sp`) specifically for [Role-Based Access Control (RBAC)](https://docs.microsoft.com/azure/role-based-access-control/overview) (via `create-for-rbac`).
|
||||
### GitHub Action
|
||||
|
||||
The `--role` argument specifies the permissions to grant to the service principal at the specified `--scope`. In this case, you grant the built-in [Contributor](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#contributor) role at the scope of the web app in the specified resource group in the specified subscription.
|
||||
[GitHub Actions](https://help.github.com/articles/about-github-actions) gives you the flexibility to build an automated software development lifecycle workflow.
|
||||
|
||||
If desired, you can omit the part of the scope starting with `/providers/...` to grant the service principal the Contributor role for the entire resource group:
|
||||
### GitHub Actions for deploying to Azure
|
||||
|
||||
```azurecli
|
||||
az ad sp create-for-rbac --name "{sp-name}" --sdk-auth --role contributor \
|
||||
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}
|
||||
```
|
||||
With [GitHub Actions for Azure](https://github.com/Azure/actions/), you can create workflows that you can set up in your repository to build, test, package, release and **deploy** to Azure.
|
||||
|
||||
For security purposes, however, it's always preferable to grant permissions at the most restrictive scope possible.
|
||||
### Azure CLI Action
|
||||
|
||||
3. When complete, the `az ad sp create-for-rbac` command displays JSON output in the following form (which is specified by the `--sdk-auth` argument):
|
||||
Refer to the [Azure CLI](https://github.com/azure/cli) GitHub Action to run your Azure CLI scripts.
|
||||
|
||||
```json
|
||||
{
|
||||
"clientId": "<GUID>",
|
||||
"clientSecret": "<GUID>",
|
||||
"subscriptionId": "<GUID>",
|
||||
"tenantId": "<GUID>",
|
||||
(...)
|
||||
}
|
||||
```
|
||||
### Azure PowerShell Action
|
||||
|
||||
4. In your repository, use **Add secret** to create a new secret named `AZURE_CREDENTIALS` (as shown in the example workflow), or using whatever name is in your workflow file.
|
||||
Refer to the [Azure PowerShell](https://github.com/azure/powershell) GitHub Action to run your Azure PowerShell scripts.
|
||||
|
||||
5. Paste the entire JSON object produced by the `az ad sp create-for-rbac` command as the secret value and save the secret.
|
||||
## Contributing
|
||||
|
||||
NOTE: to manage service principals created with `az ad sp create-for-rbac`, visit the [Azure portal](https://portal.azure.com), navigate to your Azure Active Directory, then select **Manage** > **App registrations** on the left-hand menu. Your service principal should appear in the list. Select a principal to navigate to its properties. You can also manage role assignments using the [az role assignment](https://docs.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest) command.
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
||||
the rights to use your contribution. For details, visit <https://cla.opensource.microsoft.com>.
|
||||
|
||||
# Contributing
|
||||
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
|
||||
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
|
||||
provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
||||
|
||||
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
272
__tests__/LoginConfig.test.ts
Normal file
272
__tests__/LoginConfig.test.ts
Normal file
@@ -0,0 +1,272 @@
|
||||
import { LoginConfig } from "../src/common/LoginConfig";
|
||||
|
||||
describe("LoginConfig Test", () => {
|
||||
|
||||
function setEnv(name: string, value: string) {
|
||||
process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] = value;
|
||||
}
|
||||
|
||||
function cleanEnv() {
|
||||
for (const envKey in process.env) {
|
||||
if (envKey.startsWith('INPUT_')) {
|
||||
delete process.env[envKey]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function testCreds(creds:any){
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'false');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
setEnv('creds', JSON.stringify(creds));
|
||||
let loginConfig = new LoginConfig();
|
||||
try{
|
||||
await loginConfig.initialize();
|
||||
throw new Error("The last step should fail.");
|
||||
}catch(error){
|
||||
expect(error.message.includes("Not all parameters are provided in 'creds'.")).toBeTruthy();
|
||||
}
|
||||
}
|
||||
|
||||
function testValidateWithErrorMessage(loginConfig:LoginConfig, errorMessage:string){
|
||||
try{
|
||||
loginConfig.validate();
|
||||
throw new Error("The last step should fail.");
|
||||
}catch(error){
|
||||
expect(error.message.includes(errorMessage)).toBeTruthy();
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
cleanEnv();
|
||||
});
|
||||
|
||||
test('initialize with creds, lack of clientId', async () => {
|
||||
let creds1 = {
|
||||
// 'clientId': 'client-id',
|
||||
'clientSecret': 'client-secret',
|
||||
'tenantId': 'tenant-id',
|
||||
'subscriptionId': 'subscription-id'
|
||||
}
|
||||
await testCreds(creds1);
|
||||
|
||||
});
|
||||
|
||||
test('initialize with creds, lack of clientSecret', async () => {
|
||||
let creds1 = {
|
||||
'clientId': 'client-id',
|
||||
// 'clientSecret': 'client-secret',
|
||||
'tenantId': 'tenant-id',
|
||||
'subscriptionId': 'subscription-id'
|
||||
}
|
||||
await testCreds(creds1);
|
||||
|
||||
});
|
||||
|
||||
test('initialize with creds, lack of tenantId', async () => {
|
||||
let creds1 = {
|
||||
'clientId': 'client-id',
|
||||
'clientSecret': 'client-secret',
|
||||
// 'tenantId': 'tenant-id',
|
||||
'subscriptionId': 'subscription-id'
|
||||
}
|
||||
await testCreds(creds1);
|
||||
|
||||
});
|
||||
|
||||
test('initialize with creds, lack of subscriptionId, but allowNoSubscriptionsLogin=true', async () => {
|
||||
let creds1 = {
|
||||
'clientId': 'client-id',
|
||||
'clientSecret': 'client-secret',
|
||||
'tenantId': 'tenant-id',
|
||||
// 'subscriptionId': 'subscription-id'
|
||||
}
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
setEnv('creds', JSON.stringify(creds1));
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
expect(loginConfig.environment).toBe("azurecloud");
|
||||
expect(loginConfig.enableAzPSSession).toBeTruthy();
|
||||
expect(loginConfig.allowNoSubscriptionsLogin).toBeTruthy();
|
||||
expect(loginConfig.authType).toBe("SERVICE_PRINCIPAL");
|
||||
expect(loginConfig.servicePrincipalId).toBe("client-id");
|
||||
expect(loginConfig.servicePrincipalSecret).toBe("client-secret");
|
||||
expect(loginConfig.tenantId).toBe("tenant-id");
|
||||
expect(loginConfig.subscriptionId).toBe("");
|
||||
});
|
||||
|
||||
test('initialize with creds', async () => {
|
||||
let creds = {
|
||||
'clientId': 'client-id',
|
||||
'clientSecret': 'client-secret',
|
||||
'tenantId': 'tenant-id',
|
||||
'subscriptionId': 'subscription-id'
|
||||
}
|
||||
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'false');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
setEnv('creds', JSON.stringify(creds));
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
expect(loginConfig.environment).toBe("azurecloud");
|
||||
expect(loginConfig.enableAzPSSession).toBeTruthy();
|
||||
expect(loginConfig.allowNoSubscriptionsLogin).toBeFalsy();
|
||||
expect(loginConfig.authType).toBe("SERVICE_PRINCIPAL");
|
||||
expect(loginConfig.servicePrincipalId).toBe("client-id");
|
||||
expect(loginConfig.servicePrincipalSecret).toBe("client-secret");
|
||||
expect(loginConfig.tenantId).toBe("tenant-id");
|
||||
expect(loginConfig.subscriptionId).toBe("subscription-id");
|
||||
});
|
||||
|
||||
test('initialize with individual parameters', async () => {
|
||||
setEnv('environment', 'azureusgovernment');
|
||||
setEnv('enable-AzPSSession', 'false');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
setEnv('tenant-id', 'tenant-id');
|
||||
setEnv('subscription-id', 'subscription-id');
|
||||
setEnv('client-id', 'client-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
expect(loginConfig.environment).toBe("azureusgovernment");
|
||||
expect(loginConfig.enableAzPSSession).toBeFalsy();
|
||||
expect(loginConfig.allowNoSubscriptionsLogin).toBeTruthy();
|
||||
expect(loginConfig.authType).toBe("SERVICE_PRINCIPAL");
|
||||
expect(loginConfig.servicePrincipalId).toBe("client-id");
|
||||
expect(loginConfig.tenantId).toBe("tenant-id");
|
||||
expect(loginConfig.subscriptionId).toBe("subscription-id");
|
||||
});
|
||||
|
||||
test('initialize with both creds and individual parameters', async () => {
|
||||
setEnv('environment', 'azureusgovernment');
|
||||
setEnv('enable-AzPSSession', 'false');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
|
||||
setEnv('tenant-id', 'tenant-id-aa');
|
||||
setEnv('subscription-id', 'subscription-id-aa');
|
||||
setEnv('client-id', 'client-id-aa');
|
||||
|
||||
let creds = {
|
||||
'clientId': 'client-id-bb',
|
||||
'clientSecret': 'client-secret-bb',
|
||||
'tenantId': 'tenant-id-bb',
|
||||
'subscriptionId': 'subscription-id-bb'
|
||||
}
|
||||
setEnv('creds', JSON.stringify(creds));
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
expect(loginConfig.environment).toBe("azureusgovernment");
|
||||
expect(loginConfig.enableAzPSSession).toBeFalsy();
|
||||
expect(loginConfig.allowNoSubscriptionsLogin).toBeTruthy();
|
||||
expect(loginConfig.authType).toBe("SERVICE_PRINCIPAL");
|
||||
expect(loginConfig.servicePrincipalId).toBe("client-id-aa");
|
||||
expect(loginConfig.servicePrincipalSecret).toBeNull();
|
||||
expect(loginConfig.tenantId).toBe("tenant-id-aa");
|
||||
expect(loginConfig.subscriptionId).toBe("subscription-id-aa");
|
||||
});
|
||||
|
||||
test('validate with wrong environment', async () => {
|
||||
setEnv('environment', 'aWrongCloud');
|
||||
setEnv('enable-AzPSSession', 'false');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
|
||||
setEnv('tenant-id', 'tenant-id');
|
||||
setEnv('subscription-id', 'subscription-id');
|
||||
setEnv('client-id', 'client-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
testValidateWithErrorMessage(loginConfig, "Unsupported value 'awrongcloud' for environment is passed.");
|
||||
});
|
||||
|
||||
test('validate with wrong authType', async () => {
|
||||
setEnv('environment', 'azurestack');
|
||||
setEnv('enable-AzPSSession', 'false');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE-PRINCIPAL');
|
||||
|
||||
setEnv('tenant-id', 'tenant-id');
|
||||
setEnv('subscription-id', 'subscription-id');
|
||||
setEnv('client-id', 'client-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
testValidateWithErrorMessage(loginConfig, "Unsupported value 'SERVICE-PRINCIPAL' for authentication type is passed.");
|
||||
});
|
||||
|
||||
test('validate with SERVICE_PRINCIPAL, lack of tenant id', async () => {
|
||||
setEnv('environment', 'azurestack');
|
||||
setEnv('enable-AzPSSession', 'false');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
|
||||
// setEnv('tenant-id', 'tenant-id');
|
||||
setEnv('subscription-id', 'subscription-id');
|
||||
setEnv('client-id', 'client-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
testValidateWithErrorMessage(loginConfig, "Using auth-type: SERVICE_PRINCIPAL. Not all values are present. Ensure 'client-id' and 'tenant-id' are supplied.");
|
||||
});
|
||||
|
||||
test('validate with SERVICE_PRINCIPAL, lack of client id', async () => {
|
||||
setEnv('environment', 'azurestack');
|
||||
setEnv('enable-AzPSSession', 'false');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
|
||||
setEnv('tenant-id', 'tenant-id');
|
||||
setEnv('subscription-id', 'subscription-id');
|
||||
// setEnv('client-id', 'client-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
testValidateWithErrorMessage(loginConfig, "Using auth-type: SERVICE_PRINCIPAL. Not all values are present. Ensure 'client-id' and 'tenant-id' are supplied.");
|
||||
});
|
||||
|
||||
test('validate without subscriptionId and allowNoSubscriptionsLogin=false', async () => {
|
||||
setEnv('environment', 'azurestack');
|
||||
setEnv('enable-AzPSSession', 'false');
|
||||
setEnv('allow-no-subscriptions', 'false');
|
||||
setEnv('auth-type', 'IDENTITY');
|
||||
|
||||
// setEnv('subscription-id', 'subscription-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
testValidateWithErrorMessage(loginConfig, "Ensure subscriptionId is supplied.");
|
||||
});
|
||||
|
||||
test('validate without subscriptionId and allowNoSubscriptionsLogin=true', async () => {
|
||||
setEnv('environment', 'azurestack');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'IDENTITY');
|
||||
|
||||
// setEnv('subscription-id', 'subscription-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
await loginConfig.initialize();
|
||||
loginConfig.validate();
|
||||
expect(loginConfig.environment).toBe("azurestack");
|
||||
expect(loginConfig.enableAzPSSession).toBeTruthy();
|
||||
expect(loginConfig.allowNoSubscriptionsLogin).toBeTruthy();
|
||||
expect(loginConfig.authType).toBe("IDENTITY");
|
||||
expect(loginConfig.servicePrincipalId).toBe("");
|
||||
expect(loginConfig.servicePrincipalSecret).toBeNull();
|
||||
expect(loginConfig.tenantId).toBe("");
|
||||
expect(loginConfig.subscriptionId).toBe("");
|
||||
});
|
||||
|
||||
});
|
||||
92
__tests__/PowerShell/AzPSLogin.test.ts
Normal file
92
__tests__/PowerShell/AzPSLogin.test.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import * as os from 'os';
|
||||
|
||||
import { AzPSLogin } from '../../src/PowerShell/AzPSLogin';
|
||||
import { LoginConfig } from '../../src/common/LoginConfig';
|
||||
import { AzPSConstants, AzPSUtils } from '../../src/PowerShell/AzPSUtils';
|
||||
|
||||
let azpsLogin: AzPSLogin;
|
||||
jest.setTimeout(30000);
|
||||
|
||||
beforeAll(() => {
|
||||
var loginConfig = new LoginConfig();
|
||||
loginConfig.servicePrincipalId = "servicePrincipalID";
|
||||
loginConfig.servicePrincipalSecret = "servicePrincipalSecret";
|
||||
loginConfig.tenantId = "tenantId";
|
||||
loginConfig.subscriptionId = "subscriptionId";
|
||||
azpsLogin = new AzPSLogin(loginConfig);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Testing login', () => {
|
||||
let loginSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
loginSpy = jest.spyOn(azpsLogin, 'login');
|
||||
});
|
||||
|
||||
test('ServicePrincipal login should pass', async () => {
|
||||
loginSpy.mockImplementationOnce(() => Promise.resolve());
|
||||
await azpsLogin.login();
|
||||
expect(loginSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing set module path', () => {
|
||||
test('setDefaultPSModulePath should work', () => {
|
||||
AzPSUtils.setPSModulePathForGitHubRunner();
|
||||
const runner: string = process.env.RUNNER_OS || os.type();
|
||||
if(runner.toLowerCase() === "linux"){
|
||||
expect(process.env.PSModulePath).toContain(AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX);
|
||||
}
|
||||
if(runner.toLowerCase().startsWith("windows")){
|
||||
expect(process.env.PSModulePath).toContain(AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Testing runPSScript', () => {
|
||||
test('Get PowerShell Version', async () => {
|
||||
let script = `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
$output['Success'] = $true
|
||||
$output['Result'] = $PSVersionTable.PSVersion.ToString()
|
||||
}
|
||||
catch {
|
||||
$output['Success'] = $false
|
||||
$output['Error'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
|
||||
let psVersion: string = await AzPSUtils.runPSScript(script);
|
||||
expect(psVersion === null).toBeFalsy();
|
||||
});
|
||||
|
||||
test('Get PowerShell Version with Wrong Name', async () => {
|
||||
let script = `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
$output['Success'] = $true
|
||||
$output['Result'] = $PSVersionTableWrongName.PSVersion.ToString()
|
||||
}
|
||||
catch {
|
||||
$output['Success'] = $false
|
||||
$output['Error'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
|
||||
try{
|
||||
await AzPSUtils.runPSScript(script);
|
||||
throw new Error("The last step should fail.");
|
||||
}catch(error){
|
||||
expect(error.message.includes("Azure PowerShell login failed with error: You cannot call a method on a null-valued expression.")).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
153
__tests__/PowerShell/AzPSScriptBuilder.test.ts
Normal file
153
__tests__/PowerShell/AzPSScriptBuilder.test.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import AzPSSCriptBuilder from "../../src/PowerShell/AzPSScriptBuilder";
|
||||
import { LoginConfig } from "../../src/common/LoginConfig";
|
||||
|
||||
describe("Getting AzLogin PS script", () => {
|
||||
|
||||
function setEnv(name: string, value: string) {
|
||||
process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] = value;
|
||||
}
|
||||
|
||||
function cleanEnv() {
|
||||
for (const envKey in process.env) {
|
||||
if (envKey.startsWith('INPUT_')) {
|
||||
delete process.env[envKey]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
cleanEnv();
|
||||
});
|
||||
|
||||
test('getImportLatestModuleScript', () => {
|
||||
expect(AzPSSCriptBuilder.getImportLatestModuleScript("TestModule")).toContain("(Get-Module -Name 'TestModule' -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1).Path");
|
||||
expect(AzPSSCriptBuilder.getImportLatestModuleScript("TestModule")).toContain("Import-Module -Name $latestModulePath");
|
||||
});
|
||||
|
||||
test('getAzPSLoginScript for SP+secret with allowNoSubscriptionsLogin=true', () => {
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
let creds = {
|
||||
'clientId': 'client-id',
|
||||
'clientSecret': "client-secret",
|
||||
'tenantId': 'tenant-id',
|
||||
'subscriptionId': 'subscription-id'
|
||||
}
|
||||
setEnv('creds', JSON.stringify(creds));
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
loginConfig.initialize();
|
||||
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
|
||||
expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-secret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential | out-null;")).toBeTruthy();
|
||||
expect(loginMethod).toBe('service principal with secret');
|
||||
});
|
||||
});
|
||||
|
||||
test('getAzPSLoginScript for SP+secret with allowNoSubscriptionsLogin=true, secret with single-quote', () => {
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
let creds = {
|
||||
'clientId': 'client-id',
|
||||
'clientSecret': "client-se'cret",
|
||||
'tenantId': 'tenant-id',
|
||||
'subscriptionId': 'subscription-id'
|
||||
}
|
||||
setEnv('creds', JSON.stringify(creds));
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
loginConfig.initialize();
|
||||
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
|
||||
expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-se''cret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential | out-null;")).toBeTruthy();
|
||||
expect(loginMethod).toBe('service principal with secret');
|
||||
});
|
||||
});
|
||||
|
||||
test('getAzPSLoginScript for SP+secret with allowNoSubscriptionsLogin=false', () => {
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'false'); // same as true
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
let creds = {
|
||||
'clientId': 'client-id',
|
||||
'clientSecret': 'client-secret',
|
||||
'tenantId': 'tenant-id',
|
||||
'subscriptionId': 'subscription-id'
|
||||
}
|
||||
setEnv('creds', JSON.stringify(creds));
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
loginConfig.initialize();
|
||||
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
|
||||
expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-secret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential | out-null;")).toBeTruthy();
|
||||
expect(loginMethod).toBe('service principal with secret');
|
||||
});
|
||||
});
|
||||
|
||||
test('getAzPSLoginScript for OIDC', () => {
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'false');
|
||||
setEnv('tenant-id', 'tenant-id');
|
||||
setEnv('subscription-id', 'subscription-id');
|
||||
setEnv('client-id', 'client-id');
|
||||
setEnv('auth-type', 'SERVICE_PRINCIPAL');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
loginConfig.initialize();
|
||||
jest.spyOn(loginConfig, 'getFederatedToken').mockImplementation(async () => {loginConfig.federatedToken = "fake-token";});
|
||||
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
|
||||
expect(loginScript.includes("Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -ApplicationId 'client-id' -FederatedToken 'fake-token' | out-null;")).toBeTruthy();
|
||||
expect(loginMethod).toBe('OIDC');
|
||||
});
|
||||
});
|
||||
|
||||
test('getAzPSLoginScript for System MI', () => {
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'false');
|
||||
setEnv('subscription-id', 'subscription-id');
|
||||
setEnv('auth-type', 'IDENTITY');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
loginConfig.initialize();
|
||||
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
|
||||
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -Subscription 'subscription-id' | out-null;")).toBeTruthy();
|
||||
expect(loginMethod).toBe('system-assigned managed identity');
|
||||
});
|
||||
});
|
||||
|
||||
test('getAzPSLoginScript for System MI without subscription id', () => {
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'false');
|
||||
// setEnv('subscription-id', 'subscription-id');
|
||||
setEnv('auth-type', 'IDENTITY');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
loginConfig.initialize();
|
||||
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
|
||||
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' | out-null;")).toBeTruthy();
|
||||
expect(loginMethod).toBe('system-assigned managed identity');
|
||||
});
|
||||
});
|
||||
|
||||
test('getAzPSLoginScript for user-assigned MI', () => {
|
||||
setEnv('environment', 'azurecloud');
|
||||
setEnv('enable-AzPSSession', 'true');
|
||||
setEnv('allow-no-subscriptions', 'true');
|
||||
setEnv('auth-type', 'IDENTITY');
|
||||
setEnv('client-id', 'client-id');
|
||||
|
||||
let loginConfig = new LoginConfig();
|
||||
loginConfig.initialize();
|
||||
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
|
||||
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -AccountId 'client-id' | out-null;")).toBeTruthy();
|
||||
expect(loginMethod).toBe('user-assigned managed identity');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
import { ServicePrincipalLogin } from '../../src/PowerShell/ServicePrincipalLogin';
|
||||
|
||||
jest.mock('../../src/PowerShell/Utilities/Utils');
|
||||
jest.mock('../../src/PowerShell/Utilities/PowerShellToolRunner');
|
||||
let spnlogin: ServicePrincipalLogin;
|
||||
|
||||
beforeAll(() => {
|
||||
spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId", false);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Testing initialize', () => {
|
||||
let initializeSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
initializeSpy = jest.spyOn(spnlogin, 'initialize');
|
||||
});
|
||||
test('ServicePrincipalLogin initialize should pass', async () => {
|
||||
await spnlogin.initialize();
|
||||
expect(initializeSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing login', () => {
|
||||
let loginSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
loginSpy = jest.spyOn(spnlogin, 'login');
|
||||
});
|
||||
test('ServicePrincipal login should pass', async () => {
|
||||
loginSpy.mockImplementationOnce(() => Promise.resolve());
|
||||
await spnlogin.login();
|
||||
expect(loginSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,25 +0,0 @@
|
||||
import ScriptBuilder from "../../../src/PowerShell/Utilities/ScriptBuilder";
|
||||
import Constants from "../../../src/PowerShell/Constants";
|
||||
|
||||
describe("Getting AzLogin PS script" , () => {
|
||||
const scheme = Constants.ServicePrincipal;
|
||||
let args: any = {
|
||||
servicePrincipalId: "service-principal-id",
|
||||
servicePrincipalKey: "service-principal-key",
|
||||
environment: "environment",
|
||||
scopeLevel: Constants.Subscription,
|
||||
subscriptionId: "subId",
|
||||
allowNoSubscriptionsLogin: true
|
||||
}
|
||||
|
||||
test("PS script should not set context while passing allowNoSubscriptionsLogin as true", () => {
|
||||
const loginScript = new ScriptBuilder().getAzPSLoginScript(scheme, "tenant-id", args);
|
||||
expect(loginScript.includes("Set-AzContext -SubscriptionId")).toBeFalsy();
|
||||
});
|
||||
|
||||
test("PS script should set context while passing allowNoSubscriptionsLogin as false", () => {
|
||||
args["allowNoSubscriptionsLogin"] = false;
|
||||
const loginScript = new ScriptBuilder().getAzPSLoginScript(scheme, "tenant-id", args);
|
||||
expect(loginScript.includes("Set-AzContext -SubscriptionId")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,45 +0,0 @@
|
||||
import Utils from '../../../src/PowerShell/Utilities/Utils';
|
||||
|
||||
const version: string = '9.0.0';
|
||||
const moduleName: string = 'az';
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Testing isValidVersion', () => {
|
||||
const validVersion: string = '1.2.4';
|
||||
const invalidVersion: string = 'a.bcd';
|
||||
|
||||
test('isValidVersion should be true', () => {
|
||||
expect(Utils.isValidVersion(validVersion)).toBeTruthy();
|
||||
});
|
||||
test('isValidVersion should be false', () => {
|
||||
expect(Utils.isValidVersion(invalidVersion)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing setPSModulePath', () => {
|
||||
test('PSModulePath with azPSVersion non-empty', () => {
|
||||
Utils.setPSModulePath(version);
|
||||
expect(process.env.PSModulePath).toContain(version);
|
||||
});
|
||||
test('PSModulePath with azPSVersion empty', () => {
|
||||
const prevPSModulePath = process.env.PSModulePath;
|
||||
Utils.setPSModulePath();
|
||||
expect(process.env.PSModulePath).not.toEqual(prevPSModulePath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing getLatestModule', () => {
|
||||
let getLatestModuleSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
getLatestModuleSpy = jest.spyOn(Utils, 'getLatestModule');
|
||||
});
|
||||
test('getLatestModule should pass', async () => {
|
||||
getLatestModuleSpy.mockImplementationOnce((_moduleName: string) => Promise.resolve(version));
|
||||
await Utils.getLatestModule(moduleName);
|
||||
expect(getLatestModuleSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
33
action.yml
33
action.yml
@@ -1,21 +1,44 @@
|
||||
# Login to Azure subscription
|
||||
name: 'Azure Login'
|
||||
description: 'Authenticate to Azure and run your Az CLI or Az PowerShell based Actions or scripts. github.com/Azure/Actions'
|
||||
description: 'Authenticate to Azure and run your Azure CLI or Azure PowerShell based actions or scripts.'
|
||||
inputs:
|
||||
creds:
|
||||
description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS'
|
||||
required: true
|
||||
required: false
|
||||
client-id:
|
||||
description: 'ClientId of the Azure Service principal created.'
|
||||
required: false
|
||||
tenant-id:
|
||||
description: 'TenantId of the Azure Service principal created.'
|
||||
required: false
|
||||
subscription-id:
|
||||
description: 'Azure subscriptionId'
|
||||
required: false
|
||||
enable-AzPSSession:
|
||||
description: 'Set this value to true to enable Azure PowerShell Login in addition to Az CLI login'
|
||||
description: 'Set this value to true to enable Azure PowerShell Login in addition to Azure CLI login'
|
||||
required: false
|
||||
default: false
|
||||
environment:
|
||||
description: 'Name of the environment. Supported values are azurecloud, azurestack, azureusgovernment, azurechinacloud, azuregermancloud. Default being azurecloud'
|
||||
required: false
|
||||
default: azurecloud
|
||||
allow-no-subscriptions:
|
||||
description: 'Set this value to true to enable support for accessing tenants without subscriptions'
|
||||
description: 'Set this value to true to enable support for accessing tenants without subscriptions'
|
||||
required: false
|
||||
default: false
|
||||
audience:
|
||||
description: 'Provide audience field for access-token. Default value is api://AzureADTokenExchange'
|
||||
required: false
|
||||
default: 'api://AzureADTokenExchange'
|
||||
auth-type:
|
||||
description: 'The type of authentication. Supported values are SERVICE_PRINCIPAL, IDENTITY. Default value is SERVICE_PRINCIPAL'
|
||||
required: false
|
||||
default: 'SERVICE_PRINCIPAL'
|
||||
branding:
|
||||
icon: 'login.svg'
|
||||
color: 'blue'
|
||||
runs:
|
||||
using: 'node12'
|
||||
using: 'node16'
|
||||
pre: 'lib/cleanup.js'
|
||||
main: 'lib/main.js'
|
||||
post: 'lib/cleanup.js'
|
||||
|
||||
193
lib/Cli/AzureCliLogin.js
Normal file
193
lib/Cli/AzureCliLogin.js
Normal file
@@ -0,0 +1,193 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (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.prototype.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.AzureCliLogin = void 0;
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
const LoginConfig_1 = require("../common/LoginConfig");
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const io = __importStar(require("@actions/io"));
|
||||
class AzureCliLogin {
|
||||
constructor(loginConfig) {
|
||||
this.loginConfig = loginConfig;
|
||||
this.loginOptions = defaultExecOptions();
|
||||
}
|
||||
login() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info(`Running Azure CLI Login.`);
|
||||
this.azPath = yield io.which("az", true);
|
||||
core.debug(`Azure CLI path: ${this.azPath}`);
|
||||
let output = "";
|
||||
const execOptions = {
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
yield this.executeAzCliCommand(["--version"], true, execOptions);
|
||||
core.debug(`Azure CLI version used:\n${output}`);
|
||||
this.setAzurestackEnvIfNecessary();
|
||||
yield this.executeAzCliCommand(["cloud", "set", "-n", this.loginConfig.environment], false);
|
||||
core.info(`Done setting cloud: "${this.loginConfig.environment}"`);
|
||||
if (this.loginConfig.authType === LoginConfig_1.LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL) {
|
||||
let args = ["--service-principal",
|
||||
"--username", this.loginConfig.servicePrincipalId,
|
||||
"--tenant", this.loginConfig.tenantId
|
||||
];
|
||||
if (this.loginConfig.servicePrincipalSecret) {
|
||||
yield this.loginWithSecret(args);
|
||||
}
|
||||
else {
|
||||
yield this.loginWithOIDC(args);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let args = ["--identity"];
|
||||
if (this.loginConfig.servicePrincipalId) {
|
||||
yield this.loginWithUserAssignedIdentity(args);
|
||||
}
|
||||
else {
|
||||
yield this.loginWithSystemAssignedIdentity(args);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
setAzurestackEnvIfNecessary() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (this.loginConfig.environment != "azurestack") {
|
||||
return;
|
||||
}
|
||||
if (!this.loginConfig.resourceManagerEndpointUrl) {
|
||||
throw new Error("resourceManagerEndpointUrl is a required parameter when environment is defined.");
|
||||
}
|
||||
core.info(`Unregistering cloud: "${this.loginConfig.environment}" first if it exists`);
|
||||
try {
|
||||
yield this.executeAzCliCommand(["cloud", "set", "-n", "AzureCloud"], true);
|
||||
yield this.executeAzCliCommand(["cloud", "unregister", "-n", this.loginConfig.environment], false);
|
||||
}
|
||||
catch (error) {
|
||||
core.info(`Ignore cloud not registered error: "${error}"`);
|
||||
}
|
||||
core.info(`Registering cloud: "${this.loginConfig.environment}" with ARM endpoint: "${this.loginConfig.resourceManagerEndpointUrl}"`);
|
||||
try {
|
||||
let baseUri = this.loginConfig.resourceManagerEndpointUrl;
|
||||
if (baseUri.endsWith('/')) {
|
||||
baseUri = baseUri.substring(0, baseUri.length - 1); // need to remove trailing / from resourceManagerEndpointUrl to correctly derive suffixes below
|
||||
}
|
||||
let suffixKeyvault = ".vault" + baseUri.substring(baseUri.indexOf('.')); // keyvault suffix starts with .
|
||||
let suffixStorage = baseUri.substring(baseUri.indexOf('.') + 1); // storage suffix starts without .
|
||||
let profileVersion = "2019-03-01-hybrid";
|
||||
yield this.executeAzCliCommand(["cloud", "register", "-n", this.loginConfig.environment, "--endpoint-resource-manager", `"${this.loginConfig.resourceManagerEndpointUrl}"`, "--suffix-keyvault-dns", `"${suffixKeyvault}"`, "--suffix-storage-endpoint", `"${suffixStorage}"`, "--profile", `"${profileVersion}"`], false);
|
||||
}
|
||||
catch (error) {
|
||||
core.error(`Error while trying to register cloud "${this.loginConfig.environment}"`);
|
||||
throw error;
|
||||
}
|
||||
core.info(`Done registering cloud: "${this.loginConfig.environment}"`);
|
||||
});
|
||||
}
|
||||
loginWithSecret(args) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info("Note: Azure/login action also supports OIDC login mechanism. Refer https://github.com/azure/login#configure-a-service-principal-with-a-federated-credential-to-use-oidc-based-authentication for more details.");
|
||||
args.push(`--password=${this.loginConfig.servicePrincipalSecret}`);
|
||||
yield this.callCliLogin(args, 'service principal with secret');
|
||||
});
|
||||
}
|
||||
loginWithOIDC(args) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.loginConfig.getFederatedToken();
|
||||
args.push("--federated-token", this.loginConfig.federatedToken);
|
||||
yield this.callCliLogin(args, 'OIDC');
|
||||
});
|
||||
}
|
||||
loginWithUserAssignedIdentity(args) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
args.push("--username", this.loginConfig.servicePrincipalId);
|
||||
yield this.callCliLogin(args, 'user-assigned managed identity');
|
||||
});
|
||||
}
|
||||
loginWithSystemAssignedIdentity(args) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield this.callCliLogin(args, 'system-assigned managed identity');
|
||||
});
|
||||
}
|
||||
callCliLogin(args, methodName) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info(`Attempting Azure CLI login by using ${methodName}...`);
|
||||
args.unshift("login");
|
||||
if (this.loginConfig.allowNoSubscriptionsLogin) {
|
||||
args.push("--allow-no-subscriptions");
|
||||
}
|
||||
yield this.executeAzCliCommand(args, true, this.loginOptions);
|
||||
if (this.loginConfig.subscriptionId) {
|
||||
yield this.setSubscription();
|
||||
}
|
||||
core.info(`Azure CLI login succeeds by using ${methodName}.`);
|
||||
});
|
||||
}
|
||||
setSubscription() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let args = ["account", "set", "--subscription", this.loginConfig.subscriptionId];
|
||||
yield this.executeAzCliCommand(args, true, this.loginOptions);
|
||||
core.info("Subscription is set successfully.");
|
||||
});
|
||||
}
|
||||
executeAzCliCommand(args, silent, execOptions = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
execOptions.silent = !!silent;
|
||||
yield exec.exec(`"${this.azPath}"`, args, execOptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.AzureCliLogin = AzureCliLogin;
|
||||
function defaultExecOptions() {
|
||||
return {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stderr: (data) => {
|
||||
let error = data.toString();
|
||||
let startsWithWarning = error.toLowerCase().startsWith('warning');
|
||||
let startsWithError = error.toLowerCase().startsWith('error');
|
||||
// printing ERROR
|
||||
if (error && error.trim().length !== 0 && !startsWithWarning) {
|
||||
if (startsWithError) {
|
||||
//removing the keyword 'ERROR' to avoid duplicates while throwing error
|
||||
error = error.slice(7);
|
||||
}
|
||||
core.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
59
lib/PowerShell/AzPSLogin.js
Normal file
59
lib/PowerShell/AzPSLogin.js
Normal file
@@ -0,0 +1,59 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (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.prototype.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 __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AzPSLogin = void 0;
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const AzPSScriptBuilder_1 = __importDefault(require("./AzPSScriptBuilder"));
|
||||
const AzPSUtils_1 = require("./AzPSUtils");
|
||||
class AzPSLogin {
|
||||
constructor(loginConfig) {
|
||||
this.loginConfig = loginConfig;
|
||||
}
|
||||
login() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.info(`Running Azure PowerShell Login.`);
|
||||
AzPSUtils_1.AzPSUtils.setPSModulePathForGitHubRunner();
|
||||
yield AzPSUtils_1.AzPSUtils.importLatestAzAccounts();
|
||||
const [loginMethod, loginScript] = yield AzPSScriptBuilder_1.default.getAzPSLoginScript(this.loginConfig);
|
||||
core.info(`Attempting Azure PowerShell login by using ${loginMethod}...`);
|
||||
core.debug(`Azure PowerShell Login Script: ${loginScript}`);
|
||||
yield AzPSUtils_1.AzPSUtils.runPSScript(loginScript);
|
||||
console.log(`Running Azure PowerShell Login successfully.`);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.AzPSLogin = AzPSLogin;
|
||||
116
lib/PowerShell/AzPSScriptBuilder.js
Normal file
116
lib/PowerShell/AzPSScriptBuilder.js
Normal file
@@ -0,0 +1,116 @@
|
||||
"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 });
|
||||
const LoginConfig_1 = require("../common/LoginConfig");
|
||||
class AzPSScriptBuilder {
|
||||
static getImportLatestModuleScript(moduleName) {
|
||||
let script = `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
$latestModulePath = (Get-Module -Name '${moduleName}' -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1).Path
|
||||
Import-Module -Name $latestModulePath
|
||||
$output['Success'] = $true
|
||||
$output['Result'] = $latestModulePath
|
||||
}
|
||||
catch {
|
||||
$output['Success'] = $false
|
||||
$output['Error'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
return script;
|
||||
}
|
||||
static getAzPSLoginScript(loginConfig) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let loginMethodName = "";
|
||||
let commands = "";
|
||||
if (loginConfig.environment.toLowerCase() == "azurestack") {
|
||||
commands += `Add-AzEnvironment -Name '${loginConfig.environment}' -ARMEndpoint '${loginConfig.resourceManagerEndpointUrl}' | out-null;`;
|
||||
}
|
||||
if (loginConfig.authType === LoginConfig_1.LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL) {
|
||||
if (loginConfig.servicePrincipalSecret) {
|
||||
commands += AzPSScriptBuilder.loginWithSecret(loginConfig);
|
||||
loginMethodName = 'service principal with secret';
|
||||
}
|
||||
else {
|
||||
commands += yield AzPSScriptBuilder.loginWithOIDC(loginConfig);
|
||||
loginMethodName = "OIDC";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (loginConfig.servicePrincipalId) {
|
||||
commands += AzPSScriptBuilder.loginWithUserAssignedIdentity(loginConfig);
|
||||
loginMethodName = 'user-assigned managed identity';
|
||||
}
|
||||
else {
|
||||
commands += AzPSScriptBuilder.loginWithSystemAssignedIdentity(loginConfig);
|
||||
loginMethodName = 'system-assigned managed identity';
|
||||
}
|
||||
}
|
||||
let script = `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
${commands}
|
||||
$output['Success'] = $true
|
||||
$output['Result'] = ""
|
||||
}
|
||||
catch {
|
||||
$output['Success'] = $false
|
||||
$output['Error'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
return [loginMethodName, script];
|
||||
});
|
||||
}
|
||||
static loginWithSecret(loginConfig) {
|
||||
let servicePrincipalSecret = loginConfig.servicePrincipalSecret.split("'").join("''");
|
||||
let loginCmdlet = `$psLoginSecrets = ConvertTo-SecureString '${servicePrincipalSecret}' -AsPlainText -Force; `;
|
||||
loginCmdlet += `$psLoginCredential = New-Object System.Management.Automation.PSCredential('${loginConfig.servicePrincipalId}', $psLoginSecrets); `;
|
||||
let cmdletSuffix = "-Credential $psLoginCredential";
|
||||
loginCmdlet += AzPSScriptBuilder.psLoginCmdlet(loginConfig.authType, loginConfig.environment, loginConfig.tenantId, loginConfig.subscriptionId, cmdletSuffix);
|
||||
return loginCmdlet;
|
||||
}
|
||||
static loginWithOIDC(loginConfig) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield loginConfig.getFederatedToken();
|
||||
let cmdletSuffix = `-ApplicationId '${loginConfig.servicePrincipalId}' -FederatedToken '${loginConfig.federatedToken}'`;
|
||||
return AzPSScriptBuilder.psLoginCmdlet(loginConfig.authType, loginConfig.environment, loginConfig.tenantId, loginConfig.subscriptionId, cmdletSuffix);
|
||||
});
|
||||
}
|
||||
static loginWithSystemAssignedIdentity(loginConfig) {
|
||||
let cmdletSuffix = "";
|
||||
return AzPSScriptBuilder.psLoginCmdlet(loginConfig.authType, loginConfig.environment, loginConfig.tenantId, loginConfig.subscriptionId, cmdletSuffix);
|
||||
}
|
||||
static loginWithUserAssignedIdentity(loginConfig) {
|
||||
let cmdletSuffix = `-AccountId '${loginConfig.servicePrincipalId}'`;
|
||||
return AzPSScriptBuilder.psLoginCmdlet(loginConfig.authType, loginConfig.environment, loginConfig.tenantId, loginConfig.subscriptionId, cmdletSuffix);
|
||||
}
|
||||
static psLoginCmdlet(authType, environment, tenantId, subscriptionId, cmdletSuffix) {
|
||||
let loginCmdlet = `Connect-AzAccount `;
|
||||
if (authType === LoginConfig_1.LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL) {
|
||||
loginCmdlet += "-ServicePrincipal ";
|
||||
}
|
||||
else {
|
||||
loginCmdlet += "-Identity ";
|
||||
}
|
||||
loginCmdlet += `-Environment '${environment}' `;
|
||||
if (tenantId) {
|
||||
loginCmdlet += `-Tenant '${tenantId}' `;
|
||||
}
|
||||
if (subscriptionId) {
|
||||
loginCmdlet += `-Subscription '${subscriptionId}' `;
|
||||
}
|
||||
loginCmdlet += `${cmdletSuffix} | out-null;`;
|
||||
return loginCmdlet;
|
||||
}
|
||||
}
|
||||
exports.default = AzPSScriptBuilder;
|
||||
119
lib/PowerShell/AzPSUtils.js
Normal file
119
lib/PowerShell/AzPSUtils.js
Normal file
@@ -0,0 +1,119 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (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.prototype.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 __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AzPSUtils = exports.AzPSConstants = void 0;
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const os = __importStar(require("os"));
|
||||
const path = __importStar(require("path"));
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
const io = __importStar(require("@actions/io"));
|
||||
const AzPSScriptBuilder_1 = __importDefault(require("./AzPSScriptBuilder"));
|
||||
class AzPSConstants {
|
||||
}
|
||||
exports.AzPSConstants = AzPSConstants;
|
||||
AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX = '/usr/share';
|
||||
AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS = 'C:\\Modules';
|
||||
AzPSConstants.AzAccounts = "Az.Accounts";
|
||||
AzPSConstants.PowerShell_CmdName = "pwsh";
|
||||
class AzPSUtils {
|
||||
static setPSModulePathForGitHubRunner() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const runner = process.env.RUNNER_OS || os.type();
|
||||
switch (runner.toLowerCase()) {
|
||||
case "linux":
|
||||
AzPSUtils.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX);
|
||||
break;
|
||||
case "windows":
|
||||
case "windows_nt":
|
||||
AzPSUtils.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS);
|
||||
break;
|
||||
case "macos":
|
||||
case "darwin":
|
||||
core.warning(`Skip setting the default PowerShell module path for OS ${runner.toLowerCase()}.`);
|
||||
break;
|
||||
default:
|
||||
core.warning(`Skip setting the default PowerShell module path for unknown OS ${runner.toLowerCase()}.`);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
static pushPSModulePath(psModulePath) {
|
||||
process.env.PSModulePath = `${psModulePath}${path.delimiter}${process.env.PSModulePath}`;
|
||||
core.debug(`Set PSModulePath as ${process.env.PSModulePath}`);
|
||||
}
|
||||
static importLatestAzAccounts() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let importLatestAccountsScript = AzPSScriptBuilder_1.default.getImportLatestModuleScript(AzPSConstants.AzAccounts);
|
||||
core.debug(`The script to import the latest Az.Accounts: ${importLatestAccountsScript}`);
|
||||
let azAccountsPath = yield AzPSUtils.runPSScript(importLatestAccountsScript);
|
||||
core.debug(`The latest Az.Accounts used: ${azAccountsPath}`);
|
||||
});
|
||||
}
|
||||
static runPSScript(psScript) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let outputString = "";
|
||||
let commandStdErr = false;
|
||||
const options = {
|
||||
silent: true,
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
outputString += data.toString();
|
||||
},
|
||||
stderr: (data) => {
|
||||
let error = data.toString();
|
||||
if (error && error.trim().length !== 0) {
|
||||
commandStdErr = true;
|
||||
core.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let psPath = yield io.which(AzPSConstants.PowerShell_CmdName, true);
|
||||
yield exec.exec(`"${psPath}"`, ["-Command", psScript], options);
|
||||
if (commandStdErr) {
|
||||
throw new Error('Azure PowerShell login failed with errors.');
|
||||
}
|
||||
const result = JSON.parse(outputString.trim());
|
||||
console.log(result);
|
||||
if (!(result.Success)) {
|
||||
throw new Error(`Azure PowerShell login failed with error: ${result.Error}`);
|
||||
}
|
||||
return result.Result;
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.AzPSUtils = AzPSUtils;
|
||||
@@ -1,14 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
class Constants {
|
||||
}
|
||||
exports.default = Constants;
|
||||
Constants.prefix = "az_";
|
||||
Constants.moduleName = "Az.Accounts";
|
||||
Constants.versionPattern = /[0-9]\.[0-9]\.[0-9]/;
|
||||
Constants.AzureCloud = "AzureCloud";
|
||||
Constants.Subscription = "Subscription";
|
||||
Constants.ServicePrincipal = "ServicePrincipal";
|
||||
Constants.Success = "Success";
|
||||
Constants.Error = "Error";
|
||||
Constants.AzVersion = "AzVersion";
|
||||
@@ -1,75 +0,0 @@
|
||||
"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 __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const Utils_1 = __importDefault(require("./Utilities/Utils"));
|
||||
const PowerShellToolRunner_1 = __importDefault(require("./Utilities/PowerShellToolRunner"));
|
||||
const ScriptBuilder_1 = __importDefault(require("./Utilities/ScriptBuilder"));
|
||||
const Constants_1 = __importDefault(require("./Constants"));
|
||||
class ServicePrincipalLogin {
|
||||
constructor(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, allowNoSubscriptionsLogin) {
|
||||
this.servicePrincipalId = servicePrincipalId;
|
||||
this.servicePrincipalKey = servicePrincipalKey;
|
||||
this.tenantId = tenantId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.allowNoSubscriptionsLogin = allowNoSubscriptionsLogin;
|
||||
}
|
||||
initialize() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
Utils_1.default.setPSModulePath();
|
||||
const azLatestVersion = yield Utils_1.default.getLatestModule(Constants_1.default.moduleName);
|
||||
core.debug(`Az Module version used: ${azLatestVersion}`);
|
||||
Utils_1.default.setPSModulePath(`${Constants_1.default.prefix}${azLatestVersion}`);
|
||||
});
|
||||
}
|
||||
login() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let output = "";
|
||||
const options = {
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
const args = {
|
||||
servicePrincipalId: this.servicePrincipalId,
|
||||
servicePrincipalKey: this.servicePrincipalKey,
|
||||
subscriptionId: this.subscriptionId,
|
||||
environment: ServicePrincipalLogin.environment,
|
||||
scopeLevel: ServicePrincipalLogin.scopeLevel,
|
||||
allowNoSubscriptionsLogin: this.allowNoSubscriptionsLogin
|
||||
};
|
||||
const script = new ScriptBuilder_1.default().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args);
|
||||
yield PowerShellToolRunner_1.default.init();
|
||||
yield PowerShellToolRunner_1.default.executePowerShellScriptBlock(script, options);
|
||||
const result = JSON.parse(output.trim());
|
||||
if (!(Constants_1.default.Success in result)) {
|
||||
throw new Error(`Azure PowerShell login failed with error: ${result[Constants_1.default.Error]}`);
|
||||
}
|
||||
console.log(`Azure PowerShell session successfully initialized`);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.ServicePrincipalLogin = ServicePrincipalLogin;
|
||||
ServicePrincipalLogin.environment = Constants_1.default.AzureCloud;
|
||||
ServicePrincipalLogin.scopeLevel = Constants_1.default.Subscription;
|
||||
ServicePrincipalLogin.scheme = Constants_1.default.ServicePrincipal;
|
||||
@@ -1,35 +0,0 @@
|
||||
"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 __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const io = __importStar(require("@actions/io"));
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
class PowerShellToolRunner {
|
||||
static init() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!PowerShellToolRunner.psPath) {
|
||||
PowerShellToolRunner.psPath = yield io.which("pwsh", true);
|
||||
}
|
||||
});
|
||||
}
|
||||
static executePowerShellScriptBlock(scriptBlock, options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield exec.exec(`"${PowerShellToolRunner.psPath}" -Command`, [scriptBlock], options);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.default = PowerShellToolRunner;
|
||||
@@ -1,62 +0,0 @@
|
||||
"use strict";
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const Constants_1 = __importDefault(require("../Constants"));
|
||||
class ScriptBuilder {
|
||||
constructor() {
|
||||
this.script = "";
|
||||
}
|
||||
getAzPSLoginScript(scheme, tenantId, args) {
|
||||
let command = `Clear-AzContext -Scope Process;
|
||||
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue;`;
|
||||
if (scheme === Constants_1.default.ServicePrincipal) {
|
||||
command += `Connect-AzAccount -ServicePrincipal -Tenant '${tenantId}' -Credential \
|
||||
(New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString '${args.servicePrincipalKey.replace("'", "''")}' -AsPlainText -Force))) \
|
||||
-Environment '${args.environment}' | out-null;`;
|
||||
if (args.scopeLevel === Constants_1.default.Subscription && !args.allowNoSubscriptionsLogin) {
|
||||
command += `Set-AzContext -SubscriptionId '${args.subscriptionId}' -TenantId '${tenantId}' | out-null;`;
|
||||
}
|
||||
}
|
||||
this.script += `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
${command}
|
||||
$output['${Constants_1.default.Success}'] = "true"
|
||||
}
|
||||
catch {
|
||||
$output['${Constants_1.default.Error}'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
core.debug(`Azure PowerShell Login Script: ${this.script}`);
|
||||
return this.script;
|
||||
}
|
||||
getLatestModuleScript(moduleName) {
|
||||
const command = `Get-Module -Name ${moduleName} -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1`;
|
||||
this.script += `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
$data = ${command}
|
||||
$output['${Constants_1.default.AzVersion}'] = $data.Version.ToString()
|
||||
$output['${Constants_1.default.Success}'] = "true"
|
||||
}
|
||||
catch {
|
||||
$output['${Constants_1.default.Error}'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
core.debug(`GetLatestModuleScript: ${this.script}`);
|
||||
return this.script;
|
||||
}
|
||||
}
|
||||
exports.default = ScriptBuilder;
|
||||
@@ -1,80 +0,0 @@
|
||||
"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 __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const os = __importStar(require("os"));
|
||||
const Constants_1 = __importDefault(require("../Constants"));
|
||||
const ScriptBuilder_1 = __importDefault(require("./ScriptBuilder"));
|
||||
const PowerShellToolRunner_1 = __importDefault(require("./PowerShellToolRunner"));
|
||||
class Utils {
|
||||
/**
|
||||
* Add the folder path where Az modules are present to PSModulePath based on runner
|
||||
* @param azPSVersion
|
||||
* If azPSVersion is empty, folder path in which all Az modules are present are set
|
||||
* If azPSVersion is not empty, folder path of exact Az module version is set
|
||||
*/
|
||||
static setPSModulePath(azPSVersion = "") {
|
||||
let modulePath = "";
|
||||
const runner = process.env.RUNNER_OS || os.type();
|
||||
switch (runner.toLowerCase()) {
|
||||
case "linux":
|
||||
modulePath = `/usr/share/${azPSVersion}:`;
|
||||
break;
|
||||
case "windows":
|
||||
case "windows_nt":
|
||||
modulePath = `C:\\Modules\\${azPSVersion};`;
|
||||
break;
|
||||
case "macos":
|
||||
case "darwin":
|
||||
throw new Error(`OS not supported`);
|
||||
default:
|
||||
throw new Error(`Unknown os: ${runner.toLowerCase()}`);
|
||||
}
|
||||
process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`;
|
||||
}
|
||||
static getLatestModule(moduleName) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let output = "";
|
||||
const options = {
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
yield PowerShellToolRunner_1.default.init();
|
||||
yield PowerShellToolRunner_1.default.executePowerShellScriptBlock(new ScriptBuilder_1.default()
|
||||
.getLatestModuleScript(moduleName), options);
|
||||
const result = JSON.parse(output.trim());
|
||||
if (!(Constants_1.default.Success in result)) {
|
||||
throw new Error(result[Constants_1.default.Error]);
|
||||
}
|
||||
const azLatestVersion = result[Constants_1.default.AzVersion];
|
||||
if (!Utils.isValidVersion(azLatestVersion)) {
|
||||
throw new Error(`Invalid AzPSVersion: ${azLatestVersion}`);
|
||||
}
|
||||
return azLatestVersion;
|
||||
});
|
||||
}
|
||||
static isValidVersion(version) {
|
||||
return !!version.match(Constants_1.default.versionPattern);
|
||||
}
|
||||
}
|
||||
exports.default = Utils;
|
||||
52
lib/cleanup.js
Normal file
52
lib/cleanup.js
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (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.prototype.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 });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const Utils_1 = require("./common/Utils");
|
||||
function cleanup() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
(0, Utils_1.setUserAgent)();
|
||||
yield (0, Utils_1.cleanupAzCLIAccounts)();
|
||||
if (core.getInput('enable-AzPSSession').toLowerCase() === "true") {
|
||||
yield (0, Utils_1.cleanupAzPSAccounts)();
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
core.warning(`Login cleanup failed with ${error}. Cleanup will be skipped.`);
|
||||
core.debug(error.stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
cleanup();
|
||||
136
lib/common/LoginConfig.js
Normal file
136
lib/common/LoginConfig.js
Normal file
@@ -0,0 +1,136 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (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.prototype.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.LoginConfig = void 0;
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const actions_secret_parser_1 = require("actions-secret-parser");
|
||||
class LoginConfig {
|
||||
initialize() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
this.environment = core.getInput("environment").toLowerCase();
|
||||
this.enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
|
||||
this.allowNoSubscriptionsLogin = core.getInput('allow-no-subscriptions').toLowerCase() === "true";
|
||||
this.authType = core.getInput('auth-type').toUpperCase();
|
||||
this.servicePrincipalId = core.getInput('client-id', { required: false });
|
||||
this.servicePrincipalSecret = null;
|
||||
this.tenantId = core.getInput('tenant-id', { required: false });
|
||||
this.subscriptionId = core.getInput('subscription-id', { required: false });
|
||||
this.readParametersFromCreds();
|
||||
this.audience = core.getInput('audience', { required: false });
|
||||
this.federatedToken = null;
|
||||
this.mask(this.servicePrincipalId);
|
||||
this.mask(this.servicePrincipalSecret);
|
||||
});
|
||||
}
|
||||
readParametersFromCreds() {
|
||||
let creds = core.getInput('creds', { required: false });
|
||||
let secrets = creds ? new actions_secret_parser_1.SecretParser(creds, actions_secret_parser_1.FormatType.JSON) : null;
|
||||
if (!secrets) {
|
||||
return;
|
||||
}
|
||||
if (this.authType != LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL) {
|
||||
return;
|
||||
}
|
||||
if (this.servicePrincipalId || this.tenantId || this.subscriptionId) {
|
||||
core.warning("At least one of the parameters 'client-id', 'subscription-id' or 'tenant-id' is set. 'creds' will be ignored.");
|
||||
return;
|
||||
}
|
||||
core.debug('Reading creds in JSON...');
|
||||
this.servicePrincipalId = this.servicePrincipalId ? this.servicePrincipalId : secrets.getSecret("$.clientId", false);
|
||||
this.servicePrincipalSecret = secrets.getSecret("$.clientSecret", false);
|
||||
this.tenantId = this.tenantId ? this.tenantId : secrets.getSecret("$.tenantId", false);
|
||||
this.subscriptionId = this.subscriptionId ? this.subscriptionId : secrets.getSecret("$.subscriptionId", false);
|
||||
this.resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
|
||||
if (!this.servicePrincipalId || !this.servicePrincipalSecret || !this.tenantId) {
|
||||
throw new Error("Not all parameters are provided in 'creds'. Double-check if all keys are defined in 'creds': 'clientId', 'clientSecret', 'tenantId'.");
|
||||
}
|
||||
}
|
||||
getFederatedToken() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
this.federatedToken = yield core.getIDToken(this.audience);
|
||||
this.mask(this.federatedToken);
|
||||
}
|
||||
catch (error) {
|
||||
core.error(`Please make sure to give write permissions to id-token in the workflow.`);
|
||||
throw error;
|
||||
}
|
||||
let [issuer, subjectClaim] = yield jwtParser(this.federatedToken);
|
||||
core.info("Federated token details:\n issuer - " + issuer + "\n subject claim - " + subjectClaim);
|
||||
});
|
||||
}
|
||||
validate() {
|
||||
if (!LoginConfig.azureSupportedCloudName.has(this.environment)) {
|
||||
throw new Error(`Unsupported value '${this.environment}' for environment is passed. The list of supported values for environment are '${Array.from(LoginConfig.azureSupportedCloudName).join("', '")}'. `);
|
||||
}
|
||||
if (!LoginConfig.azureSupportedAuthType.has(this.authType)) {
|
||||
throw new Error(`Unsupported value '${this.authType}' for authentication type is passed. The list of supported values for auth-type are '${Array.from(LoginConfig.azureSupportedAuthType).join("', '")}'.`);
|
||||
}
|
||||
if (this.authType === LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL) {
|
||||
if (!this.servicePrincipalId || !this.tenantId) {
|
||||
throw new Error(`Using auth-type: ${LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL}. Not all values are present. Ensure 'client-id' and 'tenant-id' are supplied.`);
|
||||
}
|
||||
}
|
||||
if (!this.subscriptionId && !this.allowNoSubscriptionsLogin) {
|
||||
throw new Error("Ensure subscriptionId is supplied.");
|
||||
}
|
||||
}
|
||||
mask(parameterValue) {
|
||||
if (parameterValue) {
|
||||
core.setSecret(parameterValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.LoginConfig = LoginConfig;
|
||||
LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL = "SERVICE_PRINCIPAL";
|
||||
LoginConfig.AUTH_TYPE_IDENTITY = "IDENTITY";
|
||||
LoginConfig.azureSupportedCloudName = new Set([
|
||||
"azureusgovernment",
|
||||
"azurechinacloud",
|
||||
"azuregermancloud",
|
||||
"azurecloud",
|
||||
"azurestack"
|
||||
]);
|
||||
LoginConfig.azureSupportedAuthType = new Set([
|
||||
LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL,
|
||||
LoginConfig.AUTH_TYPE_IDENTITY
|
||||
]);
|
||||
function jwtParser(federatedToken) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let tokenPayload = federatedToken.split('.')[1];
|
||||
let bufferObj = Buffer.from(tokenPayload, "base64");
|
||||
let decodedPayload = JSON.parse(bufferObj.toString("utf8"));
|
||||
return [decodedPayload['iss'], decodedPayload['sub']];
|
||||
});
|
||||
}
|
||||
69
lib/common/Utils.js
Normal file
69
lib/common/Utils.js
Normal file
@@ -0,0 +1,69 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (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.prototype.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.cleanupAzPSAccounts = exports.cleanupAzCLIAccounts = exports.setUserAgent = void 0;
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
const io = __importStar(require("@actions/io"));
|
||||
const crypto = __importStar(require("crypto"));
|
||||
const AzPSUtils_1 = require("../PowerShell/AzPSUtils");
|
||||
function setUserAgent() {
|
||||
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
|
||||
let actionName = 'AzureLogin';
|
||||
process.env.AZURE_HTTP_USER_AGENT = (!!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT} ` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
|
||||
process.env.AZUREPS_HOST_ENVIRONMENT = (!!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT} ` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
|
||||
}
|
||||
exports.setUserAgent = setUserAgent;
|
||||
function cleanupAzCLIAccounts() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let azPath = yield io.which("az", true);
|
||||
core.debug(`Azure CLI path: ${azPath}`);
|
||||
core.info("Clearing azure cli accounts from the local cache.");
|
||||
yield exec.exec(`"${azPath}"`, ["account", "clear"]);
|
||||
});
|
||||
}
|
||||
exports.cleanupAzCLIAccounts = cleanupAzCLIAccounts;
|
||||
function cleanupAzPSAccounts() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let psPath = yield io.which(AzPSUtils_1.AzPSConstants.PowerShell_CmdName, true);
|
||||
core.debug(`PowerShell path: ${psPath}`);
|
||||
core.debug("Importing Azure PowerShell module.");
|
||||
AzPSUtils_1.AzPSUtils.setPSModulePathForGitHubRunner();
|
||||
yield AzPSUtils_1.AzPSUtils.importLatestAzAccounts();
|
||||
core.info("Clearing azure powershell accounts from the local cache.");
|
||||
yield exec.exec(`"${psPath}"`, ["-Command", "Clear-AzContext", "-Scope", "Process"]);
|
||||
yield exec.exec(`"${psPath}"`, ["-Command", "Clear-AzContext", "-Scope", "CurrentUser", "-Force", "-ErrorAction", "SilentlyContinue"]);
|
||||
});
|
||||
}
|
||||
exports.cleanupAzPSAccounts = cleanupAzPSAccounts;
|
||||
117
lib/main.js
117
lib/main.js
@@ -1,4 +1,27 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (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.prototype.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) {
|
||||
@@ -8,90 +31,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
const io = __importStar(require("@actions/io"));
|
||||
const actions_secret_parser_1 = require("actions-secret-parser");
|
||||
const ServicePrincipalLogin_1 = require("./PowerShell/ServicePrincipalLogin");
|
||||
var azPath;
|
||||
var prefix = !!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT}` : "";
|
||||
var azPSHostEnv = !!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT}` : "";
|
||||
const Utils_1 = require("./common/Utils");
|
||||
const AzPSLogin_1 = require("./PowerShell/AzPSLogin");
|
||||
const LoginConfig_1 = require("./common/LoginConfig");
|
||||
const AzureCliLogin_1 = require("./Cli/AzureCliLogin");
|
||||
function main() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
// Set user agent variable
|
||||
var isAzCLISuccess = false;
|
||||
let usrAgentRepo = `${process.env.GITHUB_REPOSITORY}`;
|
||||
let actionName = 'AzureLogin';
|
||||
let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
|
||||
let azurePSHostEnv = (!!azPSHostEnv ? `${azPSHostEnv}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
|
||||
core.exportVariable('AZURE_HTTP_USER_AGENT', userAgentString);
|
||||
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv);
|
||||
azPath = yield io.which("az", true);
|
||||
yield executeAzCliCommand("--version");
|
||||
let creds = core.getInput('creds', { required: true });
|
||||
let secrets = new actions_secret_parser_1.SecretParser(creds, actions_secret_parser_1.FormatType.JSON);
|
||||
let servicePrincipalId = secrets.getSecret("$.clientId", false);
|
||||
let servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
|
||||
let tenantId = secrets.getSecret("$.tenantId", false);
|
||||
let subscriptionId = secrets.getSecret("$.subscriptionId", false);
|
||||
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
|
||||
const allowNoSubscriptionsLogin = core.getInput('allow-no-subscriptions').toLowerCase() === "true";
|
||||
if (!servicePrincipalId || !servicePrincipalKey || !tenantId) {
|
||||
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret and tenantId are supplied.");
|
||||
(0, Utils_1.setUserAgent)();
|
||||
// prepare the login configuration
|
||||
var loginConfig = new LoginConfig_1.LoginConfig();
|
||||
yield loginConfig.initialize();
|
||||
yield loginConfig.validate();
|
||||
// login to Azure CLI
|
||||
var cliLogin = new AzureCliLogin_1.AzureCliLogin(loginConfig);
|
||||
yield cliLogin.login();
|
||||
//login to Azure PowerShell
|
||||
if (loginConfig.enableAzPSSession) {
|
||||
var psLogin = new AzPSLogin_1.AzPSLogin(loginConfig);
|
||||
yield psLogin.login();
|
||||
}
|
||||
if (!subscriptionId && !allowNoSubscriptionsLogin) {
|
||||
throw new Error("Not all values are present in the creds object. Ensure subscriptionId is supplied.");
|
||||
}
|
||||
// Attempting Az cli login
|
||||
if (allowNoSubscriptionsLogin) {
|
||||
yield executeAzCliCommand(`login --allow-no-subscriptions --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true);
|
||||
}
|
||||
else {
|
||||
yield executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true);
|
||||
yield executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true);
|
||||
}
|
||||
isAzCLISuccess = true;
|
||||
if (enableAzPSSession) {
|
||||
// Attempting Az PS login
|
||||
console.log(`Running Azure PS Login`);
|
||||
const spnlogin = new ServicePrincipalLogin_1.ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, allowNoSubscriptionsLogin);
|
||||
yield spnlogin.initialize();
|
||||
yield spnlogin.login();
|
||||
}
|
||||
console.log("Login successful.");
|
||||
}
|
||||
catch (error) {
|
||||
if (!isAzCLISuccess) {
|
||||
core.error("Az CLI Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows");
|
||||
}
|
||||
else {
|
||||
core.error(`Azure PowerShell Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows"`);
|
||||
}
|
||||
core.setFailed(error);
|
||||
}
|
||||
finally {
|
||||
// Reset AZURE_HTTP_USER_AGENT
|
||||
core.exportVariable('AZURE_HTTP_USER_AGENT', prefix);
|
||||
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azPSHostEnv);
|
||||
}
|
||||
});
|
||||
}
|
||||
function executeAzCliCommand(command, silent) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
yield exec.exec(`"${azPath}" ${command}`, [], { silent: !!silent });
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(error);
|
||||
core.setFailed(`Login failed with ${error}. Double check if the 'auth-type' is correct. Refer to https://github.com/Azure/login#readme for more information.`);
|
||||
core.debug(error.stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
12
node_modules/.bin/browserslist
generated
vendored
Normal file
12
node_modules/.bin/browserslist
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../browserslist/cli.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../browserslist/cli.js" "$@"
|
||||
fi
|
||||
12
node_modules/.bin/browserslist-lint
generated
vendored
Normal file
12
node_modules/.bin/browserslist-lint
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../update-browserslist-db/cli.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../update-browserslist-db/cli.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/browserslist-lint.cmd
generated
vendored
Normal file
17
node_modules/.bin/browserslist-lint.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\update-browserslist-db\cli.js" %*
|
||||
28
node_modules/.bin/browserslist-lint.ps1
generated
vendored
Normal file
28
node_modules/.bin/browserslist-lint.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../update-browserslist-db/cli.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../update-browserslist-db/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../update-browserslist-db/cli.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../update-browserslist-db/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
17
node_modules/.bin/browserslist.cmd
generated
vendored
Normal file
17
node_modules/.bin/browserslist.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\browserslist\cli.js" %*
|
||||
28
node_modules/.bin/browserslist.ps1
generated
vendored
Normal file
28
node_modules/.bin/browserslist.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../browserslist/cli.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../browserslist/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../browserslist/cli.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../browserslist/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/esparse
generated
vendored
Normal file
12
node_modules/.bin/esparse
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../esprima/bin/esparse.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../esprima/bin/esparse.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/esparse.cmd
generated
vendored
Normal file
17
node_modules/.bin/esparse.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\esprima\bin\esparse.js" %*
|
||||
28
node_modules/.bin/esparse.ps1
generated
vendored
Normal file
28
node_modules/.bin/esparse.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../esprima/bin/esparse.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/esvalidate
generated
vendored
Normal file
12
node_modules/.bin/esvalidate
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../esprima/bin/esvalidate.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../esprima/bin/esvalidate.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/esvalidate.cmd
generated
vendored
Normal file
17
node_modules/.bin/esvalidate.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\esprima\bin\esvalidate.js" %*
|
||||
28
node_modules/.bin/esvalidate.ps1
generated
vendored
Normal file
28
node_modules/.bin/esvalidate.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../esprima/bin/esvalidate.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/import-local-fixture
generated
vendored
Normal file
12
node_modules/.bin/import-local-fixture
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../import-local/fixtures/cli.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../import-local/fixtures/cli.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/import-local-fixture.cmd
generated
vendored
Normal file
17
node_modules/.bin/import-local-fixture.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\import-local\fixtures\cli.js" %*
|
||||
28
node_modules/.bin/import-local-fixture.ps1
generated
vendored
Normal file
28
node_modules/.bin/import-local-fixture.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../import-local/fixtures/cli.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../import-local/fixtures/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../import-local/fixtures/cli.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../import-local/fixtures/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/jest
generated
vendored
Normal file
12
node_modules/.bin/jest
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../jest/bin/jest.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../jest/bin/jest.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/jest.cmd
generated
vendored
Normal file
17
node_modules/.bin/jest.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\jest\bin\jest.js" %*
|
||||
28
node_modules/.bin/jest.ps1
generated
vendored
Normal file
28
node_modules/.bin/jest.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../jest/bin/jest.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../jest/bin/jest.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../jest/bin/jest.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../jest/bin/jest.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/js-yaml
generated
vendored
Normal file
12
node_modules/.bin/js-yaml
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../js-yaml/bin/js-yaml.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../js-yaml/bin/js-yaml.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/js-yaml.cmd
generated
vendored
Normal file
17
node_modules/.bin/js-yaml.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\js-yaml\bin\js-yaml.js" %*
|
||||
28
node_modules/.bin/js-yaml.ps1
generated
vendored
Normal file
28
node_modules/.bin/js-yaml.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../js-yaml/bin/js-yaml.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/jsesc
generated
vendored
Normal file
12
node_modules/.bin/jsesc
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../jsesc/bin/jsesc" "$@"
|
||||
else
|
||||
exec node "$basedir/../jsesc/bin/jsesc" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/jsesc.cmd
generated
vendored
Normal file
17
node_modules/.bin/jsesc.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\jsesc\bin\jsesc" %*
|
||||
28
node_modules/.bin/jsesc.ps1
generated
vendored
Normal file
28
node_modules/.bin/jsesc.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../jsesc/bin/jsesc" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../jsesc/bin/jsesc" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../jsesc/bin/jsesc" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../jsesc/bin/jsesc" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/json5
generated
vendored
Normal file
12
node_modules/.bin/json5
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../json5/lib/cli.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../json5/lib/cli.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/json5.cmd
generated
vendored
Normal file
17
node_modules/.bin/json5.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\json5\lib\cli.js" %*
|
||||
28
node_modules/.bin/json5.ps1
generated
vendored
Normal file
28
node_modules/.bin/json5.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../json5/lib/cli.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../json5/lib/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../json5/lib/cli.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../json5/lib/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/node-which
generated
vendored
Normal file
12
node_modules/.bin/node-which
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../which/bin/node-which" "$@"
|
||||
else
|
||||
exec node "$basedir/../which/bin/node-which" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/node-which.cmd
generated
vendored
Normal file
17
node_modules/.bin/node-which.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\which\bin\node-which" %*
|
||||
28
node_modules/.bin/node-which.ps1
generated
vendored
Normal file
28
node_modules/.bin/node-which.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../which/bin/node-which" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../which/bin/node-which" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../which/bin/node-which" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/package-lock
generated
vendored
Normal file
12
node_modules/.bin/package-lock
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../package-lock/bin/package-lock.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../package-lock/bin/package-lock.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/package-lock.cmd
generated
vendored
Normal file
17
node_modules/.bin/package-lock.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\package-lock\bin\package-lock.js" %*
|
||||
28
node_modules/.bin/package-lock.ps1
generated
vendored
Normal file
28
node_modules/.bin/package-lock.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../package-lock/bin/package-lock.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../package-lock/bin/package-lock.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../package-lock/bin/package-lock.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../package-lock/bin/package-lock.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/parser
generated
vendored
Normal file
12
node_modules/.bin/parser
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../@babel/parser/bin/babel-parser.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../@babel/parser/bin/babel-parser.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/parser.cmd
generated
vendored
Normal file
17
node_modules/.bin/parser.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@babel\parser\bin\babel-parser.js" %*
|
||||
28
node_modules/.bin/parser.ps1
generated
vendored
Normal file
28
node_modules/.bin/parser.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/resolve
generated
vendored
Normal file
12
node_modules/.bin/resolve
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../resolve/bin/resolve" "$@"
|
||||
else
|
||||
exec node "$basedir/../resolve/bin/resolve" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/resolve.cmd
generated
vendored
Normal file
17
node_modules/.bin/resolve.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\resolve\bin\resolve" %*
|
||||
28
node_modules/.bin/resolve.ps1
generated
vendored
Normal file
28
node_modules/.bin/resolve.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../resolve/bin/resolve" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../resolve/bin/resolve" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../resolve/bin/resolve" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../resolve/bin/resolve" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/semver
generated
vendored
Normal file
12
node_modules/.bin/semver
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../semver/bin/semver.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/semver.cmd
generated
vendored
Normal file
17
node_modules/.bin/semver.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %*
|
||||
28
node_modules/.bin/semver.ps1
generated
vendored
Normal file
28
node_modules/.bin/semver.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../semver/bin/semver.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../semver/bin/semver.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/ts-jest
generated
vendored
Normal file
12
node_modules/.bin/ts-jest
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../ts-jest/cli.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../ts-jest/cli.js" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/ts-jest.cmd
generated
vendored
Normal file
17
node_modules/.bin/ts-jest.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\ts-jest\cli.js" %*
|
||||
28
node_modules/.bin/ts-jest.ps1
generated
vendored
Normal file
28
node_modules/.bin/ts-jest.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../ts-jest/cli.js" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../ts-jest/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../ts-jest/cli.js" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../ts-jest/cli.js" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/tsc
generated
vendored
Normal file
12
node_modules/.bin/tsc
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
|
||||
else
|
||||
exec node "$basedir/../typescript/bin/tsc" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/tsc.cmd
generated
vendored
Normal file
17
node_modules/.bin/tsc.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\typescript\bin\tsc" %*
|
||||
28
node_modules/.bin/tsc.ps1
generated
vendored
Normal file
28
node_modules/.bin/tsc.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../typescript/bin/tsc" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../typescript/bin/tsc" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../typescript/bin/tsc" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../typescript/bin/tsc" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
12
node_modules/.bin/tsserver
generated
vendored
Normal file
12
node_modules/.bin/tsserver
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
|
||||
else
|
||||
exec node "$basedir/../typescript/bin/tsserver" "$@"
|
||||
fi
|
||||
17
node_modules/.bin/tsserver.cmd
generated
vendored
Normal file
17
node_modules/.bin/tsserver.cmd
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
@ECHO off
|
||||
GOTO start
|
||||
:find_dp0
|
||||
SET dp0=%~dp0
|
||||
EXIT /b
|
||||
:start
|
||||
SETLOCAL
|
||||
CALL :find_dp0
|
||||
|
||||
IF EXIST "%dp0%\node.exe" (
|
||||
SET "_prog=%dp0%\node.exe"
|
||||
) ELSE (
|
||||
SET "_prog=node"
|
||||
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
)
|
||||
|
||||
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\typescript\bin\tsserver" %*
|
||||
28
node_modules/.bin/tsserver.ps1
generated
vendored
Normal file
28
node_modules/.bin/tsserver.ps1
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env pwsh
|
||||
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||
|
||||
$exe=""
|
||||
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||
# Fix case when both the Windows and Linux builds of Node
|
||||
# are installed in the same directory
|
||||
$exe=".exe"
|
||||
}
|
||||
$ret=0
|
||||
if (Test-Path "$basedir/node$exe") {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "$basedir/node$exe" "$basedir/../typescript/bin/tsserver" $args
|
||||
} else {
|
||||
& "$basedir/node$exe" "$basedir/../typescript/bin/tsserver" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
} else {
|
||||
# Support pipeline input
|
||||
if ($MyInvocation.ExpectingInput) {
|
||||
$input | & "node$exe" "$basedir/../typescript/bin/tsserver" $args
|
||||
} else {
|
||||
& "node$exe" "$basedir/../typescript/bin/tsserver" $args
|
||||
}
|
||||
$ret=$LASTEXITCODE
|
||||
}
|
||||
exit $ret
|
||||
3810
node_modules/.package-lock.json
generated
vendored
Normal file
3810
node_modules/.package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
node_modules/@actions/core/LICENSE.md
generated
vendored
Normal file
9
node_modules/@actions/core/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
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.
|
||||
335
node_modules/@actions/core/README.md
generated
vendored
Normal file
335
node_modules/@actions/core/README.md
generated
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
# `@actions/core`
|
||||
|
||||
> Core functions for setting results, logging, registering secrets and exporting variables across actions
|
||||
|
||||
## Usage
|
||||
|
||||
### Import the package
|
||||
|
||||
```js
|
||||
// javascript
|
||||
const core = require('@actions/core');
|
||||
|
||||
// typescript
|
||||
import * as core from '@actions/core';
|
||||
```
|
||||
|
||||
#### Inputs/Outputs
|
||||
|
||||
Action inputs can be read with `getInput` which returns a `string` or `getBooleanInput` which parses a boolean based on the [yaml 1.2 specification](https://yaml.org/spec/1.2/spec.html#id2804923). If `required` set to be false, the input should have a default value in `action.yml`.
|
||||
|
||||
Outputs can be set with `setOutput` which makes them available to be mapped into inputs of other actions to ensure they are decoupled.
|
||||
|
||||
```js
|
||||
const myInput = core.getInput('inputName', { required: true });
|
||||
const myBooleanInput = core.getBooleanInput('booleanInputName', { required: true });
|
||||
const myMultilineInput = core.getMultilineInput('multilineInputName', { required: true });
|
||||
core.setOutput('outputKey', 'outputVal');
|
||||
```
|
||||
|
||||
#### Exporting variables
|
||||
|
||||
Since each step runs in a separate process, you can use `exportVariable` to add it to this step and future steps environment blocks.
|
||||
|
||||
```js
|
||||
core.exportVariable('envVar', 'Val');
|
||||
```
|
||||
|
||||
#### Setting a secret
|
||||
|
||||
Setting a secret registers the secret with the runner to ensure it is masked in logs.
|
||||
|
||||
```js
|
||||
core.setSecret('myPassword');
|
||||
```
|
||||
|
||||
#### PATH Manipulation
|
||||
|
||||
To make a tool's path available in the path for the remainder of the job (without altering the machine or containers state), use `addPath`. The runner will prepend the path given to the jobs PATH.
|
||||
|
||||
```js
|
||||
core.addPath('/path/to/mytool');
|
||||
```
|
||||
|
||||
#### Exit codes
|
||||
|
||||
You should use this library to set the failing exit code for your action. If status is not set and the script runs to completion, that will lead to a success.
|
||||
|
||||
```js
|
||||
const core = require('@actions/core');
|
||||
|
||||
try {
|
||||
// Do stuff
|
||||
}
|
||||
catch (err) {
|
||||
// setFailed logs the message and sets a failing exit code
|
||||
core.setFailed(`Action failed with error ${err}`);
|
||||
}
|
||||
```
|
||||
|
||||
Note that `setNeutral` is not yet implemented in actions V2 but equivalent functionality is being planned.
|
||||
|
||||
#### Logging
|
||||
|
||||
Finally, this library provides some utilities for logging. Note that debug logging is hidden from the logs by default. This behavior can be toggled by enabling the [Step Debug Logs](../../docs/action-debugging.md#step-debug-logs).
|
||||
|
||||
```js
|
||||
const core = require('@actions/core');
|
||||
|
||||
const myInput = core.getInput('input');
|
||||
try {
|
||||
core.debug('Inside try block');
|
||||
|
||||
if (!myInput) {
|
||||
core.warning('myInput was not set');
|
||||
}
|
||||
|
||||
if (core.isDebug()) {
|
||||
// curl -v https://github.com
|
||||
} else {
|
||||
// curl https://github.com
|
||||
}
|
||||
|
||||
// Do stuff
|
||||
core.info('Output to the actions build log')
|
||||
|
||||
core.notice('This is a message that will also emit an annotation')
|
||||
}
|
||||
catch (err) {
|
||||
core.error(`Error ${err}, action may still succeed though`);
|
||||
}
|
||||
```
|
||||
|
||||
This library can also wrap chunks of output in foldable groups.
|
||||
|
||||
```js
|
||||
const core = require('@actions/core')
|
||||
|
||||
// Manually wrap output
|
||||
core.startGroup('Do some function')
|
||||
doSomeFunction()
|
||||
core.endGroup()
|
||||
|
||||
// Wrap an asynchronous function call
|
||||
const result = await core.group('Do something async', async () => {
|
||||
const response = await doSomeHTTPRequest()
|
||||
return response
|
||||
})
|
||||
```
|
||||
|
||||
#### Annotations
|
||||
|
||||
This library has 3 methods that will produce [annotations](https://docs.github.com/en/rest/reference/checks#create-a-check-run).
|
||||
```js
|
||||
core.error('This is a bad error. This will also fail the build.')
|
||||
|
||||
core.warning('Something went wrong, but it\'s not bad enough to fail the build.')
|
||||
|
||||
core.notice('Something happened that you might want to know about.')
|
||||
```
|
||||
|
||||
These will surface to the UI in the Actions page and on Pull Requests. They look something like this:
|
||||
|
||||

|
||||
|
||||
These annotations can also be attached to particular lines and columns of your source files to show exactly where a problem is occuring.
|
||||
|
||||
These options are:
|
||||
```typescript
|
||||
export interface AnnotationProperties {
|
||||
/**
|
||||
* A title for the annotation.
|
||||
*/
|
||||
title?: string
|
||||
|
||||
/**
|
||||
* The name of the file for which the annotation should be created.
|
||||
*/
|
||||
file?: string
|
||||
|
||||
/**
|
||||
* The start line for the annotation.
|
||||
*/
|
||||
startLine?: number
|
||||
|
||||
/**
|
||||
* The end line for the annotation. Defaults to `startLine` when `startLine` is provided.
|
||||
*/
|
||||
endLine?: number
|
||||
|
||||
/**
|
||||
* The start column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
||||
*/
|
||||
startColumn?: number
|
||||
|
||||
/**
|
||||
* The start column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
||||
* Defaults to `startColumn` when `startColumn` is provided.
|
||||
*/
|
||||
endColumn?: number
|
||||
}
|
||||
```
|
||||
|
||||
#### Styling output
|
||||
|
||||
Colored output is supported in the Action logs via standard [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code). 3/4 bit, 8 bit and 24 bit colors are all supported.
|
||||
|
||||
Foreground colors:
|
||||
|
||||
```js
|
||||
// 3/4 bit
|
||||
core.info('\u001b[35mThis foreground will be magenta')
|
||||
|
||||
// 8 bit
|
||||
core.info('\u001b[38;5;6mThis foreground will be cyan')
|
||||
|
||||
// 24 bit
|
||||
core.info('\u001b[38;2;255;0;0mThis foreground will be bright red')
|
||||
```
|
||||
|
||||
Background colors:
|
||||
|
||||
```js
|
||||
// 3/4 bit
|
||||
core.info('\u001b[43mThis background will be yellow');
|
||||
|
||||
// 8 bit
|
||||
core.info('\u001b[48;5;6mThis background will be cyan')
|
||||
|
||||
// 24 bit
|
||||
core.info('\u001b[48;2;255;0;0mThis background will be bright red')
|
||||
```
|
||||
|
||||
Special styles:
|
||||
|
||||
```js
|
||||
core.info('\u001b[1mBold text')
|
||||
core.info('\u001b[3mItalic text')
|
||||
core.info('\u001b[4mUnderlined text')
|
||||
```
|
||||
|
||||
ANSI escape codes can be combined with one another:
|
||||
|
||||
```js
|
||||
core.info('\u001b[31;46mRed foreground with a cyan background and \u001b[1mbold text at the end');
|
||||
```
|
||||
|
||||
> Note: Escape codes reset at the start of each line
|
||||
|
||||
```js
|
||||
core.info('\u001b[35mThis foreground will be magenta')
|
||||
core.info('This foreground will reset to the default')
|
||||
```
|
||||
|
||||
Manually typing escape codes can be a little difficult, but you can use third party modules such as [ansi-styles](https://github.com/chalk/ansi-styles).
|
||||
|
||||
```js
|
||||
const style = require('ansi-styles');
|
||||
core.info(style.color.ansi16m.hex('#abcdef') + 'Hello world!')
|
||||
```
|
||||
|
||||
#### Action state
|
||||
|
||||
You can use this library to save state and get state for sharing information between a given wrapper action:
|
||||
|
||||
**action.yml**:
|
||||
|
||||
```yaml
|
||||
name: 'Wrapper action sample'
|
||||
inputs:
|
||||
name:
|
||||
default: 'GitHub'
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'main.js'
|
||||
post: 'cleanup.js'
|
||||
```
|
||||
|
||||
In action's `main.js`:
|
||||
|
||||
```js
|
||||
const core = require('@actions/core');
|
||||
|
||||
core.saveState("pidToKill", 12345);
|
||||
```
|
||||
|
||||
In action's `cleanup.js`:
|
||||
|
||||
```js
|
||||
const core = require('@actions/core');
|
||||
|
||||
var pid = core.getState("pidToKill");
|
||||
|
||||
process.kill(pid);
|
||||
```
|
||||
|
||||
#### OIDC Token
|
||||
|
||||
You can use these methods to interact with the GitHub OIDC provider and get a JWT ID token which would help to get access token from third party cloud providers.
|
||||
|
||||
**Method Name**: getIDToken()
|
||||
|
||||
**Inputs**
|
||||
|
||||
audience : optional
|
||||
|
||||
**Outputs**
|
||||
|
||||
A [JWT](https://jwt.io/) ID Token
|
||||
|
||||
In action's `main.ts`:
|
||||
```js
|
||||
const core = require('@actions/core');
|
||||
async function getIDTokenAction(): Promise<void> {
|
||||
|
||||
const audience = core.getInput('audience', {required: false})
|
||||
|
||||
const id_token1 = await core.getIDToken() // ID Token with default audience
|
||||
const id_token2 = await core.getIDToken(audience) // ID token with custom audience
|
||||
|
||||
// this id_token can be used to get access token from third party cloud providers
|
||||
}
|
||||
getIDTokenAction()
|
||||
```
|
||||
|
||||
In action's `actions.yml`:
|
||||
|
||||
```yaml
|
||||
name: 'GetIDToken'
|
||||
description: 'Get ID token from Github OIDC provider'
|
||||
inputs:
|
||||
audience:
|
||||
description: 'Audience for which the ID token is intended for'
|
||||
required: false
|
||||
outputs:
|
||||
id_token1:
|
||||
description: 'ID token obtained from OIDC provider'
|
||||
id_token2:
|
||||
description: 'ID token obtained from OIDC provider'
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'dist/index.js'
|
||||
```
|
||||
|
||||
#### Filesystem path helpers
|
||||
|
||||
You can use these methods to manipulate file paths across operating systems.
|
||||
|
||||
The `toPosixPath` function converts input paths to Posix-style (Linux) paths.
|
||||
The `toWin32Path` function converts input paths to Windows-style paths. These
|
||||
functions work independently of the underlying runner operating system.
|
||||
|
||||
```js
|
||||
toPosixPath('\\foo\\bar') // => /foo/bar
|
||||
toWin32Path('/foo/bar') // => \foo\bar
|
||||
```
|
||||
|
||||
The `toPlatformPath` function converts input paths to the expected value on the runner's operating system.
|
||||
|
||||
```js
|
||||
// On a Windows runner.
|
||||
toPlatformPath('/foo/bar') // => \foo\bar
|
||||
|
||||
// On a Linux runner.
|
||||
toPlatformPath('\\foo\\bar') // => /foo/bar
|
||||
```
|
||||
15
node_modules/@actions/core/lib/command.d.ts
generated
vendored
Normal file
15
node_modules/@actions/core/lib/command.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
export interface CommandProperties {
|
||||
[key: string]: any;
|
||||
}
|
||||
/**
|
||||
* Commands
|
||||
*
|
||||
* Command Format:
|
||||
* ::name key=value,key=value::message
|
||||
*
|
||||
* Examples:
|
||||
* ::warning::This is the message
|
||||
* ::set-env name=MY_VAR::some value
|
||||
*/
|
||||
export declare function issueCommand(command: string, properties: CommandProperties, message: any): void;
|
||||
export declare function issue(name: string, message?: string): void;
|
||||
92
node_modules/@actions/core/lib/command.js
generated
vendored
Normal file
92
node_modules/@actions/core/lib/command.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
"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(require("os"));
|
||||
const utils_1 = require("./utils");
|
||||
/**
|
||||
* 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
|
||||
1
node_modules/@actions/core/lib/command.js.map
generated
vendored
Normal file
1
node_modules/@actions/core/lib/command.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAwB;AACxB,mCAAsC;AAWtC;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAC1B,OAAe,EACf,UAA6B,EAC7B,OAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAA;AAC/C,CAAC;AAPD,oCAOC;AAED,SAAgB,KAAK,CAAC,IAAY,EAAE,OAAO,GAAG,EAAE;IAC9C,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;AACjC,CAAC;AAFD,sBAEC;AAED,MAAM,UAAU,GAAG,IAAI,CAAA;AAEvB,MAAM,OAAO;IAKX,YAAY,OAAe,EAAE,UAA6B,EAAE,OAAe;QACzE,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,GAAG,iBAAiB,CAAA;SAC5B;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,QAAQ;QACN,IAAI,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,OAAO,CAAA;QAEtC,IAAI,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;YAC9D,MAAM,IAAI,GAAG,CAAA;YACb,IAAI,KAAK,GAAG,IAAI,CAAA;YAChB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE;gBACjC,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;oBACvC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;oBAChC,IAAI,GAAG,EAAE;wBACP,IAAI,KAAK,EAAE;4BACT,KAAK,GAAG,KAAK,CAAA;yBACd;6BAAM;4BACL,MAAM,IAAI,GAAG,CAAA;yBACd;wBAED,MAAM,IAAI,GAAG,GAAG,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAA;qBAC1C;iBACF;aACF;SACF;QAED,MAAM,IAAI,GAAG,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAA;QACpD,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAED,SAAS,UAAU,CAAC,CAAM;IACxB,OAAO,sBAAc,CAAC,CAAC,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,SAAS,cAAc,CAAC,CAAM;IAC5B,OAAO,sBAAc,CAAC,CAAC,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AACzB,CAAC"}
|
||||
198
node_modules/@actions/core/lib/core.d.ts
generated
vendored
Normal file
198
node_modules/@actions/core/lib/core.d.ts
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Interface for getInput options
|
||||
*/
|
||||
export interface InputOptions {
|
||||
/** Optional. Whether the input is required. If required and not present, will throw. Defaults to false */
|
||||
required?: boolean;
|
||||
/** Optional. Whether leading/trailing whitespace will be trimmed for the input. Defaults to true */
|
||||
trimWhitespace?: boolean;
|
||||
}
|
||||
/**
|
||||
* The code to exit an action
|
||||
*/
|
||||
export declare enum ExitCode {
|
||||
/**
|
||||
* A code indicating that the action was successful
|
||||
*/
|
||||
Success = 0,
|
||||
/**
|
||||
* A code indicating that the action was a failure
|
||||
*/
|
||||
Failure = 1
|
||||
}
|
||||
/**
|
||||
* Optional properties that can be sent with annotatation commands (notice, error, and warning)
|
||||
* See: https://docs.github.com/en/rest/reference/checks#create-a-check-run for more information about annotations.
|
||||
*/
|
||||
export interface AnnotationProperties {
|
||||
/**
|
||||
* A title for the annotation.
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* The path of the file for which the annotation should be created.
|
||||
*/
|
||||
file?: string;
|
||||
/**
|
||||
* The start line for the annotation.
|
||||
*/
|
||||
startLine?: number;
|
||||
/**
|
||||
* The end line for the annotation. Defaults to `startLine` when `startLine` is provided.
|
||||
*/
|
||||
endLine?: number;
|
||||
/**
|
||||
* The start column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
||||
*/
|
||||
startColumn?: number;
|
||||
/**
|
||||
* The start column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
||||
* Defaults to `startColumn` when `startColumn` is provided.
|
||||
*/
|
||||
endColumn?: number;
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export declare function exportVariable(name: string, val: any): void;
|
||||
/**
|
||||
* Registers a secret which will get masked from logs
|
||||
* @param secret value of the secret
|
||||
*/
|
||||
export declare function setSecret(secret: string): void;
|
||||
/**
|
||||
* Prepends inputPath to the PATH (for this action and future actions)
|
||||
* @param inputPath
|
||||
*/
|
||||
export declare function addPath(inputPath: string): void;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export declare function getInput(name: string, options?: InputOptions): string;
|
||||
/**
|
||||
* 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[]
|
||||
*
|
||||
*/
|
||||
export declare function getMultilineInput(name: string, options?: InputOptions): string[];
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export declare function getBooleanInput(name: string, options?: InputOptions): boolean;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export declare function setOutput(name: string, value: any): void;
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
export declare function setCommandEcho(enabled: boolean): void;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export declare function setFailed(message: string | Error): void;
|
||||
/**
|
||||
* Gets whether Actions Step Debug is on or not
|
||||
*/
|
||||
export declare function isDebug(): boolean;
|
||||
/**
|
||||
* Writes debug message to user log
|
||||
* @param message debug message
|
||||
*/
|
||||
export declare function debug(message: string): void;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
export declare function error(message: string | Error, properties?: AnnotationProperties): void;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
export declare function warning(message: string | Error, properties?: AnnotationProperties): void;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
export declare function notice(message: string | Error, properties?: AnnotationProperties): void;
|
||||
/**
|
||||
* Writes info to log with console.log.
|
||||
* @param message info message
|
||||
*/
|
||||
export declare function info(message: string): void;
|
||||
/**
|
||||
* Begin an output group.
|
||||
*
|
||||
* Output until the next `groupEnd` will be foldable in this group
|
||||
*
|
||||
* @param name The name of the output group
|
||||
*/
|
||||
export declare function startGroup(name: string): void;
|
||||
/**
|
||||
* End an output group.
|
||||
*/
|
||||
export declare function endGroup(): void;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export declare function group<T>(name: string, fn: () => Promise<T>): Promise<T>;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export declare function saveState(name: string, value: any): void;
|
||||
/**
|
||||
* Gets the value of an state set by this action's main execution.
|
||||
*
|
||||
* @param name name of the state to get
|
||||
* @returns string
|
||||
*/
|
||||
export declare function getState(name: string): string;
|
||||
export declare function getIDToken(aud?: string): Promise<string>;
|
||||
/**
|
||||
* Summary exports
|
||||
*/
|
||||
export { summary } from './summary';
|
||||
/**
|
||||
* @deprecated use core.summary
|
||||
*/
|
||||
export { markdownSummary } from './summary';
|
||||
/**
|
||||
* Path exports
|
||||
*/
|
||||
export { toPosixPath, toWin32Path, toPlatformPath } from './path-utils';
|
||||
337
node_modules/@actions/core/lib/core.js
generated
vendored
Normal file
337
node_modules/@actions/core/lib/core.js
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
"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 = require("./command");
|
||||
const file_command_1 = require("./file-command");
|
||||
const utils_1 = require("./utils");
|
||||
const os = __importStar(require("os"));
|
||||
const path = __importStar(require("path"));
|
||||
const uuid_1 = require("uuid");
|
||||
const oidc_utils_1 = require("./oidc-utils");
|
||||
/**
|
||||
* 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) {
|
||||
const delimiter = `ghadelimiter_${uuid_1.v4()}`;
|
||||
// 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 (name.includes(delimiter)) {
|
||||
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
|
||||
}
|
||||
if (convertedVal.includes(delimiter)) {
|
||||
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
|
||||
}
|
||||
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
|
||||
file_command_1.issueCommand('ENV', commandValue);
|
||||
}
|
||||
else {
|
||||
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.issueCommand('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 !== '');
|
||||
return inputs;
|
||||
}
|
||||
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) {
|
||||
process.stdout.write(os.EOL);
|
||||
command_1.issueCommand('set-output', { name }, 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) {
|
||||
command_1.issueCommand('save-state', { name }, 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 = require("./summary");
|
||||
Object.defineProperty(exports, "summary", { enumerable: true, get: function () { return summary_1.summary; } });
|
||||
/**
|
||||
* @deprecated use core.summary
|
||||
*/
|
||||
var summary_2 = require("./summary");
|
||||
Object.defineProperty(exports, "markdownSummary", { enumerable: true, get: function () { return summary_2.markdownSummary; } });
|
||||
/**
|
||||
* Path exports
|
||||
*/
|
||||
var path_utils_1 = require("./path-utils");
|
||||
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
|
||||
1
node_modules/@actions/core/lib/core.js.map
generated
vendored
Normal file
1
node_modules/@actions/core/lib/core.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/@actions/core/lib/file-command.d.ts
generated
vendored
Normal file
1
node_modules/@actions/core/lib/file-command.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export declare function issueCommand(command: string, message: any): void;
|
||||
42
node_modules/@actions/core/lib/file-command.js
generated
vendored
Normal file
42
node_modules/@actions/core/lib/file-command.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
"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.issueCommand = void 0;
|
||||
// We use any as a valid input type
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
const fs = __importStar(require("fs"));
|
||||
const os = __importStar(require("os"));
|
||||
const utils_1 = require("./utils");
|
||||
function issueCommand(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.issueCommand = issueCommand;
|
||||
//# sourceMappingURL=file-command.js.map
|
||||
1
node_modules/@actions/core/lib/file-command.js.map
generated
vendored
Normal file
1
node_modules/@actions/core/lib/file-command.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"file-command.js","sourceRoot":"","sources":["../src/file-command.ts"],"names":[],"mappings":";AAAA,uCAAuC;;;;;;;;;;;;;;;;;;;;;;AAEvC,mCAAmC;AACnC,uDAAuD;AAEvD,uCAAwB;AACxB,uCAAwB;AACxB,mCAAsC;AAEtC,SAAgB,YAAY,CAAC,OAAe,EAAE,OAAY;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAA;IACjD,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,IAAI,KAAK,CACb,wDAAwD,OAAO,EAAE,CAClE,CAAA;KACF;IACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;KACrD;IAED,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,sBAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;QACjE,QAAQ,EAAE,MAAM;KACjB,CAAC,CAAA;AACJ,CAAC;AAdD,oCAcC"}
|
||||
7
node_modules/@actions/core/lib/oidc-utils.d.ts
generated
vendored
Normal file
7
node_modules/@actions/core/lib/oidc-utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export declare class OidcClient {
|
||||
private static createHttpClient;
|
||||
private static getRequestToken;
|
||||
private static getIDTokenUrl;
|
||||
private static getCall;
|
||||
static getIDToken(audience?: string): Promise<string>;
|
||||
}
|
||||
77
node_modules/@actions/core/lib/oidc-utils.js
generated
vendored
Normal file
77
node_modules/@actions/core/lib/oidc-utils.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
"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 = require("@actions/http-client");
|
||||
const auth_1 = require("@actions/http-client/lib/auth");
|
||||
const core_1 = require("./core");
|
||||
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.result.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
|
||||
1
node_modules/@actions/core/lib/oidc-utils.js.map
generated
vendored
Normal file
1
node_modules/@actions/core/lib/oidc-utils.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"oidc-utils.js","sourceRoot":"","sources":["../src/oidc-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;AAGA,sDAA+C;AAC/C,wDAAqE;AACrE,iCAAuC;AAKvC,MAAa,UAAU;IACb,MAAM,CAAC,gBAAgB,CAC7B,UAAU,GAAG,IAAI,EACjB,QAAQ,GAAG,EAAE;QAEb,MAAM,cAAc,GAAmB;YACrC,YAAY,EAAE,UAAU;YACxB,UAAU,EAAE,QAAQ;SACrB,CAAA;QAED,OAAO,IAAI,wBAAU,CACnB,qBAAqB,EACrB,CAAC,IAAI,8BAAuB,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC,EAC3D,cAAc,CACf,CAAA;IACH,CAAC;IAEO,MAAM,CAAC,eAAe;QAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;QAC3D,IAAI,CAAC,KAAK,EAAE;YACV,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAA;SACF;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAEO,MAAM,CAAC,aAAa;QAC1B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;QAC9D,IAAI,CAAC,UAAU,EAAE;YACf,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAA;SAC3E;QACD,OAAO,UAAU,CAAA;IACnB,CAAC;IAEO,MAAM,CAAO,OAAO,CAAC,YAAoB;;;YAC/C,MAAM,UAAU,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAA;YAEhD,MAAM,GAAG,GAAG,MAAM,UAAU;iBACzB,OAAO,CAAgB,YAAY,CAAC;iBACpC,KAAK,CAAC,KAAK,CAAC,EAAE;gBACb,MAAM,IAAI,KAAK,CACb;uBACa,KAAK,CAAC,UAAU;yBACd,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CACtC,CAAA;YACH,CAAC,CAAC,CAAA;YAEJ,MAAM,QAAQ,SAAG,GAAG,CAAC,MAAM,0CAAE,KAAK,CAAA;YAClC,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;aACjE;YACD,OAAO,QAAQ,CAAA;;KAChB;IAED,MAAM,CAAO,UAAU,CAAC,QAAiB;;YACvC,IAAI;gBACF,gDAAgD;gBAChD,IAAI,YAAY,GAAW,UAAU,CAAC,aAAa,EAAE,CAAA;gBACrD,IAAI,QAAQ,EAAE;oBACZ,MAAM,eAAe,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAA;oBACpD,YAAY,GAAG,GAAG,YAAY,aAAa,eAAe,EAAE,CAAA;iBAC7D;gBAED,YAAK,CAAC,mBAAmB,YAAY,EAAE,CAAC,CAAA;gBAExC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;gBACvD,gBAAS,CAAC,QAAQ,CAAC,CAAA;gBACnB,OAAO,QAAQ,CAAA;aAChB;YAAC,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;aACnD;QACH,CAAC;KAAA;CACF;AAzED,gCAyEC"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user