feat: enhance shas parsing logic in update workflow

This commit is contained in:
robertsLando 2025-10-20 18:15:55 +02:00
parent d1da523a05
commit cda5244d2a
No known key found for this signature in database
3 changed files with 113 additions and 37 deletions

View File

@ -26,6 +26,8 @@ jobs:
actions: write
runs-on: ubuntu-latest
needs: [build-alpine, build-linux, build-linuxstatic, build-macos, build-windows]
outputs:
shas: ${{ steps.generate_sha_file.outputs.shas_txt }}
steps:
- run: echo Is making new release? '${{ inputs.newRelease }}'
- name: Checkout
@ -92,11 +94,14 @@ jobs:
echo "### SHAs of produced and carried forward binaries by this workflow" >> $GITHUB_STEP_SUMMARY
echo " - $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
sha_output_file=${GITHUB_SHA}_${RANDOM}_shas.txt
echo "sha_output_file=${sha_output_file}" >> $GITHUB_OUTPUT
cat artifact-shas/*.sha256sum > ${sha_output_file}
cat artifact-shas/*.sha256sum >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
# Store SHAs in output variable using multiline format
echo "shas_txt<<EOF" >> $GITHUB_OUTPUT
cat artifact-shas/*.sha256sum >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# Get a random string of characters to represent the EOF delimiter
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "sha_summary<<$EOF" >> $GITHUB_ENV
@ -130,11 +135,8 @@ jobs:
- name: Add release url to summary
run: echo "Release created/updated at ${{ steps.create_release.outputs.url }}" >> $GITHUB_STEP_SUMMARY
- name: Create PR for expected shas update
run: |
# trigger the update-expected.yml workflow with the latest shas
curl -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/actions/workflows/update-expected.yml/dispatches \
-d '{"ref":"main","inputs":{"shas":"$(cat ${{ steps.generate_sha_file.outputs.sha_output_file }})"}}'
update-expected-shas:
needs: collect-artifacts
uses: ./.github/workflows/update-expected.yml
with:
shas: ${{ needs.collect-artifacts.outputs.shas }}

View File

@ -32,33 +32,16 @@ jobs:
- name: Install deps
run: yarn install --ignore-engines
- name: Parses shas
id: parse-shas
- name: Parse and update shas.txt
run: |
echo "${{ inputs.shas }}\n" | while read -r sha patchName; do
# ensure sha and patchName are set
if [ -z "$sha" ] || [ -z "$patchName" ]; then
echo "Done"
continue
fi
echo "sha: $sha, patchName: $patchName"
# get node major, os and arch from patchName
major=$(echo $patchName | grep -oP 'node-v\K[0-9]+')
os=$(echo $patchName | grep -oP 'node-v[0-9.]+-(.*)-' | cut -d'-' -f3)
arch=$(echo $patchName | grep -oP 'node-v[0-9.]+-(.*)-(.*)' | cut -d'-' -f4)
if grep -E -q "$major\.([0-9.]+){2}-$os-$arch" shas.txt; then
sed -i -E "/$major\.([0-9.]+){2}-$os-$arch/c $sha $patchName" shas.txt
else
# if file doesn't end with a newline, add it
if [ "$(tail -c 1 shas.txt)" != "" ]; then
echo "" >> shas.txt
fi
echo "$sha $patchName" >> shas.txt
fi
done
# Write the shas input to a temporary file outside the repo
tmp_file="/tmp/new-shas-${GITHUB_RUN_ID}.txt"
echo "${{ inputs.shas }}" > "$tmp_file"
# Build and run the TypeScript script
yarn build
node lib-es5/parse-update-shas.js "$tmp_file"
# Clean up the temporary file
rm "$tmp_file"
- name: Update expected shas
run: |
yarn updateExpected

91
lib/parse-update-shas.ts Normal file
View File

@ -0,0 +1,91 @@
import * as fs from 'fs';
import * as path from 'path';
import { log, wasReported } from './log';
function parseAndUpdateShas(inputFile: string): void {
// Read the input file containing new SHAs
if (!fs.existsSync(inputFile)) {
throw wasReported(`Input file ${inputFile} does not exist`);
}
const input = fs.readFileSync(inputFile, 'utf8');
const lines = input.split('\n').map(l => l.trim()).filter(Boolean);
// Read existing shas.txt
const shasPath = path.join(process.cwd(), 'shas.txt');
let shasTxt = '';
try {
shasTxt = fs.readFileSync(shasPath, 'utf8');
} catch (e) {
log.info('shas.txt not found, creating new one');
shasTxt = '';
}
let shasArr = shasTxt.split('\n');
// Process each line from input
for (const line of lines) {
const [sha, patchName] = line.split(/\s+/);
if (!sha || !patchName) {
log.warn(`Skipping invalid line: ${line}`);
continue;
}
// Extract major, os, arch. E.g.: node-v22.20.0-win-x64
const match = patchName.match(/^node-v(\d+)\.[^ ]*-(.+)-(.+)$/);
if (!match) {
log.warn(`Skipping line with invalid patch name format: ${line}`);
continue;
}
const major = match[1];
const os = match[2];
const arch = match[3];
// Regex for matching line in shas.txt
const re = new RegExp(`^\\S+\\s+node-v${major}\\.([0-9.]+){2}-${os}-${arch}$`);
let found = false;
shasArr = shasArr.map(l => {
if (re.test(l)) {
found = true;
log.info(`Updating: ${l} -> ${sha} ${patchName}`);
return `${sha} ${patchName}`;
}
return l;
});
if (!found) {
log.info(`Adding new entry: ${sha} ${patchName}`);
shasArr.push(`${sha} ${patchName}`);
}
}
// Write updated shas.txt
const filteredShas = shasArr.filter(Boolean);
const updatedContent = filteredShas.length > 0 ? `${filteredShas.join('\n')}\n` : '';
fs.writeFileSync(shasPath, updatedContent);
log.info(`Successfully updated ${shasPath}`);
}
// Main execution
if (require.main === module) {
const args = process.argv.slice(2);
if (args.length !== 1) {
log.error('Usage: parse-update-shas.ts <input-file>');
log.error(' input-file: Path to file containing SHA lines in format "<sha> <patch-name>"');
process.exit(1);
}
const inputFile = args[0];
try {
parseAndUpdateShas(inputFile);
} catch (error) {
if (error instanceof Error && !('wasReported' in error)) {
log.error(error);
}
process.exit(1);
}
}
export { parseAndUpdateShas };