Skip to content

chore: add release test workflow for dry-run testing #3

chore: add release test workflow for dry-run testing

chore: add release test workflow for dry-run testing #3

Workflow file for this run

name: Release
on:
# Trigger on version tags (e.g., v1.0.0, v1.2.3)
push:
tags:
- 'v*.*.*'
# Security: Minimal permissions following principle of least privilege
permissions:
contents: write # Create releases
id-token: write # For npm publish (OIDC)
jobs:
release:
runs-on: ubuntu-latest
steps:
# Security: Using version tags (consider pinning to commit SHAs for production)
# To get latest SHA: https://api.github.com/repos/actions/checkout/commits/main
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history for changelog
# Note: github.ref automatically points to the tag that triggered this workflow
# Security: Using version tags (consider pinning to commit SHAs for production)
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
# Security: No cache needed - this repo has zero dependencies
# Security: Verify no package installations in workflow files
- name: Security Check - No Package Installations
run: |
echo "🔍 Scanning workflow files for security..."
if grep -rE "(npm install|npm ci|yarn install|pnpm install|bun install|pip install|pip3 install)" .github/workflows/ 2>/dev/null; then
echo "❌ ERROR: Package installation detected in workflow files!"
echo "This repository uses zero dependencies - no installs should be needed"
exit 1
fi
echo "✅ No package installations found in workflows"
# Security: Verify package.json has zero dependencies
- name: Security Check - Zero Dependencies
run: |
echo "🔍 Verifying package.json has zero dependencies..."
if node -e "const pkg = require('./package.json'); if (pkg.dependencies || pkg.devDependencies) { console.error('ERROR: Dependencies found!'); console.error('dependencies:', pkg.dependencies); console.error('devDependencies:', pkg.devDependencies); process.exit(1); } else { console.log('✅ Zero dependencies confirmed'); }"; then
echo "✅ Package has zero dependencies - safe from supply chain attacks"
else
echo "❌ ERROR: Dependencies detected in package.json"
echo "This is a security risk - this package should have zero dependencies"
exit 1
fi
# Security: Verify no node_modules directory exists
- name: Security Check - No node_modules
run: |
if [ -d "node_modules" ]; then
echo "❌ ERROR: node_modules directory found!"
echo "This repository should not have any installed dependencies"
exit 1
fi
echo "✅ No node_modules directory found"
- name: Extract version from tag
id: version
run: |
# Extract version from tag (remove 'v' prefix)
VERSION="${GITHUB_REF#refs/tags/v}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
echo "📦 Version: $VERSION"
- name: Verify version matches package.json
run: |
PACKAGE_VERSION=$(node -p "require('./package.json').version")
if [ "$PACKAGE_VERSION" != "${{ steps.version.outputs.version }}" ]; then
echo "❌ ERROR: Version mismatch!"
echo " Tag version: ${{ steps.version.outputs.version }}"
echo " package.json version: $PACKAGE_VERSION"
exit 1
fi
echo "✅ Version matches package.json"
# Security: Verify package.json integrity
- name: Security Check - Package.json Integrity
run: |
echo "🔍 Verifying package.json integrity..."
# Check for suspicious install scripts that might indicate tampering
node -e "
const pkg = require('./package.json');
const scripts = pkg.scripts || {};
const suspicious = Object.keys(scripts).filter(k =>
k.includes('install') || k.includes('post') || k.includes('pre')
);
if (suspicious.length > 0) {
console.error('❌ ERROR: Suspicious scripts found:', suspicious);
console.error('Scripts:', suspicious.map(s => scripts[s]).join(', '));
process.exit(1);
}
console.log('✅ Package.json integrity check passed');
"
- name: Run tests
run: |
echo "🧪 Running tests before release..."
npm run test:smoke
# Security: Verify npm token is set (but don't expose it)
# Note: In GitHub Actions, secrets are always non-empty strings (masked if not set)
# We'll verify it works by checking if npm can authenticate
- name: Security Check - NPM Token
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
echo "🔍 Verifying NPM_TOKEN..."
# Try to get npm user info (this will fail if token is invalid/missing)
if npm whoami --registry=https://registry.npmjs.org 2>/dev/null; then
echo "✅ NPM_TOKEN is valid and configured"
else
echo "❌ ERROR: NPM_TOKEN is missing or invalid!"
echo "Please add a valid NPM_TOKEN to repository secrets"
exit 1
fi
# Security: Dry run first to verify package contents
- name: Security Check - npm publish dry run
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
echo "🔍 Running npm publish dry run to verify package contents..."
npm publish --dry-run --access public
echo "✅ Dry run successful - package contents verified"
- name: Publish to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
echo "📦 Publishing to npm..."
# Security: Use --dry-run flag removed, but we already verified above
npm publish --access public
echo "✅ Published @dreamhorizonorg/sentinel@${{ steps.version.outputs.version }} to npm"
- name: Generate release notes from CHANGELOG
id: release_notes
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="${{ steps.version.outputs.tag }}"
REPO="${{ github.repository }}"
# Extract changelog entry for this version
if [ -f CHANGELOG.md ]; then
# Get changelog section for this version (from ## [VERSION] to next ##)
# Use a more robust awk script that handles multiline content
CHANGELOG_SECTION=$(awk -v version="$VERSION" '
/^## \[/ {
if (found) exit
if ($0 ~ "## \\[" version "\\]") {
found = 1
print
next
}
}
found { print }
' CHANGELOG.md)
if [ -z "$CHANGELOG_SECTION" ]; then
# Fallback if version not found in changelog
CHANGELOG_SECTION="## Changes
See [CHANGELOG.md](https://github.com/$REPO/blob/main/CHANGELOG.md) for details."

Check failure on line 174 in .github/workflows/release.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/release.yml

Invalid workflow file

You have an error in your yaml syntax on line 174
fi
else
CHANGELOG_SECTION="## Changes
See commit history for details."
fi
# Create release notes using a here-doc with proper escaping
{
echo "# 🛡️ Sentinel Package Manager $VERSION"
echo ""
echo "$CHANGELOG_SECTION"
echo ""
echo "## 📦 Installation"
echo ""
echo "\`\`\`bash"
echo "npm install -g @dreamhorizonorg/sentinel@$VERSION"
echo "\`\`\`"
echo ""
echo "## 🔗 Links"
echo ""
echo "- **npm**: https://www.npmjs.com/package/@dreamhorizonorg/sentinel/v/$VERSION"
echo "- **GitHub**: https://github.com/$REPO/releases/tag/$TAG"
echo "- **Documentation**: https://github.com/$REPO#readme"
} > release_notes.md
# Security: Using version tag (consider pinning to commit SHA)
# Latest SHA: https://api.github.com/repos/softprops/action-gh-release/commits/main
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.version.outputs.tag }}
name: Release ${{ steps.version.outputs.tag }}
body_path: release_notes.md
draft: false
prerelease: ${{ contains(steps.version.outputs.version, '-') || contains(steps.version.outputs.version, 'alpha') || contains(steps.version.outputs.version, 'beta') || contains(steps.version.outputs.version, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release summary
run: |
echo "## 🎉 Release Complete!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version**: ${{ steps.version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
echo "**npm**: https://www.npmjs.com/package/@dreamhorizonorg/sentinel/v/${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**GitHub Release**: https://github.com/${{ github.repository }}/releases/tag/${{ steps.version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY