Skip to content

PR check #133 - app-acquisitions #69

PR check #133 - app-acquisitions

PR check #133 - app-acquisitions #69

Workflow file for this run

name: PR Check
run-name: >-
${{ inputs.pr_number != '' && format('PR check #{0} - {1}', inputs.pr_number, inputs.repo_name) || format('PR check - {0}', inputs.repo_name) }}
on:
workflow_dispatch:
inputs:
repo_owner:
description: 'Repository owner'
required: true
type: string
repo_name:
description: 'Repository name'
required: true
type: string
pr_number:
description: 'Pull request number'
required: true
type: string
head_sha:
description: 'Head commit SHA to validate'
required: true
type: string
permissions:
contents: read
checks: write
statuses: write
jobs:
pre-check:
name: Pre-Check Configuration
runs-on: ubuntu-latest
outputs:
validation_status: ${{ steps.validate.outputs.status }}
validation_message: ${{ steps.validate.outputs.message }}
is_update_pr: ${{ steps.validate.outputs.is_update_pr }}
head_branch: ${{ steps.pr-info.outputs.head_ref }}
base_branch: ${{ steps.pr-info.outputs.base_ref }}
steps:
- name: Print Input Parameters
run: |
echo "::group::Workflow Inputs"
echo "repo_owner: ${{ inputs.repo_owner }}"
echo "repo_name: ${{ inputs.repo_name }}"
echo "pr_number: ${{ inputs.pr_number }}"
echo "head_sha: ${{ inputs.head_sha }}"
echo "::endgroup::"
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.EUREKA_CI_APP_ID }}
private-key: ${{ secrets.EUREKA_CI_APP_KEY }}
owner: ${{ inputs.repo_owner }}
repositories: ${{ inputs.repo_name }}
- name: Get Pull Request Information
id: pr-info
uses: folio-org/kitfox-github/.github/actions/get-pr-info@master
with:
repository: ${{ inputs.repo_owner }}/${{ inputs.repo_name }}
pr_number: ${{ inputs.pr_number }}
github_token: ${{ steps.app-token.outputs.token }}
- name: Check Commit in PR
id: check-commit
if: steps.pr-info.outputs.pr_exists == 'true'
uses: folio-org/kitfox-github/.github/actions/is-commit-in-pr@master
with:
repository: ${{ inputs.repo_owner }}/${{ inputs.repo_name }}
pr_number: ${{ inputs.pr_number }}
commit_sha: ${{ inputs.head_sha }}
github_token: ${{ steps.app-token.outputs.token }}
- name: Checkout Repository
if: steps.pr-info.outputs.pr_exists == 'true' && steps.check-commit.outputs.commit_found == 'true'
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo_owner }}/${{ inputs.repo_name }}
ref: ${{ inputs.head_sha }}
token: ${{ steps.app-token.outputs.token }}
- name: Get Update Configuration
id: get-config
if: steps.pr-info.outputs.pr_exists == 'true' && steps.check-commit.outputs.commit_found == 'true'
uses: folio-org/kitfox-github/.github/actions/get-update-config@master
with:
repo: ${{ inputs.repo_owner }}/${{ inputs.repo_name }}
branch: master
github_token: ${{ steps.app-token.outputs.token }}
- name: Validate Configuration
id: validate
if: steps.pr-info.outputs.pr_exists == 'true' && steps.check-commit.outputs.commit_found == 'true'
env:
TARGET_BRANCH: ${{ steps.pr-info.outputs.base_ref }}
HEAD_BRANCH: ${{ steps.pr-info.outputs.head_ref }}
PR_LABELS: ${{ steps.pr-info.outputs.labels }}
CONFIG_EXISTS: ${{ steps.get-config.outputs.config_exists }}
ENABLED: ${{ steps.get-config.outputs.enabled }}
RELEASE_BRANCHES: ${{ steps.get-config.outputs.branches }}
BRANCH_CONFIG: ${{ steps.get-config.outputs.branch_config }}
REQUIRED_LABELS: ${{ steps.get-config.outputs.pr_labels }}
run: |
echo "::notice::Validating configuration for branch $TARGET_BRANCH"
if [[ "$CONFIG_EXISTS" != "true" ]]; then
echo "status=skipped" >> "$GITHUB_OUTPUT"
echo "message=Release configuration file not found" >> "$GITHUB_OUTPUT"
echo "::warning::Configuration file not found: .github/release-config.yml"
exit 0
fi
if [[ "$ENABLED" != "true" ]]; then
echo "status=skipped" >> "$GITHUB_OUTPUT"
echo "message=Release scanning is disabled in configuration" >> "$GITHUB_OUTPUT"
echo "::notice::Release scanning is disabled"
exit 0
fi
BRANCH_EXISTS=$(echo "$RELEASE_BRANCHES" | jq -r ".[] | select(. == \"$TARGET_BRANCH\")" 2>/dev/null)
if [ -z "$BRANCH_EXISTS" ]; then
echo "status=skipped" >> "$GITHUB_OUTPUT"
echo "message=Target branch $TARGET_BRANCH is not configured for release scanning" >> "$GITHUB_OUTPUT"
echo "::notice::Branch $TARGET_BRANCH is not in release_branches configuration"
exit 0
fi
BRANCH_ENTRY=$(echo "$BRANCH_CONFIG" | jq -r ".[] | select(.branch == \"$TARGET_BRANCH\")")
NEED_PR=$(echo "$BRANCH_ENTRY" | jq -r ".need_pr // false")
UPDATE_BRANCH=$(echo "$BRANCH_ENTRY" | jq -r ".update_branch // empty")
if [[ "$NEED_PR" != "true" ]]; then
echo "status=skipped" >> "$GITHUB_OUTPUT"
echo "message=Branch $TARGET_BRANCH is not configured for PR-based updates" >> "$GITHUB_OUTPUT"
echo "::notice::Branch $TARGET_BRANCH has need_pr=false, skipping PR check"
exit 0
fi
if [[ "$HEAD_BRANCH" != "$UPDATE_BRANCH" ]]; then
echo "is_update_pr=false" >> "$GITHUB_OUTPUT"
echo "status=success" >> "$GITHUB_OUTPUT"
echo "message=Non-update PR - validation skipped" >> "$GITHUB_OUTPUT"
echo "::notice::Head branch '$HEAD_BRANCH' is not the configured update branch '$UPDATE_BRANCH', this is a non-update PR"
exit 0
fi
echo "is_update_pr=true" >> "$GITHUB_OUTPUT"
if [ -n "$REQUIRED_LABELS" ]; then
echo "::notice::Checking for required labels: $REQUIRED_LABELS"
PR_LABELS_ARRAY=$(echo "$PR_LABELS" | jq -r '.[]' 2>/dev/null || echo "")
MISSING_LABELS=""
IFS=',' read -ra LABEL_ARRAY <<< "$REQUIRED_LABELS"
for label in "${LABEL_ARRAY[@]}"; do
label=$(echo "$label" | xargs)
if ! echo "$PR_LABELS_ARRAY" | grep -q "^$label$"; then
MISSING_LABELS="${MISSING_LABELS}${MISSING_LABELS:+, }$label"
fi
done
if [ -n "$MISSING_LABELS" ]; then
echo "status=skipped" >> "$GITHUB_OUTPUT"
echo "message=PR is missing required labels: $MISSING_LABELS" >> "$GITHUB_OUTPUT"
echo "::notice::PR does not have required labels, skipping validation"
exit 0
fi
fi
echo "status=success" >> "$GITHUB_OUTPUT"
echo "message=Configuration validation passed" >> "$GITHUB_OUTPUT"
echo "::notice::Configuration validation successful"
non-update-check:
name: Non-Update PR Check
needs: pre-check
if: |
needs.pre-check.outputs.validation_status == 'success' &&
needs.pre-check.outputs.is_update_pr == 'false'
runs-on: ubuntu-latest
outputs:
has_violations: ${{ steps.check-protected.outputs.has_violations }}
violations: ${{ steps.check-protected.outputs.violations }}
env:
PROTECTED_LOCK_FILE: application.lock.json
PROTECTED_TEMPLATE_FILE: application.template.json
TITLE_TEXT: "${{ inputs.repo_name }} PR #${{ inputs.pr_number }} blocked - protected file violation"
TITLE_BLOCK: |
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*${{ inputs.repo_name }} PR blocked - protected file violation <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|#${{ github.run_number }}>*"
}
}
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.EUREKA_CI_APP_ID }}
private-key: ${{ secrets.EUREKA_CI_APP_KEY }}
owner: ${{ inputs.repo_owner }}
repositories: ${{ inputs.repo_name }}
- name: Check Protected Files
id: check-protected
uses: folio-org/kitfox-github/.github/actions/check-protected-files@master
with:
check_type: pr
repo_owner: ${{ inputs.repo_owner }}
repo_name: ${{ inputs.repo_name }}
pr_number: ${{ inputs.pr_number }}
github_token: ${{ steps.app-token.outputs.token }}
protected_lock_file: ${{ env.PROTECTED_LOCK_FILE }}
protected_template_file: ${{ env.PROTECTED_TEMPLATE_FILE }}
- name: Create Check Run
uses: folio-org/kitfox-github/.github/actions/check-run-create@master
with:
repo_owner: ${{ inputs.repo_owner }}
repo_name: ${{ inputs.repo_name }}
head_sha: ${{ inputs.head_sha }}
github_token: ${{ steps.app-token.outputs.token }}
has_violations: ${{ steps.check-protected.outputs.has_violations }}
violations: ${{ steps.check-protected.outputs.violations }}
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
- name: Get Repository Variables
id: get-vars
if: steps.check-protected.outputs.has_violations == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
try {
const { data: variable } = await github.rest.actions.getRepoVariable({
owner: '${{ inputs.repo_owner }}',
repo: '${{ inputs.repo_name }}',
name: 'SLACK_NOTIF_CHANNEL'
});
console.log(`Found SLACK_NOTIF_CHANNEL: ${variable.value}`);
core.setOutput('team_channel', variable.value);
} catch (error) {
console.log(`SLACK_NOTIF_CHANNEL not found or not accessible: ${error.message}`);
core.setOutput('team_channel', '');
}
- name: Build Notification Attachment
id: build-attachment
if: steps.check-protected.outputs.has_violations == 'true'
env:
VIOLATIONS: ${{ steps.check-protected.outputs.violations }}
run: |
ATTACHMENT=$(cat <<EOF
{
"color": "danger",
"fields": [
{
"title": "PR",
"value": "<https://github.com/${{ inputs.repo_owner }}/${{ inputs.repo_name }}/pull/${{ inputs.pr_number }}|#${{ inputs.pr_number }}>",
"short": true
},
{
"title": "Target Branch",
"value": "${{ needs.pre-check.outputs.base_branch }}",
"short": true
},
{
"title": "Violations",
"value": "${VIOLATIONS}",
"short": false
}
],
"footer": "Eureka CI/CD"
}
EOF
)
echo "ATTACHMENT<<EOF" >> "$GITHUB_ENV"
echo "$ATTACHMENT" >> "$GITHUB_ENV"
echo "EOF" >> "$GITHUB_ENV"
- name: Send Violation Notification to Team Channel
if: steps.check-protected.outputs.has_violations == 'true' && steps.get-vars.outputs.team_channel != ''
continue-on-error: true
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.EUREKA_CI_SLACK_BOT_TOKEN }}
errors: false
payload: |
{
"channel": "${{ steps.get-vars.outputs.team_channel }}",
"text": "${{ env.TITLE_TEXT }}",
"blocks": [
${{ env.TITLE_BLOCK }}
],
"attachments": [
${{ env.ATTACHMENT }}
]
}
- name: Send Violation Notification to General Channel
if: steps.check-protected.outputs.has_violations == 'true' && vars.GENERAL_SLACK_NOTIF_CHANNEL != ''
continue-on-error: true
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.EUREKA_CI_SLACK_BOT_TOKEN }}
errors: false
payload: |
{
"channel": "${{ vars.GENERAL_SLACK_NOTIF_CHANNEL }}",
"text": "${{ env.TITLE_TEXT }}",
"blocks": [
${{ env.TITLE_BLOCK }}
],
"attachments": [
${{ env.ATTACHMENT }}
]
}
check:
name: Check commit
needs: pre-check
if: |
needs.pre-check.outputs.validation_status == 'success' &&
needs.pre-check.outputs.is_update_pr == 'true'
runs-on: ubuntu-latest
outputs:
validation_passed: ${{ steps.check-commit.outputs.validation_passed }}
failure_reason: ${{ steps.check-commit.outputs.failure_reason }}
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.EUREKA_CI_APP_ID }}
private-key: ${{ secrets.EUREKA_CI_APP_KEY }}
owner: ${{ inputs.repo_owner }}
repositories: ${{ inputs.repo_name }}
- name: Checkout Repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo_owner }}/${{ inputs.repo_name }}
ref: ${{ inputs.head_sha }}
token: ${{ steps.app-token.outputs.token }}
- name: Check Commit
id: check-commit
uses: folio-org/kitfox-github/.github/actions/check-commit@master
with:
repo_owner: ${{ inputs.repo_owner }}
repo_name: ${{ inputs.repo_name }}
head_sha: ${{ inputs.head_sha }}
base_branch: ${{ needs.pre-check.outputs.base_branch }}
github_token: ${{ steps.app-token.outputs.token }}
check_type: pr
pr_number: ${{ inputs.pr_number }}
head_branch: ${{ needs.pre-check.outputs.head_branch }}
far_url: ${{ vars.FAR_URL }}
workflow_run_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
notify:
name: Send Notifications
needs: [pre-check, check]
if: |
always() && !cancelled() &&
needs.pre-check.outputs.validation_status == 'success' &&
needs.pre-check.outputs.is_update_pr == 'true'
runs-on: ubuntu-latest
outputs:
team_channel: ${{ steps.get-vars.outputs.team_channel }}
env:
TITLE_TEXT: "${{ inputs.repo_name }} release update check ${{ (needs.check.result == 'success' && needs.check.outputs.validation_passed == 'true') && 'passed' || 'failed' }}"
TITLE_BLOCK: |
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*${{ inputs.repo_name }} release update check ${{ (needs.check.result == 'success' && needs.check.outputs.validation_passed == 'true') && 'passed' || 'failed' }} <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|#${{ github.run_number }}>*"
}
}
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.EUREKA_CI_APP_ID }}
private-key: ${{ secrets.EUREKA_CI_APP_KEY }}
owner: ${{ inputs.repo_owner }}
repositories: ${{ inputs.repo_name }}
- name: Get Repository Variables
id: get-vars
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
try {
const { data: variable } = await github.rest.actions.getRepoVariable({
owner: '${{ inputs.repo_owner }}',
repo: '${{ inputs.repo_name }}',
name: 'SLACK_NOTIF_CHANNEL'
});
console.log(`Found SLACK_NOTIF_CHANNEL: ${variable.value}`);
core.setOutput('team_channel', variable.value);
} catch (error) {
console.log(`SLACK_NOTIF_CHANNEL not found or not accessible: ${error.message}`);
core.setOutput('team_channel', '');
}
- name: Build Notification Attachment
id: build-attachment
env:
BASE_BRANCH: ${{ needs.pre-check.outputs.base_branch }}
HEAD_BRANCH: ${{ needs.pre-check.outputs.head_branch }}
FAILURE_REASON: ${{ needs.check.outputs.failure_reason }}
run: |
ATTACHMENT=$(cat <<EOF
{
"color": "${{ (needs.check.result == 'success' && needs.check.outputs.validation_passed == 'true') && 'good' || 'danger' }}",
"fields": [
{
"title": "Release branch",
"value": "<https://github.com/${{ inputs.repo_owner }}/${{ inputs.repo_name }}/tree/${BASE_BRANCH}|${BASE_BRANCH}>",
"short": true
},
{
"title": "Update branch",
"value": "<https://github.com/${{ inputs.repo_owner }}/${{ inputs.repo_name }}/tree/${HEAD_BRANCH}|${HEAD_BRANCH}>",
"short": true
},
{
"title": "PR Number",
"value": "<https://github.com/${{ inputs.repo_owner }}/${{ inputs.repo_name }}/pull/${{ inputs.pr_number }}|#${{ inputs.pr_number }}>",
"short": true
},
{
"title": "Commit",
"value": "<https://github.com/${{ inputs.repo_owner }}/${{ inputs.repo_name }}/commit/${{ inputs.head_sha }}|${{ inputs.head_sha }}>",
"short": true
}${{ (needs.check.result != 'success' || needs.check.outputs.validation_passed != 'true') && format(',
{{
"title": "Failure Reason",
"value": "{0}",
"short": false
}}', needs.check.outputs.failure_reason) || '' }}
],
"footer": "Eureka CI/CD"
}
EOF
)
echo "ATTACHMENT<<EOF" >> "$GITHUB_ENV"
echo "$ATTACHMENT" >> "$GITHUB_ENV"
echo "EOF" >> "$GITHUB_ENV"
- name: Send to Team Channel
if: steps.get-vars.outputs.team_channel != ''
continue-on-error: true
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.EUREKA_CI_SLACK_BOT_TOKEN }}
errors: false
payload: |
{
"channel": "${{ steps.get-vars.outputs.team_channel }}",
"text": "${{ env.TITLE_TEXT }}",
"blocks": [
${{ env.TITLE_BLOCK }}
],
"attachments": [
${{ env.ATTACHMENT }}
]
}
- name: Send to General Channel
if: vars.GENERAL_SLACK_NOTIF_CHANNEL != ''
continue-on-error: true
uses: slackapi/slack-github-action@v2.1.1
with:
method: chat.postMessage
token: ${{ secrets.EUREKA_CI_SLACK_BOT_TOKEN }}
errors: false
payload: |
{
"channel": "${{ vars.GENERAL_SLACK_NOTIF_CHANNEL }}",
"text": "${{ env.TITLE_TEXT }}",
"blocks": [
${{ env.TITLE_BLOCK }}
],
"attachments": [
${{ env.ATTACHMENT }}
]
}
summarize:
name: Workflow Summary
needs: [pre-check, check, notify]
if: always()
runs-on: ubuntu-latest
steps:
- name: Generate Workflow Summary
env:
PRE_CHECK_RESULT: ${{ needs.pre-check.result }}
VALIDATION_STATUS: ${{ needs.pre-check.outputs.validation_status }}
VALIDATION_MESSAGE: ${{ needs.pre-check.outputs.validation_message }}
CHECK_RESULT: ${{ needs.check.result }}
VALIDATION_PASSED: ${{ needs.check.outputs.validation_passed }}
FAILURE_REASON: ${{ needs.check.outputs.failure_reason }}
HEAD_BRANCH: ${{ needs.pre-check.outputs.head_branch }}
BASE_BRANCH: ${{ needs.pre-check.outputs.base_branch }}
run: |
{
echo "### PR Check Summary"
echo ""
echo "**Repository:** \`${{ inputs.repo_owner }}/${{ inputs.repo_name }}\`"
echo "**PR:** [#${{ inputs.pr_number }}](https://github.com/${{ inputs.repo_owner }}/${{ inputs.repo_name }}/pull/${{ inputs.pr_number }})"
echo "**Commit:** [\`${{ inputs.head_sha }}\`](https://github.com/${{ inputs.repo_owner }}/${{ inputs.repo_name }}/commit/${{ inputs.head_sha }})"
echo ""
echo "### Pre-Check Status"
echo ""
if [[ "$PRE_CHECK_RESULT" == "success" ]]; then
if [[ "$VALIDATION_STATUS" == "success" ]]; then
echo "**Pre-Check:** Passed"
echo "- **Base Branch:** $BASE_BRANCH"
echo "- **Head Branch:** $HEAD_BRANCH"
echo "- **Message:** $VALIDATION_MESSAGE"
elif [[ "$VALIDATION_STATUS" == "skipped" ]]; then
echo "**Pre-Check:** Skipped"
echo "- **Reason:** $VALIDATION_MESSAGE"
elif [[ -z "$VALIDATION_STATUS" ]]; then
echo "**Pre-Check:** Validation step was skipped"
echo "- This typically means the PR was not found or the commit is not in the PR"
else
echo "**Pre-Check:** Unknown status ($VALIDATION_STATUS)"
fi
elif [[ "$PRE_CHECK_RESULT" == "failure" ]]; then
echo "**Pre-Check:** Failed"
echo "- **Message:** $VALIDATION_MESSAGE"
elif [[ "$PRE_CHECK_RESULT" == "cancelled" ]]; then
echo "**Pre-Check:** Cancelled"
else
echo "**Pre-Check:** Skipped"
fi
echo ""
echo "### Application Check Status"
echo ""
if [[ "$VALIDATION_STATUS" != "success" ]]; then
echo "Application check was skipped due to pre-check status"
elif [[ "$CHECK_RESULT" == "success" ]]; then
if [[ "$VALIDATION_PASSED" == "true" ]]; then
echo "**Application Check:** Passed"
else
echo "**Application Check:** Failed"
if [[ -n "$FAILURE_REASON" ]]; then
echo "- **Failure Reason:** $FAILURE_REASON"
fi
fi
elif [[ "$CHECK_RESULT" == "failure" ]]; then
echo "**Application Check:** Failed"
if [[ -n "$FAILURE_REASON" ]]; then
echo "- **Failure Reason:** $FAILURE_REASON"
else
echo "- Check the workflow logs for details"
fi
elif [[ "$CHECK_RESULT" == "cancelled" ]]; then
echo "**Application Check:** Cancelled"
else
echo "**Application Check:** Skipped"
fi
echo ""
echo "### Notification Status"
echo ""
if [[ -n "${{ needs.notify.outputs.team_channel }}" ]]; then
if [[ "${{ needs.notify.result }}" == "success" ]]; then
echo "**Team Channel** (\`${{ needs.notify.outputs.team_channel }}\`): Sent"
elif [[ "${{ needs.notify.result }}" == "failure" ]]; then
echo "**Team Channel** (\`${{ needs.notify.outputs.team_channel }}\`): Failed"
else
echo "**Team Channel** (\`${{ needs.notify.outputs.team_channel }}\`): Skipped"
fi
else
echo "**Team Channel:** Not configured"
fi
echo ""
if [[ -n "${{ vars.GENERAL_SLACK_NOTIF_CHANNEL }}" ]]; then
if [[ "${{ needs.notify.result }}" == "success" ]]; then
echo "**General Channel** (\`${{ vars.GENERAL_SLACK_NOTIF_CHANNEL }}\`): Sent"
elif [[ "${{ needs.notify.result }}" == "failure" ]]; then
echo "**General Channel** (\`${{ vars.GENERAL_SLACK_NOTIF_CHANNEL }}\`): Failed"
else
echo "**General Channel** (\`${{ vars.GENERAL_SLACK_NOTIF_CHANNEL }}\`): Skipped"
fi
else
echo "**General Channel:** Not configured"
fi
echo ""
echo "---"
echo ""
echo "**Workflow Run:** [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
} >> $GITHUB_STEP_SUMMARY