Skip to content

ci: check sha #1792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .github/workflows/verify-packages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Verify Package Builds

on:
push:

jobs:
verify:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Install tsx globally
run: npm install -g tsx

- name: Get tags older than 6 months
id: get_tags
run: |
TAGS=$(git for-each-ref --sort=-taggerdate --format '%(refname:short) %(taggerdate:iso8601)' refs/tags | \
awk -v date="$(date -d '6 months ago' +%Y-%m-%d)" '$2 < date {print $1}')
echo "tags<<EOF" >> $GITHUB_OUTPUT
echo "$TAGS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Verify packages for each tag
id: verify_tags
run: |
set -e
mkdir -p results
echo "| Tag | Result | Differing Packages |" > results/summary.md
echo "|-----|--------|--------------------|" >> results/summary.md
echo "Tags to check:"
echo "${{ steps.get_tags.outputs.tags }}"
for TAG in ${{ steps.get_tags.outputs.tags }}; do
echo "\nProcessing tag: $TAG"
echo "Checking out $TAG"
git checkout $TAG
npm ci || { echo "| $TAG | npm ci failed | - |" >> results/summary.md; continue; }
echo "Running build-packages.ts for tag: $TAG"
DIFFERS_JSON=$(TAG=$TAG npx tsx ./build-packages.ts)
echo "build-packages.ts output for $TAG: $DIFFERS_JSON"
if [ "$DIFFERS_JSON" != "[]" ]; then
# Remove brackets and quotes for markdown table
DIFFERS_LIST=$(echo $DIFFERS_JSON | jq -r '. | join(", ")')
echo "| $TAG | ❌ Mismatch | $DIFFERS_LIST |" >> results/summary.md
else
echo "| $TAG | ✅ Match | - |" >> results/summary.md
fi
done
git checkout $GITHUB_SHA # Return to original commit

- name: Print summary table
run: |
cat results/summary.md

# continue: check github action status !!!
90 changes: 90 additions & 0 deletions build-packages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env tsx

import * as fs from 'fs';
import * as path from 'path';
import { spawnSync } from 'child_process';

const ORIGINAL_DIR = process.cwd();
const PACKAGES_DIR = path.resolve(ORIGINAL_DIR, 'packages');

// Get all package directories
const packages = fs.readdirSync(PACKAGES_DIR).filter(item => {
const itemPath = path.join(PACKAGES_DIR, item);
return fs.statSync(itemPath).isDirectory() && !item.startsWith('.');
});

// console.debug(`Found ${packages.length} packages to process`);

const NPM_VERSION_TAG = (process.env.NPM_VERSION_TAG || 'latest').replace(/^v/, '');

// Process all packages
const results = packages
.map(dir => {
const json = path.join(PACKAGES_DIR, dir, 'package.json');
const pkg = JSON.parse(fs.readFileSync(json, 'utf8'));

if (pkg.private === true) {
// console.debug(`Skipping package: ${pkg.name}`);
return null;
}

// console.debug(`\nProcessing package: ${pkg.name}`);
process.chdir(path.join(PACKAGES_DIR, dir));

// Run npm publish dry-run
const result = spawnSync('npm', ['publish', '--dry-run'], { encoding: 'utf8' });
const output = `${result.stdout}\n${result.stderr}`;

// Extract values using inline functions
const shasum = extractFromOutput(output, /npm notice shasum:\s+([a-f0-9]{40})/);
const integrity = extractFromOutput(
output,
/npm notice integrity:\s+(sha\d+-[A-Za-z0-9+/=]+(?:\[\.\.\.\][A-Za-z0-9+/=]*==?)?)/
);

// console.debug(` Package: ${pkg.name}`);
// console.debug(` Tarball hash: ${integrity}`);
// console.debug(` Shasum: ${shasum}`);

const registryUrl = `https://registry.npmjs.org/${pkg.name}/${NPM_VERSION_TAG}`;
const registryCheck = spawnSync('curl', [registryUrl], {
encoding: 'utf8',
});
const registryData = JSON.parse(registryCheck.stdout);
const registryShasum = registryData.dist?.shasum;

return {
name: pkg.name,
tarballHash: integrity,
shasum,
differs: registryShasum === shasum,
};
})
.filter(Boolean) as (PackageInfo & { differs: boolean })[];

// Restore original directory
process.chdir(ORIGINAL_DIR);

// Output final results
// console.debug('\n=== PACKAGE BUILD RESULTS ===');
// console.debug(results);

// Output JSON array of differing packages
const differingPackages = results.filter(r => r.differs).map(r => r.name);
console.log(JSON.stringify(differingPackages));

// HELPERS
function extractFromOutput(output: string, regex: RegExp): string {
return (
output
.split('\n')
.map(line => line.match(regex)?.[1])
.find(Boolean) || 'Not found'
);
}

interface PackageInfo {
name: string;
tarballHash: string;
shasum: string;
}
Loading