Make action compatible with push events (#12)

This commit is contained in:
Bᴇʀɴᴅ Sᴄʜᴏʀɢᴇʀs 2022-07-30 14:33:55 +02:00
parent d2d078c510
commit f1fcfe77d5
No known key found for this signature in database
GPG key ID: BC5E2BD907F9A8EC
13 changed files with 179 additions and 75 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,5 @@
name: 'Changed charts'
description: 'Collects the changed Helm charts and returns the lint/test matrix'
name: 'Collect charts'
description: 'Collects Helm charts based on the inputs and returns the lint/test matrix'
inputs:
token:
description: >
@ -17,8 +17,20 @@ inputs:
should be excluded from linting/testing.
required: true
default: '.ci/repo-config.yaml'
getAllCharts:
description: >
Instead of finding the changed charts, return
all the charts
required: false
default: 'false'
overrideCharts:
description: >
A JSON encoded array of charts to return instead of finding
the changed charts
required: false
default: '[]'
outputs:
changedCharts:
charts:
description: >
An array of all the Helm charts that contain changes
chartsToInstall:

View file

@ -49,20 +49,22 @@ function getErrorMessage(error) {
return error.message;
return String(error);
}
function requestAddedModifiedFiles(base, head, githubToken) {
function requestAddedModifiedFiles(baseCommit, headCommit, githubToken) {
return __awaiter(this, void 0, void 0, function* () {
let result = [];
const octokit = github.getOctokit(githubToken);
core.info(`Base commit: ${baseCommit}`);
core.info(`Head commit: ${headCommit}`);
// Use GitHub's compare two commits API.
const response = yield octokit.rest.repos.compareCommits({
base,
head,
base: baseCommit,
head: headCommit,
owner: github.context.repo.owner,
repo: github.context.repo.repo,
});
// Ensure that the request was successful.
if (response.status !== 200) {
throw new Error(`The GitHub API for comparing the base and head commits for this PR event returned ${response.status}, expected 200.`);
throw new Error(`The GitHub API returned ${response.status}, expected 200.`);
}
// Ensure that the head commit is ahead of the base commit.
if (response.data.status !== "ahead") {
@ -78,6 +80,30 @@ function requestAddedModifiedFiles(base, head, githubToken) {
return result;
});
}
function requestAllFiles(commit, githubToken) {
return __awaiter(this, void 0, void 0, function* () {
let result = [];
const octokit = github.getOctokit(githubToken);
core.info(`Commit SHA: ${commit}`);
const response = yield octokit.rest.git.getTree({
tree_sha: commit,
owner: github.context.repo.owner,
repo: github.context.repo.repo,
recursive: "true",
});
// Ensure that the request was successful.
if (response.status !== 200) {
throw new Error(`The GitHub API returned ${response.status}, expected 200.`);
}
const responseTreeItems = response.data.tree || [];
responseTreeItems.forEach((item) => {
if (item.type == "blob" && item.path) {
result.push(item.path);
}
});
return result;
});
}
function getRepoConfig(configPath) {
return __awaiter(this, void 0, void 0, function* () {
// Ensure that the repo config file exists.
@ -110,33 +136,56 @@ function run() {
var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function* () {
try {
if (github.context.eventName !== "pull_request") {
throw new Error("This action can only run on pull requests!");
}
const githubToken = core.getInput("token", { required: true });
const chartsFolder = core.getInput("chartsFolder", { required: true });
const repoConfigFilePath = core.getInput("repoConfigFile", {
required: true,
});
let getAllCharts = core.getInput("getAllCharts", { required: false });
const overrideCharts = core.getInput("overrideCharts", { required: false });
const repoConfig = yield getRepoConfig(repoConfigFilePath);
core.info(`Repo configuration: ${JSON.stringify(repoConfig, undefined, 2)}`);
// Define the base and head commits to be extracted from the payload.
const baseCommit = (_b = (_a = github.context.payload.pull_request) === null || _a === void 0 ? void 0 : _a.base) === null || _b === void 0 ? void 0 : _b.sha;
const headCommit = (_d = (_c = github.context.payload.pull_request) === null || _c === void 0 ? void 0 : _c.head) === null || _d === void 0 ? void 0 : _d.sha;
// Ensure that the base and head properties are set on the payload.
if (!baseCommit || !headCommit) {
throw new Error(`The base and head commits are missing from the payload for this PR.`);
if (overrideCharts && overrideCharts != "[]") {
const responseCharts = YAML.parse(overrideCharts);
core.info(`Charts: ${JSON.stringify(responseCharts, undefined, 2)}`);
core.setOutput("charts", responseCharts);
return;
}
const eventName = github.context.eventName;
let baseCommit;
let headCommit;
switch (eventName) {
case "pull_request":
baseCommit = (_b = (_a = github.context.payload.pull_request) === null || _a === void 0 ? void 0 : _a.base) === null || _b === void 0 ? void 0 : _b.sha;
headCommit = (_d = (_c = github.context.payload.pull_request) === null || _c === void 0 ? void 0 : _c.head) === null || _d === void 0 ? void 0 : _d.sha;
break;
case "push":
baseCommit = github.context.payload.before;
headCommit = github.context.payload.after;
break;
case "workflow_dispatch":
getAllCharts = "true";
baseCommit = "";
headCommit = github.context.sha;
break;
default:
throw new Error(`This action only supports pull requests, pushes and workflow_dispatch,` +
`${github.context.eventName} events are not supported.`);
}
let responseFiles;
if (getAllCharts === "true") {
responseFiles = yield requestAllFiles(headCommit, githubToken);
}
else {
responseFiles = yield requestAddedModifiedFiles(baseCommit, headCommit, githubToken);
}
core.info(`Base commit: ${baseCommit}`);
core.info(`Head commit: ${headCommit}`);
const responseFiles = yield requestAddedModifiedFiles(baseCommit, headCommit, githubToken);
const changedCharts = filterChangedCharts(responseFiles, chartsFolder);
const chartsToInstall = changedCharts.filter((x) => !repoConfig["excluded-charts-install"].includes(x));
const chartsToLint = changedCharts.filter((x) => !repoConfig["excluded-charts-lint"].includes(x));
core.info(`Changed charts: ${JSON.stringify(changedCharts, undefined, 2)}`);
core.info(`Charts: ${JSON.stringify(changedCharts, undefined, 2)}`);
core.info(`Charts to lint: ${JSON.stringify(chartsToLint, undefined, 2)}`);
core.info(`Charts to install: ${JSON.stringify(chartsToInstall, undefined, 2)}`);
core.setOutput("changedCharts", changedCharts);
core.setOutput("charts", changedCharts);
core.setOutput("chartsToInstall", chartsToInstall);
core.setOutput("chartsToLint", chartsToLint);
}

File diff suppressed because one or more lines are too long

View file

@ -12,17 +12,20 @@ function getErrorMessage(error: unknown) {
}
async function requestAddedModifiedFiles(
base: string,
head: string,
baseCommit: string,
headCommit: string,
githubToken: string
) {
let result: string[] = [];
const octokit = github.getOctokit(githubToken);
core.info(`Base commit: ${baseCommit}`);
core.info(`Head commit: ${headCommit}`);
// Use GitHub's compare two commits API.
const response = await octokit.rest.repos.compareCommits({
base,
head,
base: baseCommit,
head: headCommit,
owner: github.context.repo.owner,
repo: github.context.repo.repo,
});
@ -30,7 +33,7 @@ async function requestAddedModifiedFiles(
// Ensure that the request was successful.
if (response.status !== 200) {
throw new Error(
`The GitHub API for comparing the base and head commits for this PR event returned ${response.status}, expected 200.`
`The GitHub API returned ${response.status}, expected 200.`
);
}
@ -51,6 +54,35 @@ async function requestAddedModifiedFiles(
return result;
}
async function requestAllFiles(commit: string, githubToken: string) {
let result: string[] = [];
const octokit = github.getOctokit(githubToken);
core.info(`Commit SHA: ${commit}`);
const response = await octokit.rest.git.getTree({
tree_sha: commit,
owner: github.context.repo.owner,
repo: github.context.repo.repo,
recursive: "true",
});
// Ensure that the request was successful.
if (response.status !== 200) {
throw new Error(
`The GitHub API returned ${response.status}, expected 200.`
);
}
const responseTreeItems = response.data.tree || [];
responseTreeItems.forEach((item) => {
if (item.type == "blob" && item.path) {
result.push(item.path);
}
});
return result;
}
async function getRepoConfig(configPath: string) {
// Ensure that the repo config file exists.
if (!(await fs.pathExists(configPath))) {
@ -88,40 +120,63 @@ function filterChangedCharts(files: string[], parentFolder: string) {
async function run() {
try {
if (github.context.eventName !== "pull_request") {
throw new Error("This action can only run on pull requests!");
}
const githubToken = core.getInput("token", { required: true });
const chartsFolder = core.getInput("chartsFolder", { required: true });
const repoConfigFilePath = core.getInput("repoConfigFile", {
required: true,
});
let getAllCharts = core.getInput("getAllCharts", { required: false });
const overrideCharts = core.getInput("overrideCharts", { required: false });
const repoConfig = await getRepoConfig(repoConfigFilePath);
core.info(
`Repo configuration: ${JSON.stringify(repoConfig, undefined, 2)}`
);
// Define the base and head commits to be extracted from the payload.
const baseCommit = github.context.payload.pull_request?.base?.sha;
const headCommit = github.context.payload.pull_request?.head?.sha;
if (overrideCharts && overrideCharts != "[]") {
const responseCharts = YAML.parse(overrideCharts);
core.info(`Charts: ${JSON.stringify(responseCharts, undefined, 2)}`);
core.setOutput("charts", responseCharts);
return;
}
// Ensure that the base and head properties are set on the payload.
if (!baseCommit || !headCommit) {
throw new Error(
`The base and head commits are missing from the payload for this PR.`
const eventName = github.context.eventName;
let baseCommit: string;
let headCommit: string;
switch (eventName) {
case "pull_request":
baseCommit = github.context.payload.pull_request?.base?.sha;
headCommit = github.context.payload.pull_request?.head?.sha;
break;
case "push":
baseCommit = github.context.payload.before;
headCommit = github.context.payload.after;
break;
case "workflow_dispatch":
getAllCharts = "true";
baseCommit = "";
headCommit = github.context.sha;
break;
default:
throw new Error(
`This action only supports pull requests, pushes and workflow_dispatch,` +
`${github.context.eventName} events are not supported.`
);
}
let responseFiles: string[];
if (getAllCharts === "true") {
responseFiles = await requestAllFiles(headCommit, githubToken);
} else {
responseFiles = await requestAddedModifiedFiles(
baseCommit,
headCommit,
githubToken
);
}
core.info(`Base commit: ${baseCommit}`);
core.info(`Head commit: ${headCommit}`);
const responseFiles = await requestAddedModifiedFiles(
baseCommit,
headCommit,
githubToken
);
const changedCharts = filterChangedCharts(responseFiles, chartsFolder);
const chartsToInstall = changedCharts.filter(
(x) => !repoConfig["excluded-charts-install"].includes(x)
@ -130,13 +185,13 @@ async function run() {
(x) => !repoConfig["excluded-charts-lint"].includes(x)
);
core.info(`Changed charts: ${JSON.stringify(changedCharts, undefined, 2)}`);
core.info(`Charts: ${JSON.stringify(changedCharts, undefined, 2)}`);
core.info(`Charts to lint: ${JSON.stringify(chartsToLint, undefined, 2)}`);
core.info(
`Charts to install: ${JSON.stringify(chartsToInstall, undefined, 2)}`
);
core.setOutput("changedCharts", changedCharts);
core.setOutput("charts", changedCharts);
core.setOutput("chartsToInstall", chartsToInstall);
core.setOutput("chartsToLint", chartsToLint);
} catch (error) {

View file

@ -6,9 +6,11 @@ on:
workflow_dispatch:
inputs:
chart:
description: "Chart to release"
default: "_all_"
required: true
description: >
Chart to release. Comma-separated string.
Defaults to releasing everything.
default: ""
required: false
push:
branches:
- main
@ -37,28 +39,13 @@ jobs:
path: "src"
fetch-depth: 0
- name: Collect changes
id: collect-changes
uses: ./src/.github/actions/collect-changes
- name: Collect charts to release
uses: ./src/.github/actions/collect-charts
id: collect-charts
with:
token: ${{ steps.get-app-token.outputs.token }}
working-directory: src
- name: Determine charts to release
id: charts-to-release
shell: bash
run: |
CHARTS=()
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
if [ "${{ github.event.inputs.chart }}" == "_all_" ]; then
CHARTS=($(find "src/charts" -type f -name 'Chart.yaml' | sed -r 's|/[^/]+$||' | sed 's|src/charts/||' | sort | uniq))
else
CHARTS=(${{ github.event.inputs.chart }})
fi
elif [ "${{ steps.collect-changes.outputs.chartChangesDetected }}" == "true" ]; then
CHARTS=(${{ steps.collect-changes.outputs.addedOrModifiedCharts }})
fi
printf "::set-output name=charts::%s\n" "${CHARTS[*]}"
repoConfigFile: ./src/.ci/repo-config.yaml
overrideCharts: "[${{ inputs.chart }}]"
- name: Checkout gh-pages branch
uses: actions/checkout@v3
@ -80,9 +67,10 @@ jobs:
env:
SRC_DIR: "src/charts"
DEST_DIR: "dest"
CHARTS: "${{ steps.charts-to-release.outputs.charts }}"
run: |
for CHART in $CHARTS ; do
CHARTS=( $(yq --null-input e '${{ steps.collect-charts.outputs.charts }}[]' ) )
for CHART in "${CHARTS[@]}" ; do
mapfile -t CHART_PATH_PARTS < <(echo "$CHART" | tr '/' '\n')
CHART_TYPE=${CHART_PATH_PARTS[0]}

View file

@ -54,7 +54,7 @@ jobs:
outputs:
addedOrModifiedFilesDetected: ${{ steps.changed-files.outputs.allAddedOrModified }}
addedOrModifiedFiles: ${{ steps.changed-files.outputs.allAddedOrModified_files }}
addedOrModifiedCharts: ${{ steps.changed-charts.outputs.changedCharts }}
addedOrModifiedCharts: ${{ steps.changed-charts.outputs.charts }}
chartsToLint: ${{ steps.changed-charts.outputs.chartsToLint }}
chartsToInstall: ${{ steps.changed-charts.outputs.chartsToInstall }}
steps:
@ -73,5 +73,5 @@ jobs:
- added|modified: '**'
- name: Collect changed charts
uses: ./.github/actions/collect-changed-charts
uses: ./.github/actions/collect-charts
id: changed-charts