Skip to content

Initiate new vote

Initiate new vote #35

Workflow file for this run

name: Initiate new vote
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- votes/initiateNewVote/_EDIT_ME.yml
push:
branches:
- initiateNewVote
env:
STAGING_VOTE_BRANCH: initiateNewVote
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
lint-vote-init-file:
if: github.event.pull_request && github.event.pull_request.draft == false
permissions:
contents: write
pull-requests: write
repository-projects: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
# If the subject is still REPLACEME, that would mean it's a PR to modify
# the sample file, not a PR initializing a vote.
- run: '! grep -q "subject: REPLACEME" votes/initiateNewVote.yml'
- name: Validate YAML and ensure there are more than 1 candidate
run:
npx js-yaml votes/initiateNewVote.yml | jq '.candidates | unique |
length > 1 or error("Not enough candidates")'
- name: Change base branch
if: github.base_ref == github.event.repository.default_branch
run: |
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/$GITHUB_REPOSITORY/git/refs \
-f ref="refs/heads/$STAGING_VOTE_BRANCH" \
-f sha="$BASE_SHA" || true
gh pr edit "$PR_URL" --base "$STAGING_VOTE_BRANCH"
env:
GH_TOKEN: ${{ github.token }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_URL: ${{ github.event.pull_request.html_url }}
initiate-new-vote:
if: github.event.pusher
permissions:
contents: write
pull-requests: write
repository-projects: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
fetch-depth: 2
- name: Extract info from the pushed file
id: data
run: |
npx js-yaml votes/initiateNewVote/_EDIT_ME.yml > data.json
{
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "json_data<<$EOF"
cat data.json
echo "$EOF"
} >> "$GITHUB_OUTPUT"
echo "branchName=votes/$(node -p 'require("./data.json")["path-friendly-id"] || crypto.randomUUID()')" >> "$GITHUB_OUTPUT"
node >> "$GITHUB_ENV" <<'EOF'
'use strict';
const { createHash } = require('node:crypto');
const { candidates, secretHolders } = require("./data.json");
for (let i = 0; i < candidates.length; i++) {
const delimiter = createHash('sha256').update(candidates[i], 'utf8').digest('base64');
console.log(`__CANDIDATES_${i}<<${delimiter}`)
process.stdout.write(candidates[i]);
process.stdout.write(`\n${delimiter}\n`);
}
console.log('__CANDIDATES<<EOF');
for (let i = 0; i < candidates.length; i++) {
console.log(`--candidate "$__CANDIDATES_${i}" \\`);
}
if (candidates.length) console.log('');
console.log('EOF');
for (let i = 0; i < secretHolders.length; i++) {
const delimiter = createHash('sha256').update(secretHolders[i], 'utf8').digest('base64');
console.log(`__SECRET_HOLDER_${i}<<${delimiter}`)
process.stdout.write(secretHolders[i]);
process.stdout.write(`\n${delimiter}\n`);
}
console.log('__SECRET_HOLDERS<<EOF');
for (let i = 0; i < secretHolders.length; i++) {
console.log(`--secret-holder "$__SECRET_HOLDER_${i}" \\`);
}
if (secretHolders.length) console.log('');
console.log('EOF');
EOF
- name: Reset to the base branch
run: git fetch origin HEAD && git reset FETCH_HEAD --hard
- name: Install npm dependencies
run: npm install @node-core/caritat
- name: Configure git
run: |
git config --global user.email "[email protected]"
git config --global user.name "Node.js GitHub Bot"
- name: Configure and (re)start GPG agent
shell: bash
run: |
if [ -f /usr/lib/systemd/user/gpg-agent.service ]; then
mkdir ~/.gnupg
cat <<EOT >> ~/.gnupg/gpg-agent.conf
allow-preset-passphrase
default-cache-ttl 60
max-cache-ttl 50
EOT
chmod 600 ~/.gnupg/*
chmod 700 ~/.gnupg
systemctl --user restart gpg-agent
else
gpg-agent --daemon --allow-preset-passphrase \
--default-cache-ttl 60 --max-cache-ttl 60
fi
- name: Generate the vote init commit
run: |
./votes/initiateNewVote/generateVoteInitCommit.mjs \
--remote origin \
--github-repo-name "$GITHUB_REPOSITORY" \
--vote-repository-path . \
--branch "$__BRANCH" \
--subject "$__SUBJECT" \
${{ env.__CANDIDATES }} \
${{ env.__SECRET_HOLDERS }} \
--shuffle-candidates "$__SHUFFLE_CANDIDATES" \
--header-instructions "$__HEADER_INSTRUCTIONS" \
--footer-instructions "$__FOOTER_INSTRUCTIONS"
env:
GH_TOKEN: ${{ github.token }}
__BRANCH: ${{ steps.data.outputs.branchName }}
__SUBJECT: ${{ fromJSON(steps.data.outputs.json_data).subject }}
__SHUFFLE_CANDIDATES: ${{ fromJSON(steps.data.outputs.json_data).canShuffleCandidates }}
__HEADER_INSTRUCTIONS: ${{ fromJSON(steps.data.outputs.json_data).headerInstructions }}
__FOOTER_INSTRUCTIONS: ${{ fromJSON(steps.data.outputs.json_data).footerInstructions }}
- run: git reset HEAD --hard
- name: Generate the vote branch
run: |
PARENT_SHA=$(git rev-parse HEAD^)
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/$GITHUB_REPOSITORY/git/refs \
-f "ref=refs/heads/$BRANCH_NAME" -f "sha=$PARENT_SHA"
./votes/initiateNewVote/createCommitOnBranch.mjs \
"$GITHUB_REPOSITORY" \
"$BRANCH_NAME" \
"$PARENT_SHA" "$(
# Modified or added files
git show HEAD --name-only --diff-filter=d --pretty=format:
)" "$(
# Deleted files
git show HEAD --name-only --diff-filter=D --pretty=format:
)" "$(
# Commit title
git log -1 HEAD --pretty=format:%s
)" "$(
# Commit body
git log -1 HEAD --pretty=format:%b
)"
env:
GH_TOKEN: ${{ github.token }}
BRANCH_NAME: ${{ steps.data.outputs.branchName }}
- name: Open the vote PR
run: |
./votes/initiateNewVote/generateNewVotePR.mjs \
--github-repo-name "$GITHUB_REPOSITORY" \
--branch "$__BRANCH" \
--subject "$__SUBJECT" \
--pr-intro "$__PR_INTRO"
env:
GH_TOKEN: ${{ github.token }}
__BRANCH: ${{ steps.data.outputs.branchName }}
__SUBJECT: ${{ fromJSON(steps.data.outputs.json_data).subject }}
__PR_INTRO: ${{ fromJSON(steps.data.outputs.json_data).prBody }}
- name: Remove ${{ env.STAGING_VOTE_BRANCH }} branch if there are no open PRs, or revert commit
run: |
set -x
if [[ "$(gh search prs --repo="$GITHUB_REPOSITORY" --state open -B "$STAGING_VOTE_BRANCH" --jq '. | length' --json id)" == "0" ]]; then
gh api \
--method DELETE \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$GITHUB_REPOSITORY/git/$GITHUB_REF"
else
git reset "$GITHUB_SHA" --hard
git revert HEAD --no-edit
./votes/initiateNewVote/createCommitOnBranch.mjs \
"$GITHUB_REPOSITORY" \
"$STAGING_VOTE_BRANCH" \
"$GITHUB_SHA" "$(
# Modified or added files
git show HEAD --name-only --diff-filter=d --pretty=format:
)" "$(
# Deleted files
git show HEAD --name-only --diff-filter=D --pretty=format:
)" "$(
# Commit title
git log -1 HEAD --pretty=format:%s
)" "$(
# Commit body
git log -1 HEAD --pretty=format:%b
)"
gh api graphql -F base="$STAGING_VOTE_BRANCH" -F head="$HEAD" -F repoID="$REPO_ID" -f query='
mutation(base: String!, head: String!, repoID: ID!) {
mergeBranch(input: {
base: $base,
head: $head,
repositoryId: $repoID
}) {
mergeCommit {
oid
}
}
}'
fi
env:
HEAD: ${{ github.event.repository.default_branch }}
REPO_ID: ${{ github.event.repository.id }}
GH_TOKEN: ${{ github.token }}