Diamond cut auto propose to safe #38
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# - Ensure Deploy Process Integrity | |
# - ensures that the systems in place to guarantee audits, approvals, versioning, test coverage etc. cannot be easily deactivated | |
# or altered without approval of the Information Security Manager (or CTO) | |
# - protects any git actions in folder .github/workflows/* | |
name: Ensure Deploy Process Integrity | |
on: | |
pull_request: | |
jobs: | |
protect-security-system: | |
runs-on: ubuntu-latest | |
permissions: | |
pull-requests: write | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 ##### Fetch all history for all branches | |
- name: Check Git Diff for protected files | |
id: check_protected_files | |
run: | | |
##### get all files modified by this PR | |
FILES=$(git diff --name-only origin/main HEAD) | |
##### make sure that there are modified files | |
if [[ -z $FILES ]]; then | |
echo -e "\033[31mNo files found. This should not happen. Please check the code of the Github action. Aborting now.\033[0m" | |
echo "CONTINUE=false" >> $GITHUB_ENV | |
exit 1 | |
fi | |
##### Initialize empty variables | |
PROTECTED_FILES="" | |
##### go through all modified file names/paths and identify contracts with path 'src/*' | |
while IFS= read -r FILE; do | |
if echo "$FILE" | grep -E '^.github/workflows/'; then | |
##### modified git action found | |
PROTECTED_FILES="${PROTECTED_FILES}${FILE}"$'\n' | |
fi | |
done <<< "$FILES" | |
##### if none found, exit here as there is nothing to do | |
if [[ -z "$PROTECTED_FILES" ]]; then | |
echo -e "\033[32mNo protected files found in Git diff.\033[0m" | |
echo -e "\033[32mNo further checks are required.\033[0m" | |
# set action output to false | |
echo "CONTINUE=false" >> $GITHUB_ENV | |
exit 0 | |
else | |
##### set action output to true | |
echo -e "\033[31mThe following protected files were found in Git diff:\033[0m" | |
echo "$PROTECTED_FILES" | |
echo "CONTINUE=true" >> $GITHUB_ENV | |
fi | |
- name: Get "Information Security Manager" Group Members | |
if: env.CONTINUE == 'true' | |
env: | |
GH_PAT: ${{ secrets.GIT_TOKEN }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
##### unset the default git token (does not have sufficient rights to get team members) | |
unset GITHUB_TOKEN | |
##### use the Personal Access Token to log into git CLI | |
echo $GH_PAT | gh auth login --with-token | |
##### Function to get team members using github CLI | |
getTeamMembers() { | |
local org=$1 | |
local team=$2 | |
gh api \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
"/orgs/$org/teams/$team/members" | jq -r '.[].login' | |
} | |
ORG_NAME='lifinance' | |
# GROUP_NAME='information-security-manager' | |
GROUP_NAME='smart-contract-core' | |
##### get team members | |
INFORMATION_SECURITY_MEMBERS=$(getTeamMembers $ORG_NAME $GROUP_NAME) | |
echo "Team members of 'Information Security Manager' group: $INFORMATION_SECURITY_MEMBERS" | |
##### store members in variable | |
echo -e "$INFORMATION_SECURITY_MEMBERS" > itSec_git_handles.txt | |
- name: Check approval of Information Security Manager | |
id: check-sec-mgr-approval | |
uses: actions/github-script@v7 | |
if: env.CONTINUE == 'true' | |
with: | |
script: | | |
const fs = require('fs'); | |
// ANSI escape codes for colors (used for colored output in Git action console) | |
const colors = { | |
reset: "\033[0m", | |
red: "\033[31m", | |
green: "\033[32m", | |
yellow: "\033[33m", | |
}; | |
// Read git handles from file | |
const itSecHandlesFile = 'itSec_git_handles.txt'; | |
const itSecHandles = fs.readFileSync(itSecHandlesFile, 'utf-8').split(/\r?\n/).filter(Boolean); | |
if(!(await github.pulls)) { | |
console.log(`${colors.red}Could not get reviewers of this PR from Github. Are there any reviews yet?${colors.reset}`); | |
console.log(`${colors.red}Check failed.${colors.reset}`); | |
core.setFailed("Required approval is missing"); | |
return | |
} | |
// get all reviewers of the current pr | |
const { data: reviews } = await github.pulls.listReviews({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
pull_number: context.issue.number, | |
}); | |
// extract the git login handles of all reviewers | |
const reviewerHandles = reviews.map(review => review.user.login); | |
console.log(`This PR has been reviewed by the following git members: ${reviewerHandles}`) | |
// check if at least one of these reviewers is member in information-security-manager group | |
if (reviewerHandles.some((handle) => itSecHandles.includes(handle))) { | |
console.log(`${colors.green}The current PR was approved by a member of the information-security-manager group.${colors.reset}`); | |
console.log(`${colors.green}Check passed.${colors.reset}`); | |
core.setOutput('approved', 'true'); | |
} else { | |
console.log(`${colors.red}The PR requires a missing approval by a member of the information-security-manager group.${colors.reset}`); | |
console.log(`${colors.red}Find group members here: https://github.com/orgs/lifinance/teams/information-security-manager.${colors.reset}`); | |
console.log(`${colors.red}Check failed.${colors.reset}`); | |
core.setFailed("Required approval is missing"); | |
} |