Skip to content

chore(deps): npm audit fix — clear 8 Dependabot alerts on validator lockfile #2320

chore(deps): npm audit fix — clear 8 Dependabot alerts on validator lockfile

chore(deps): npm audit fix — clear 8 Dependabot alerts on validator lockfile #2320

Workflow file for this run

name: Validate Recipe (Unit Test)
on: [pull_request, workflow_dispatch]
permissions:
contents: read
jobs:
log-context:
runs-on: ubuntu-latest
steps:
# Dump all contexts
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Dump job context
env:
JOB_CONTEXT: ${{ toJson(job) }}
run: echo "$JOB_CONTEXT"
- name: Dump steps context
env:
STEPS_CONTEXT: ${{ toJson(steps) }}
run: echo "$STEPS_CONTEXT"
- name: Dump runner context
env:
RUNNER_CONTEXT: ${{ toJson(runner) }}
run: echo "$RUNNER_CONTEXT"
- name: Dump strategy context
env:
STRATEGY_CONTEXT: ${{ toJson(strategy) }}
run: echo "$STRATEGY_CONTEXT"
- name: Dump matrix context
env:
MATRIX_CONTEXT: ${{ toJson(matrix) }}
run: echo "$MATRIX_CONTEXT"
validate-schema:
name: Validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: "14"
- name: Install dependencies
run: npm --prefix validator install
- name: Validate
run: npm --prefix validator run check
get-test-definition-files:
name: Get Test Definition Files
needs: [validate-schema]
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.get-test-definition-files.outputs.result }}
needs_system_identity: ${{ steps.filter-agent-control.outputs.needs_system_identity }}
needs_system_identity_eu: ${{ steps.filter-agent-control.outputs.needs_system_identity_eu }}
needs_system_identity_jp: ${{ steps.filter-agent-control.outputs.needs_system_identity_jp }}
files_list: ${{ steps.get-test-definition-files.outputs.files_list }}
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Ensure no fork repo
if: ${{ github.event_name == 'pull_request' }}
run: |
SOURCE_NAME=$(echo ${{ github.event.pull_request.head.repo.full_name }})
REMOTE_NAME=$(echo ${{ github.event.pull_request.base.repo.full_name }})
if [ $SOURCE_NAME != $REMOTE_NAME ]; then
echo "PR should be created from a branch on the source repo, not from a fork, so the E2E tests can run. If you need access please reach out to the #help-virtuoso channel."
exit 1
fi
# 1) Check for all incoming changes to files under `recipes` directory
- name: Get Changed Files
id: getfile
run: |
RECIPES=$(git diff --name-only --diff-filter=AMR ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | grep "recipes" || true)
if [ -z "$RECIPES" ]; then
echo "No recipe files detected."
else
echo "RECIPES<<EOF" >> $GITHUB_ENV
echo $RECIPES >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
fi
TEST_DEFINITIONS=$(git diff --name-only --diff-filter=AMR ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | grep "test/definitions" || true)
if [ -z "$TEST_DEFINITIONS" ]; then
echo "No test definitions files detected."
else
echo "TEST_DEFINITIONS<<EOF" >> $GITHUB_ENV
echo $TEST_DEFINITIONS >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
fi
# 2) Use javascript action / yq to pull the test definition file from the recipe yaml
- name: Get Test Definition Files
id: get-test-definition-files
uses: actions/github-script@v3
with:
script: |
const fs = require('fs');
const fsp = fs.promises;
const path = require('path');
// readdir recursive directory search
const { resolve } = path;
const { readdir } = fsp;
async function getFiles(dir) {
const dirents = await readdir(dir, { withFileTypes: true });
const files = await Promise.all(dirents.map((dirent) => {
const res = path.join(dir, dirent.name);
return dirent.isDirectory() ? getFiles(res) : res;
}));
return Array.prototype.concat(...files);
}
var outputTestFiles = []
if (process.env.TEST_DEFINITIONS != '') {
// Get incoming added/updated test definitions files
const testDefinitionFiles = process.env.TEST_DEFINITIONS ? process.env.TEST_DEFINITIONS.split(' ') : []
console.log(`Detected Test Definitions Files: ${JSON.stringify(testDefinitionFiles, null, 2)}`)
testDefinitionFiles.forEach(testDefinitionFile => {
if (!outputTestFiles.includes(testDefinitionFile)) {
outputTestFiles.push(testDefinitionFile)
}
})
}
if (process.env.RECIPES != '') {
// Get incoming added/updated recipe files
const recipeFiles = process.env.RECIPES ? process.env.RECIPES.split(' ') : []
console.log(`Detected Recipe Files: ${JSON.stringify(recipeFiles, null, 2)}`)
if (recipeFiles.length) {
// Get all deploy config files
const deployConfigsUS = await getFiles('test/definitions');
const deployConfigsEU = await getFiles('test/definitions-eu');
const deployConfigsJP = await getFiles('test/definitions-jp');
const deployConfigs = deployConfigsUS.concat(deployConfigsEU).concat(deployConfigsJP);
console.log("All deployConfigs:", deployConfigs);
// Build up list of Deploy Configs to run based on recipes that have changed
const testDefinitionFilesToRun = deployConfigs.reduce((p, c) => {
const contents = require(`${process.env.GITHUB_WORKSPACE}/${c}`);
var recipes = []
if (contents.instrumentations && contents.instrumentations.resources) {
contents.instrumentations.resources.forEach(resource => {
if (resource.params && resource.params.recipe_content_url) {
recipes = recipes.concat(resource.params.recipe_content_url);
}
});
}
// returns list of matched recipes from the deploy config file
const matchedRecipes = recipes.filter(
(r) => recipeFiles.filter((rf) => r.includes(rf)).length > 0
);
// Add the current deploy config file to our output if there were matches
return matchedRecipes.length > 0 ? [`${c}`, ...p] : p;
}, []);
console.log('testDefinitionFilesToRun:', testDefinitionFilesToRun);
testDefinitionFilesToRun.forEach(testDefinitionFile => {
if (!outputTestFiles.includes(testDefinitionFile)) {
outputTestFiles.push(testDefinitionFile)
}
})
}
}
const outputTestFilesMap = outputTestFiles.map(testDefinitionFile => {
return { testDefinitionFile }
})
const output = {
"include": outputTestFilesMap
}
console.log('Matrix output:', JSON.stringify(output, null, 2));
core.setOutput('files_list', JSON.stringify(outputTestFiles));
return output;
- name: Check if agent-control test definitions exist
id: filter-agent-control
run: |
FILES=$(echo '${{ steps.get-test-definition-files.outputs.files_list }}' | jq -r '.[]')
# needs_system_identity = US system identity — for definitions/agent-control/
# needs_system_identity_eu = EU system identity — for definitions-eu/agent-control/
# needs_system_identity_jp = JP system identity — for definitions-jp/agent-control/
NEEDS_IDENTITY=false
NEEDS_IDENTITY_EU=false
NEEDS_IDENTITY_JP=false
for FILE in $FILES; do
if [[ "$FILE" == test/definitions-eu/agent-control/* ]]; then
NEEDS_IDENTITY_EU=true
elif [[ "$FILE" == test/definitions-jp/agent-control/* ]]; then
NEEDS_IDENTITY_JP=true
elif [[ "$FILE" == test/definitions/agent-control/* ]]; then
NEEDS_IDENTITY=true
fi
done
echo "needs_system_identity=$NEEDS_IDENTITY" >> $GITHUB_OUTPUT
echo "needs_system_identity_eu=$NEEDS_IDENTITY_EU" >> $GITHUB_OUTPUT
echo "needs_system_identity_jp=$NEEDS_IDENTITY_JP" >> $GITHUB_OUTPUT
create-system-identity:
name: Create System Identity
runs-on: ubuntu-latest
needs: [get-test-definition-files]
if: needs.get-test-definition-files.outputs.needs_system_identity == 'true'
outputs:
CLIENT_ID: ${{ steps.create-identity.outputs.CLIENT_ID }}
CLIENT_SECRET: ${{ steps.create-identity.outputs.CLIENT_SECRET }}
SYSTEM_IDENTITY_ID: ${{ steps.create-identity.outputs.SYSTEM_IDENTITY_ID }}
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Write Test Definition File JSON to file
env:
USER_JSON: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG }}
run: |
mkdir -p configs
echo "$USER_JSON" > configs/gitusdkr${{ github.run_id }}.json
- name: Extract New Relic Credentials
id: extract-nr-creds
run: |
NR_API_KEY=$(jq -r -e '.credentials.newrelic.nrPersonalApiKey' configs/gitusdkr${{ github.run_id }}.json)
NR_ORG_ID=$(jq -r -e '.credentials.newrelic.nrOrganizationId' configs/gitusdkr${{ github.run_id }}.json)
echo "::add-mask::$NR_API_KEY"
echo "::add-mask::$NR_ORG_ID"
echo "NR_API_KEY=$NR_API_KEY" >> $GITHUB_OUTPUT
echo "NR_ORG_ID=$NR_ORG_ID" >> $GITHUB_OUTPUT
- name: Create System Identity
id: create-identity
run: |
RESPONSE=$(curl -X POST https://api.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"mutation { systemIdentityCreate( name: \\\"open-install-library-e2e-us\\\" organizationId: \\\"${{ steps.extract-nr-creds.outputs.NR_ORG_ID }}\\\" ) { id clientId clientSecret } }\"
}")
CLIENT_ID=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.clientId')
CLIENT_SECRET=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.clientSecret')
SYSTEM_IDENTITY_ID=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.id')
echo "CLIENT_ID=$CLIENT_ID" >> $GITHUB_OUTPUT
echo "CLIENT_SECRET=$CLIENT_SECRET" >> $GITHUB_OUTPUT
echo "SYSTEM_IDENTITY_ID=$SYSTEM_IDENTITY_ID" >> $GITHUB_OUTPUT
- name: Get NR Control Group ID
id: get-nr-control-group
run: |
RESPONSE=$(curl -X POST https://api.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"query getSystemIdentityGroupsQuery(\$organizationId: ID!, \$name: String!) { customerAdministration { systemIdentityGroups(filter: {name: {eq: \$name}, organizationId: {eq: \$organizationId}}) { items { id } totalCount } } }\",
\"variables\": { \"organizationId\": \"${{ steps.extract-nr-creds.outputs.NR_ORG_ID }}\", \"name\": \"NR Control Group\" }
}")
GROUP_ID=$(echo "$RESPONSE" | jq -e -r '.data.customerAdministration.systemIdentityGroups.items[0].id')
echo "GROUP_ID=$GROUP_ID" >> $GITHUB_OUTPUT
- name: Add System Identity to NR Control Group
if: steps.get-nr-control-group.outputs.GROUP_ID != ''
run: |
curl -X POST https://api.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"mutation createSystemIdentityAddToGroupsMutation(\$systemIdentityIds: [ID!]!, \$systemIdentityGroupIds: [ID!]!) { systemIdentityAddToGroups(systemIdentityIds: \$systemIdentityIds, systemIdentityGroupIds: \$systemIdentityGroupIds) { systemIdentityGroups { id } } }\",
\"variables\": { \"systemIdentityIds\": [\"${{ steps.create-identity.outputs.SYSTEM_IDENTITY_ID }}\"], \"systemIdentityGroupIds\": [\"${{ steps.get-nr-control-group.outputs.GROUP_ID }}\"] }
}"
create-system-identity-eu:
name: Create System Identity (EU)
runs-on: ubuntu-latest
needs: [get-test-definition-files]
if: needs.get-test-definition-files.outputs.needs_system_identity_eu == 'true'
outputs:
CLIENT_ID: ${{ steps.create-identity.outputs.CLIENT_ID }}
CLIENT_SECRET: ${{ steps.create-identity.outputs.CLIENT_SECRET }}
SYSTEM_IDENTITY_ID: ${{ steps.create-identity.outputs.SYSTEM_IDENTITY_ID }}
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Write Test Definition File JSON to file (EU)
env:
USER_JSON: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG_EU }}
run: |
mkdir -p configs
echo "$USER_JSON" > configs/gitusdkr${{ github.run_id }}.json
- name: Extract New Relic Credentials (EU)
id: extract-nr-creds
run: |
NR_API_KEY=$(jq -r -e '.credentials.newrelic.nrPersonalApiKey' configs/gitusdkr${{ github.run_id }}.json)
NR_ORG_ID=$(jq -r -e '.credentials.newrelic.nrOrganizationId' configs/gitusdkr${{ github.run_id }}.json)
echo "::add-mask::$NR_API_KEY"
echo "::add-mask::$NR_ORG_ID"
echo "NR_API_KEY=$NR_API_KEY" >> $GITHUB_OUTPUT
echo "NR_ORG_ID=$NR_ORG_ID" >> $GITHUB_OUTPUT
- name: Create System Identity (EU)
id: create-identity
run: |
RESPONSE=$(curl -X POST https://api.eu.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"mutation { systemIdentityCreate( name: \\\"open-install-library-e2e-eu\\\" organizationId: \\\"${{ steps.extract-nr-creds.outputs.NR_ORG_ID }}\\\" ) { id clientId clientSecret } }\"
}")
CLIENT_ID=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.clientId')
CLIENT_SECRET=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.clientSecret')
SYSTEM_IDENTITY_ID=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.id')
echo "CLIENT_ID=$CLIENT_ID" >> $GITHUB_OUTPUT
echo "CLIENT_SECRET=$CLIENT_SECRET" >> $GITHUB_OUTPUT
echo "SYSTEM_IDENTITY_ID=$SYSTEM_IDENTITY_ID" >> $GITHUB_OUTPUT
- name: Get NR Control Group ID (EU)
id: get-nr-control-group
run: |
RESPONSE=$(curl -X POST https://api.eu.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"query getSystemIdentityGroupsQuery(\$organizationId: ID!, \$name: String!) { customerAdministration { systemIdentityGroups(filter: {name: {eq: \$name}, organizationId: {eq: \$organizationId}}) { items { id } totalCount } } }\",
\"variables\": { \"organizationId\": \"${{ steps.extract-nr-creds.outputs.NR_ORG_ID }}\", \"name\": \"NR Control Group\" }
}")
GROUP_ID=$(echo "$RESPONSE" | jq -e -r '.data.customerAdministration.systemIdentityGroups.items[0].id')
echo "GROUP_ID=$GROUP_ID" >> $GITHUB_OUTPUT
- name: Add System Identity to NR Control Group (EU)
if: steps.get-nr-control-group.outputs.GROUP_ID != ''
run: |
curl -X POST https://api.eu.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"mutation createSystemIdentityAddToGroupsMutation(\$systemIdentityIds: [ID!]!, \$systemIdentityGroupIds: [ID!]!) { systemIdentityAddToGroups(systemIdentityIds: \$systemIdentityIds, systemIdentityGroupIds: \$systemIdentityGroupIds) { systemIdentityGroups { id } } }\",
\"variables\": { \"systemIdentityIds\": [\"${{ steps.create-identity.outputs.SYSTEM_IDENTITY_ID }}\"], \"systemIdentityGroupIds\": [\"${{ steps.get-nr-control-group.outputs.GROUP_ID }}\"] }
}"
create-system-identity-jp:
name: Create System Identity (JP)
runs-on: ubuntu-latest
needs: [get-test-definition-files]
if: needs.get-test-definition-files.outputs.needs_system_identity_jp == 'true'
outputs:
CLIENT_ID: ${{ steps.create-identity.outputs.CLIENT_ID }}
CLIENT_SECRET: ${{ steps.create-identity.outputs.CLIENT_SECRET }}
SYSTEM_IDENTITY_ID: ${{ steps.create-identity.outputs.SYSTEM_IDENTITY_ID }}
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Write Test Definition File JSON to file (JP)
env:
USER_JSON: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG_JP }}
run: |
mkdir -p configs
echo "$USER_JSON" > configs/gitusdkr${{ github.run_id }}.json
- name: Extract New Relic Credentials (JP)
id: extract-nr-creds
run: |
NR_API_KEY=$(jq -r -e '.credentials.newrelic.nrPersonalApiKey' configs/gitusdkr${{ github.run_id }}.json)
NR_ORG_ID=$(jq -r -e '.credentials.newrelic.nrOrganizationId' configs/gitusdkr${{ github.run_id }}.json)
echo "::add-mask::$NR_API_KEY"
echo "::add-mask::$NR_ORG_ID"
echo "NR_API_KEY=$NR_API_KEY" >> $GITHUB_OUTPUT
echo "NR_ORG_ID=$NR_ORG_ID" >> $GITHUB_OUTPUT
- name: Create System Identity (JP)
id: create-identity
run: |
RESPONSE=$(curl -X POST https://api.jp.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"mutation { systemIdentityCreate( name: \\\"open-install-library-e2e-jp\\\" organizationId: \\\"${{ steps.extract-nr-creds.outputs.NR_ORG_ID }}\\\" ) { id clientId clientSecret } }\"
}")
CLIENT_ID=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.clientId')
CLIENT_SECRET=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.clientSecret')
SYSTEM_IDENTITY_ID=$(echo "$RESPONSE" | jq -e -r '.data.systemIdentityCreate.id')
echo "CLIENT_ID=$CLIENT_ID" >> $GITHUB_OUTPUT
echo "CLIENT_SECRET=$CLIENT_SECRET" >> $GITHUB_OUTPUT
echo "SYSTEM_IDENTITY_ID=$SYSTEM_IDENTITY_ID" >> $GITHUB_OUTPUT
- name: Get NR Control Group ID (JP)
id: get-nr-control-group
run: |
RESPONSE=$(curl -X POST https://api.jp.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"query getSystemIdentityGroupsQuery(\$organizationId: ID!, \$name: String!) { customerAdministration { systemIdentityGroups(filter: {name: {eq: \$name}, organizationId: {eq: \$organizationId}}) { items { id } totalCount } } }\",
\"variables\": { \"organizationId\": \"${{ steps.extract-nr-creds.outputs.NR_ORG_ID }}\", \"name\": \"NR Control Group\" }
}")
GROUP_ID=$(echo "$RESPONSE" | jq -e -r '.data.customerAdministration.systemIdentityGroups.items[0].id')
echo "GROUP_ID=$GROUP_ID" >> $GITHUB_OUTPUT
- name: Add System Identity to NR Control Group (JP)
if: steps.get-nr-control-group.outputs.GROUP_ID != ''
run: |
curl -X POST https://api.jp.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: ${{ steps.extract-nr-creds.outputs.NR_API_KEY }}" \
--data-raw "{
\"query\": \"mutation createSystemIdentityAddToGroupsMutation(\$systemIdentityIds: [ID!]!, \$systemIdentityGroupIds: [ID!]!) { systemIdentityAddToGroups(systemIdentityIds: \$systemIdentityIds, systemIdentityGroupIds: \$systemIdentityGroupIds) { systemIdentityGroups { id } } }\",
\"variables\": { \"systemIdentityIds\": [\"${{ steps.create-identity.outputs.SYSTEM_IDENTITY_ID }}\"], \"systemIdentityGroupIds\": [\"${{ steps.get-nr-control-group.outputs.GROUP_ID }}\"] }
}"
test-deploy-recipe:
name: Test Deploy Recipe
needs: [get-test-definition-files, create-system-identity, create-system-identity-eu, create-system-identity-jp]
if: ${{ always() && fromJSON(needs.get-test-definition-files.outputs.matrix).include[0] && (needs.create-system-identity.result == 'success' || needs.create-system-identity.result == 'skipped') && (needs.create-system-identity-eu.result == 'success' || needs.create-system-identity-eu.result == 'skipped') && (needs.create-system-identity-jp.result == 'success' || needs.create-system-identity-jp.result == 'skipped') }}
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJSON(needs.get-test-definition-files.outputs.matrix) }}
fail-fast: false
max-parallel: 10
env:
MATRIX: ${{ toJSON(matrix) }}
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Mask and set system identity credentials (US — for definitions/)
if: ${{ needs.create-system-identity.result == 'success' && !startsWith(matrix.testDefinitionFile, 'test/definitions-eu/') && !startsWith(matrix.testDefinitionFile, 'test/definitions-jp/') }}
run: |
echo "::add-mask::${{ needs.create-system-identity.outputs.CLIENT_ID }}"
echo "::add-mask::${{ needs.create-system-identity.outputs.CLIENT_SECRET }}"
echo "SYSTEM_IDENTITY_CLIENT_ID=${{ needs.create-system-identity.outputs.CLIENT_ID }}" >> $GITHUB_ENV
echo "SYSTEM_IDENTITY_CLIENT_SECRET=${{ needs.create-system-identity.outputs.CLIENT_SECRET }}" >> $GITHUB_ENV
- name: Mask and set system identity credentials (EU — for definitions-eu/)
if: ${{ needs.create-system-identity-eu.result == 'success' && startsWith(matrix.testDefinitionFile, 'test/definitions-eu/') }}
run: |
echo "::add-mask::${{ needs.create-system-identity-eu.outputs.CLIENT_ID }}"
echo "::add-mask::${{ needs.create-system-identity-eu.outputs.CLIENT_SECRET }}"
echo "SYSTEM_IDENTITY_CLIENT_ID=${{ needs.create-system-identity-eu.outputs.CLIENT_ID }}" >> $GITHUB_ENV
echo "SYSTEM_IDENTITY_CLIENT_SECRET=${{ needs.create-system-identity-eu.outputs.CLIENT_SECRET }}" >> $GITHUB_ENV
- name: Mask and set system identity credentials (JP — for definitions-jp/)
if: ${{ needs.create-system-identity-jp.result == 'success' && startsWith(matrix.testDefinitionFile, 'test/definitions-jp/') }}
run: |
echo "::add-mask::${{ needs.create-system-identity-jp.outputs.CLIENT_ID }}"
echo "::add-mask::${{ needs.create-system-identity-jp.outputs.CLIENT_SECRET }}"
echo "SYSTEM_IDENTITY_CLIENT_ID=${{ needs.create-system-identity-jp.outputs.CLIENT_ID }}" >> $GITHUB_ENV
echo "SYSTEM_IDENTITY_CLIENT_SECRET=${{ needs.create-system-identity-jp.outputs.CLIENT_SECRET }}" >> $GITHUB_ENV
- name: Update Test Definition Files URLs
id: get-test-definition-files
env:
TEST_DEFINITION_FILE: ${{ matrix.testDefinitionFile }}
uses: actions/github-script@v3
with:
script: |
const fs = require('fs');
const fsp = fs.promises;
const path = require('path');
// before returning, we need to edit the deploy config files in-place so they
// use the right URLs from the branch
async function getDeployConfigFile(file, outputDir) {
const data = await fsp.readFile(path.join(outputDir, file));
return JSON.parse(data);
}
// Get testDefinitonFile from MATRIX env var
const testDefinitionFile = process.env.TEST_DEFINITION_FILE;
console.log(`Detected Deploy Config: ${JSON.stringify(testDefinitionFile, null, 2)}`)
// Update URLs to use branch this PR is opened with
const data = await getDeployConfigFile(testDefinitionFile, process.env.GITHUB_WORKSPACE);
// Update github source URLs with branch name
let jsonContent = JSON.stringify(data, null, 2);
const replacementString = `$1$2-b ${process.env.GITHUB_HEAD_REF} $3$4`;
const sourceRepositoryRegex = /(.*)(\")(https:\/\/github.com\/newrelic\/open-install-library)(.*)/gi;
jsonContent = jsonContent.replace(sourceRepositoryRegex, replacementString);
// Update raw URLs with branch name
const replacementString2 = `$1${process.env.GITHUB_HEAD_REF}$3`;
const sourceRepositoryRegex2 = /(raw.githubusercontent.com\/newrelic\/open-install-library\/)(main)(\/newrelic\/recipes\/)*/gi;
jsonContent = jsonContent.replace(sourceRepositoryRegex2, replacementString2);
// Write file back to workspace
const outputPath = `${process.env.GITHUB_WORKSPACE}/${testDefinitionFile}`;
console.log("Updated Deploy Config File: ", outputPath);
console.log("Deploy Config content: ", jsonContent);
fs.writeFileSync(outputPath, jsonContent);
return testDefinitionFile;
- name: Write AWS Certificate to File
env:
AWS_PEM: ${{ secrets.GIT_DEPLOYER_CANADA_AWS_PEM }}
run: |
mkdir -p configs
rm -f configs/gitdeployerCanada.pem
echo "$AWS_PEM" > configs/gitdeployerCanada.pem
sudo chmod 400 configs/gitdeployerCanada.pem
- name: Write Test Definition File JSON to file (region-aware)
env:
USER_JSON_US: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG }}
USER_JSON_EU: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG_EU }}
USER_JSON_JP: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG_JP }}
TEST_FILE: ${{ matrix.testDefinitionFile }}
run: |
# Route deployer config by test file path:
# definitions-eu/ → EU config (api.eu.newrelic.com, EU org, EU fleet IDs)
# definitions-jp/ → JP config (api.jp.newrelic.com, JP org, JP fleet IDs)
# definitions/ → US config (default)
if [[ "$TEST_FILE" == test/definitions-eu/* ]]; then
echo "$USER_JSON_EU" > configs/gitusdkr${{ github.run_id }}.json
elif [[ "$TEST_FILE" == test/definitions-jp/* ]]; then
echo "$USER_JSON_JP" > configs/gitusdkr${{ github.run_id }}.json
else
echo "$USER_JSON_US" > configs/gitusdkr${{ github.run_id }}.json
fi
- name: Pull Deployer image
run: |
# Docker Hub's registry-1.docker.io occasionally returns
# "context deadline exceeded" mid-run; this one-shot pull was the
# only failure of run 27639559831 (otherwise-healthy JP logs test).
# Retry with linear backoff so a registry blip can't fail an
# otherwise-healthy matrix entry.
attempt=1
max_attempts=5
while [ $attempt -le $max_attempts ]; do
if docker pull newrelic/deployer:latest; then
docker images newrelic/deployer:latest
exit 0
fi
backoff=$((attempt * 5))
echo "::warning::docker pull attempt $attempt/$max_attempts failed; retrying in ${backoff}s"
sleep $backoff
attempt=$((attempt + 1))
done
echo "::error::docker pull newrelic/deployer:latest failed after $max_attempts attempts"
exit 1
- name: Run deployer
id: deployerRun
continue-on-error: true
run: |
set +e
testDefinitionFile=$(echo $MATRIX | jq -c -r '.testDefinitionFile')
echo $testDefinitionFile
if [[ "$testDefinitionFile" == test/definitions/agent-control/* || "$testDefinitionFile" == test/definitions-eu/agent-control/* || "$testDefinitionFile" == test/definitions-jp/agent-control/* ]]; then
docker run \
-v ${{ github.workspace }}/configs/:/mnt/deployer/configs/\
-v ${{ github.workspace }}/test/:/mnt/deployer/test/\
-e SYSTEM_IDENTITY_CLIENT_ID=$SYSTEM_IDENTITY_CLIENT_ID \
-e SYSTEM_IDENTITY_CLIENT_SECRET=$SYSTEM_IDENTITY_CLIENT_SECRET \
--entrypoint ruby newrelic/deployer:latest main.rb -c configs/gitusdkr${{ github.run_id }}.json -d $testDefinitionFile -l debug
else
docker run \
-v ${{ github.workspace }}/configs/:/mnt/deployer/configs/\
-v ${{ github.workspace }}/test/:/mnt/deployer/test/\
--entrypoint ruby newrelic/deployer:latest main.rb -c configs/gitusdkr${{ github.run_id }}.json -d $testDefinitionFile -l debug
fi
echo ::set-output name=exit_status::$?
- name: Teardown any previous deployment
if: always()
id: cleanupResources
continue-on-error: true
run: |
testDefinitionFile=$(echo $MATRIX | jq -c -r '.testDefinitionFile')
echo $testDefinitionFile
docker run \
-v ${{ github.workspace }}/configs/:/mnt/deployer/configs/\
-v ${{ github.workspace }}/test/:/mnt/deployer/test/\
--entrypoint ruby newrelic/deployer:latest main.rb -c configs/gitusdkr${{ github.run_id }}.json -d $testDefinitionFile -t
- name: Report any error
if: steps.deployerRun.outputs.exit_status != 0
run: exit 1
cleanup-system-identity:
name: Cleanup System Identity
runs-on: ubuntu-latest
needs: [test-deploy-recipe, get-test-definition-files, create-system-identity]
if: always() && needs.get-test-definition-files.outputs.needs_system_identity == 'true'
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Write Test Definition File JSON to file
env:
USER_JSON: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG }}
run: |
mkdir -p configs
echo "$USER_JSON" > configs/gitusdkr${{ github.run_id }}.json
- name: Clean up system identity
continue-on-error: true
run: |
if [ -f configs/gitusdkr${{ github.run_id }}.json ]; then
NR_API_KEY=$(jq -r -e '.credentials.newrelic.nrPersonalApiKey' configs/gitusdkr${{ github.run_id }}.json)
SYSTEM_IDENTITY_ID="${{ needs.create-system-identity.outputs.SYSTEM_IDENTITY_ID }}"
echo "::add-mask::$NR_API_KEY"
echo "::add-mask::$SYSTEM_IDENTITY_ID"
if [ ! -z "$SYSTEM_IDENTITY_ID" ] && [ "$SYSTEM_IDENTITY_ID" != "null" ]; then
echo "Cleaning up system identity with ID: $SYSTEM_IDENTITY_ID"
curl -X POST https://api.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: $NR_API_KEY" \
--data-raw "{
\"query\": \"mutation { systemIdentityDelete(id: \\\"$SYSTEM_IDENTITY_ID\\\") { id } }\"
}" || echo "Failed to delete system identity, it may have already been deleted"
else
echo "No system identity to clean up"
fi
else
echo "Config file not found, skipping system identity cleanup"
fi
cleanup-system-identity-eu:
name: Cleanup System Identity (EU)
runs-on: ubuntu-latest
needs: [test-deploy-recipe, get-test-definition-files, create-system-identity-eu]
if: always() && needs.get-test-definition-files.outputs.needs_system_identity_eu == 'true'
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Write Test Definition File JSON to file (EU)
env:
USER_JSON: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG_EU }}
run: |
mkdir -p configs
echo "$USER_JSON" > configs/gitusdkr${{ github.run_id }}.json
- name: Clean up system identity (EU)
continue-on-error: true
run: |
if [ -f configs/gitusdkr${{ github.run_id }}.json ]; then
NR_API_KEY=$(jq -r -e '.credentials.newrelic.nrPersonalApiKey' configs/gitusdkr${{ github.run_id }}.json)
SYSTEM_IDENTITY_ID="${{ needs.create-system-identity-eu.outputs.SYSTEM_IDENTITY_ID }}"
echo "::add-mask::$NR_API_KEY"
echo "::add-mask::$SYSTEM_IDENTITY_ID"
if [ ! -z "$SYSTEM_IDENTITY_ID" ] && [ "$SYSTEM_IDENTITY_ID" != "null" ]; then
echo "Cleaning up EU system identity with ID: $SYSTEM_IDENTITY_ID"
curl -X POST https://api.eu.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: $NR_API_KEY" \
--data-raw "{
\"query\": \"mutation { systemIdentityDelete(id: \\\"$SYSTEM_IDENTITY_ID\\\") { id } }\"
}" || echo "Failed to delete EU system identity, it may have already been deleted"
else
echo "No EU system identity to clean up"
fi
else
echo "EU config file not found, skipping system identity cleanup"
fi
cleanup-system-identity-jp:
name: Cleanup System Identity (JP)
runs-on: ubuntu-latest
needs: [test-deploy-recipe, get-test-definition-files, create-system-identity-jp]
if: always() && needs.get-test-definition-files.outputs.needs_system_identity_jp == 'true'
steps:
- name: Checkout Repo
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Write Test Definition File JSON to file (JP)
env:
USER_JSON: ${{ secrets.GIT_DEPLOYER_DOCKER_USER_CONFIG_JP }}
run: |
mkdir -p configs
echo "$USER_JSON" > configs/gitusdkr${{ github.run_id }}.json
- name: Clean up system identity (JP)
continue-on-error: true
run: |
if [ -f configs/gitusdkr${{ github.run_id }}.json ]; then
NR_API_KEY=$(jq -r -e '.credentials.newrelic.nrPersonalApiKey' configs/gitusdkr${{ github.run_id }}.json)
SYSTEM_IDENTITY_ID="${{ needs.create-system-identity-jp.outputs.SYSTEM_IDENTITY_ID }}"
echo "::add-mask::$NR_API_KEY"
echo "::add-mask::$SYSTEM_IDENTITY_ID"
if [ ! -z "$SYSTEM_IDENTITY_ID" ] && [ "$SYSTEM_IDENTITY_ID" != "null" ]; then
echo "Cleaning up JP system identity with ID: $SYSTEM_IDENTITY_ID"
curl -X POST https://api.jp.newrelic.com/graphql \
-H 'content-type: application/json; charset=utf-8' \
-H "API-Key: $NR_API_KEY" \
--data-raw "{
\"query\": \"mutation { systemIdentityDelete(id: \\\"$SYSTEM_IDENTITY_ID\\\") { id } }\"
}" || echo "Failed to delete JP system identity, it may have already been deleted"
else
echo "No JP system identity to clean up"
fi
else
echo "JP config file not found, skipping system identity cleanup"
fi
slack-notify:
runs-on: ubuntu-latest
needs: [test-deploy-recipe, cleanup-system-identity, cleanup-system-identity-eu, cleanup-system-identity-jp]
if: always()
steps:
- name: Build Result Slack Notification
uses: 8398a7/action-slack@v3
with:
author_name: GitHub Actions
status: custom
fields: commit,repo,ref,author,eventName,message,workflow
custom_payload: |
{
username: "GitHub Actions",
icon_emoji: ":octocat:",
attachments: [{
color: ${{
needs.test-deploy-recipe.result == 'success'
}} === true ? '#43cc11' : '#e05d44',
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `Build for ${process.env.AS_REPO}`
}
},
{
type: "section",
fields: [
{
type: "mrkdwn",
text: `*Commit:*\n${process.env.AS_COMMIT}`
},
{
type: "mrkdwn",
text: `*Author:*\n${process.env.AS_AUTHOR}`
},
{
type: "mrkdwn",
text: `*Branch:*\n${process.env.AS_REF}`
},
{
type: "mrkdwn",
text: `*Message:*\n${process.env.AS_MESSAGE}`
},
{
type: "mrkdwn",
text: `*Type:*\n${process.env.AS_EVENT_NAME}`
},
{
type: "mrkdwn",
text: "*PR:*\n${{ github.event.pull_request.html_url }}"
},
{
type: "mrkdwn",
text: `*Workflow:*\n${ process.env.AS_WORKFLOW }`
}
]
},
{
type: "section",
text: {
type: "mrkdwn",
text: [
"*Result:*",
`• ${ ${{ needs.test-deploy-recipe.result == 'success' }} === true ? '✅' : '❌' } AWS recipe validation test: ${{ needs.test-deploy-recipe.result }}`
].join('\n')
}
},
{
type: "context",
elements: [
{
type: "image",
image_url: "https://avatars2.githubusercontent.com/in/15368",
alt_text: "Github Actions"
},
{
type: "mrkdwn",
text: "This message was created automatically by GitHub Actions."
}
]
}
]
}]
}
env:
GITHUB_TOKEN: ${{ github.token }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}