diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml new file mode 100644 index 00000000000..5bdacc4584c --- /dev/null +++ b/.github/workflows/dependency-check.yml @@ -0,0 +1,211 @@ +name: Dependency Status Check + +on: + workflow_dispatch: + inputs: + check_type: + description: "Type of dependency check" + required: false + default: "all" + type: choice + options: + - all + - node + - dotnet + - docker + - npm + schedule: + - cron: "0 8 * * 1" # Weekly on Monday at 8 AM + +jobs: + dependency-status: + runs-on: path-test-2 + outputs: + node20-status: ${{ steps.check-versions.outputs.node20-status }} + node24-status: ${{ steps.check-versions.outputs.node24-status }} + dotnet-status: ${{ steps.check-versions.outputs.dotnet-status }} + docker-status: ${{ steps.check-versions.outputs.docker-status }} + buildx-status: ${{ steps.check-versions.outputs.buildx-status }} + npm-vulnerabilities: ${{ steps.check-versions.outputs.npm-vulnerabilities }} + open-dependency-prs: ${{ steps.check-prs.outputs.open-dependency-prs }} + steps: + - uses: actions/checkout@v5 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Check dependency versions + id: check-versions + run: | + echo "## Dependency Status Report" >> $GITHUB_STEP_SUMMARY + echo "Generated on: $(date)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Check Node versions + if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "node" ]]; then + echo "### Node.js Versions" >> $GITHUB_STEP_SUMMARY + + VERSIONS_JSON=$(curl -s https://raw.githubusercontent.com/actions/node-versions/main/versions-manifest.json) + LATEST_NODE20=$(echo "$VERSIONS_JSON" | jq -r '.[] | select(.version | startswith("20.")) | .version' | head -1) + LATEST_NODE24=$(echo "$VERSIONS_JSON" | jq -r '.[] | select(.version | startswith("24.")) | .version' | head -1) + + CURRENT_NODE20=$(grep "NODE20_VERSION=" src/Misc/externals.sh | cut -d'"' -f2) + CURRENT_NODE24=$(grep "NODE24_VERSION=" src/Misc/externals.sh | cut -d'"' -f2) + + NODE20_STATUS="✅ up-to-date" + NODE24_STATUS="✅ up-to-date" + + if [ "$CURRENT_NODE20" != "$LATEST_NODE20" ]; then + NODE20_STATUS="⚠️ outdated" + fi + + if [ "$CURRENT_NODE24" != "$LATEST_NODE24" ]; then + NODE24_STATUS="⚠️ outdated" + fi + + echo "| Version | Current | Latest | Status |" >> $GITHUB_STEP_SUMMARY + echo "|---------|---------|--------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Node 20 | $CURRENT_NODE20 | $LATEST_NODE20 | $NODE20_STATUS |" >> $GITHUB_STEP_SUMMARY + echo "| Node 24 | $CURRENT_NODE24 | $LATEST_NODE24 | $NODE24_STATUS |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + echo "node20-status=$NODE20_STATUS" >> $GITHUB_OUTPUT + echo "node24-status=$NODE24_STATUS" >> $GITHUB_OUTPUT + fi + + # Check .NET version + if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "dotnet" ]]; then + echo "### .NET SDK Version" >> $GITHUB_STEP_SUMMARY + + current_dotnet_version=$(jq -r .sdk.version ./src/global.json) + current_major_minor=$(echo "$current_dotnet_version" | cut -d '.' -f 1,2) + latest_dotnet_version=$(curl -sb -H "Accept: application/json" "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$current_major_minor/latest.version") + + DOTNET_STATUS="✅ up-to-date" + if [ "$current_dotnet_version" != "$latest_dotnet_version" ]; then + DOTNET_STATUS="⚠️ outdated" + fi + + echo "| Component | Current | Latest | Status |" >> $GITHUB_STEP_SUMMARY + echo "|-----------|---------|--------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| .NET SDK | $current_dotnet_version | $latest_dotnet_version | $DOTNET_STATUS |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + echo "dotnet-status=$DOTNET_STATUS" >> $GITHUB_OUTPUT + fi + + # Check Docker versions + if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "docker" ]]; then + echo "### Docker Versions" >> $GITHUB_STEP_SUMMARY + + current_docker=$(grep "ARG DOCKER_VERSION=" ./images/Dockerfile | cut -d'=' -f2) + current_buildx=$(grep "ARG BUILDX_VERSION=" ./images/Dockerfile | cut -d'=' -f2) + + latest_docker=$(curl -s https://download.docker.com/linux/static/stable/x86_64/ | grep -o 'docker-[0-9]*\.[0-9]*\.[0-9]*\.tgz' | sort -V | tail -n 1 | sed 's/docker-\(.*\)\.tgz/\1/') + latest_buildx=$(curl -s https://api.github.com/repos/docker/buildx/releases/latest | jq -r '.tag_name' | sed 's/^v//') + + DOCKER_STATUS="✅ up-to-date" + BUILDX_STATUS="✅ up-to-date" + + if [ "$current_docker" != "$latest_docker" ]; then + DOCKER_STATUS="⚠️ outdated" + fi + + if [ "$current_buildx" != "$latest_buildx" ]; then + BUILDX_STATUS="⚠️ outdated" + fi + + echo "| Component | Current | Latest | Status |" >> $GITHUB_STEP_SUMMARY + echo "|-----------|---------|--------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Docker | $current_docker | $latest_docker | $DOCKER_STATUS |" >> $GITHUB_STEP_SUMMARY + echo "| Docker Buildx | $current_buildx | $latest_buildx | $BUILDX_STATUS |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + echo "docker-status=$DOCKER_STATUS" >> $GITHUB_OUTPUT + echo "buildx-status=$BUILDX_STATUS" >> $GITHUB_OUTPUT + fi + + # Check npm vulnerabilities + if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "npm" ]]; then + echo "### NPM Security Audit" >> $GITHUB_STEP_SUMMARY + + cd src/Misc/expressionFunc/hashFiles + npm install --silent + + AUDIT_OUTPUT="" + AUDIT_EXIT_CODE=0 + # Run npm audit and capture output and exit code + if ! AUDIT_OUTPUT=$(npm audit --json 2>&1); then + AUDIT_EXIT_CODE=$? + fi + + # Check if output is valid JSON + if echo "$AUDIT_OUTPUT" | jq . >/dev/null 2>&1; then + VULN_COUNT=$(echo "$AUDIT_OUTPUT" | jq '.metadata.vulnerabilities.total // 0') + # Ensure VULN_COUNT is a number + VULN_COUNT=$(echo "$VULN_COUNT" | grep -o '[0-9]*' | head -1) + VULN_COUNT=${VULN_COUNT:-0} + + NPM_STATUS="✅ no vulnerabilities" + if [ "$VULN_COUNT" -gt 0 ] 2>/dev/null; then + NPM_STATUS="⚠️ $VULN_COUNT vulnerabilities found" + + # Get vulnerability details + HIGH_VULNS=$(echo "$AUDIT_OUTPUT" | jq '.metadata.vulnerabilities.high // 0') + CRITICAL_VULNS=$(echo "$AUDIT_OUTPUT" | jq '.metadata.vulnerabilities.critical // 0') + + echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY + echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Critical | $CRITICAL_VULNS |" >> $GITHUB_STEP_SUMMARY + echo "| High | $HIGH_VULNS |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + else + echo "No npm vulnerabilities found ✅" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + fi + else + NPM_STATUS="❌ npm audit failed" + echo "npm audit failed to run or returned invalid JSON ❌" >> $GITHUB_STEP_SUMMARY + echo "Exit code: $AUDIT_EXIT_CODE" >> $GITHUB_STEP_SUMMARY + echo "Output: $AUDIT_OUTPUT" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + fi + + echo "npm-vulnerabilities=$NPM_STATUS" >> $GITHUB_OUTPUT + fi + + - name: Check for open dependency PRs + id: check-prs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "### Open Dependency PRs" >> $GITHUB_STEP_SUMMARY + + # Get open PRs with dependency label + OPEN_PRS=$(gh pr list --label "dependency" --state open --json number,title,url) + PR_COUNT=$(echo "$OPEN_PRS" | jq '. | length') + + if [ "$PR_COUNT" -gt 0 ]; then + echo "Found $PR_COUNT open dependency PR(s):" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "$OPEN_PRS" | jq -r '.[] | "- [#\(.number)](\(.url)) \(.title)"' >> $GITHUB_STEP_SUMMARY + else + echo "No open dependency PRs found ✅" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "open-dependency-prs=$PR_COUNT" >> $GITHUB_OUTPUT + + - name: Summary + run: | + echo "### Summary" >> $GITHUB_STEP_SUMMARY + echo "- Check for open PRs with the \`dependency\` label before releases" >> $GITHUB_STEP_SUMMARY + echo "- Review and merge dependency updates regularly" >> $GITHUB_STEP_SUMMARY + echo "- Critical vulnerabilities should be addressed immediately" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Automated workflows run weekly to check for updates:**" >> $GITHUB_STEP_SUMMARY + echo "- Node.js versions (Mondays at 6 AM)" >> $GITHUB_STEP_SUMMARY + echo "- NPM audit fix (Mondays at 7 AM)" >> $GITHUB_STEP_SUMMARY + echo "- .NET SDK updates (Mondays at midnight)" >> $GITHUB_STEP_SUMMARY + echo "- Docker/Buildx updates (Mondays at midnight)" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/docker-buildx-upgrade.yml b/.github/workflows/docker-buildx-upgrade.yml index 2a214415904..ab60e012a6c 100644 --- a/.github/workflows/docker-buildx-upgrade.yml +++ b/.github/workflows/docker-buildx-upgrade.yml @@ -2,8 +2,8 @@ name: "Docker/Buildx Version Upgrade" on: schedule: - - cron: '0 0 * * 1' # Run every Monday at midnight - workflow_dispatch: # Allow manual triggering + - cron: "0 0 * * 1" # Run every Monday at midnight + workflow_dispatch: # Allow manual triggering jobs: check-versions: @@ -35,7 +35,7 @@ jobs: echo "Failed to retrieve a valid Docker version" exit 1 fi - + should_update=0 [ "$current_version" != "$latest_version" ] && should_update=1 @@ -64,17 +64,17 @@ jobs: run: | docker_should_update="${{ steps.check_docker_version.outputs.SHOULD_UPDATE }}" buildx_should_update="${{ steps.check_buildx_version.outputs.SHOULD_UPDATE }}" - + # Show annotation if only Docker needs update if [[ "$docker_should_update" == "1" && "$buildx_should_update" == "0" ]]; then echo "::warning ::Docker version (${{ steps.check_docker_version.outputs.LATEST_VERSION }}) needs update but Buildx is current. Only updating when both need updates." fi - + # Show annotation if only Buildx needs update if [[ "$docker_should_update" == "0" && "$buildx_should_update" == "1" ]]; then echo "::warning ::Buildx version (${{ steps.check_buildx_version.outputs.LATEST_VERSION }}) needs update but Docker is current. Only updating when both need updates." fi - + # Show annotation when both are current if [[ "$docker_should_update" == "0" && "$buildx_should_update" == "0" ]]; then echo "::warning ::Latest Docker version is ${{ steps.check_docker_version.outputs.LATEST_VERSION }} and Buildx version is ${{ steps.check_buildx_version.outputs.LATEST_VERSION }}. No updates needed." @@ -90,25 +90,25 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v5 - + - name: Update Docker version shell: bash run: | latest_version="${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }}" current_version="${{ needs.check-versions.outputs.DOCKER_CURRENT_VERSION }}" - + # Update version in Dockerfile sed -i "s/ARG DOCKER_VERSION=$current_version/ARG DOCKER_VERSION=$latest_version/g" ./images/Dockerfile - + - name: Update Buildx version shell: bash run: | latest_version="${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}" current_version="${{ needs.check-versions.outputs.BUILDX_CURRENT_VERSION }}" - + # Update version in Dockerfile sed -i "s/ARG BUILDX_VERSION=$current_version/ARG BUILDX_VERSION=$latest_version/g" ./images/Dockerfile - + - name: Commit changes and create Pull Request env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -117,7 +117,7 @@ jobs: branch_name="feature/docker-buildx-upgrade" commit_message="Upgrade Docker to v${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }} and Buildx to v${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}" pr_title="Update Docker to v${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }} and Buildx to v${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}" - + # Configure git git config --global user.name "github-actions[bot]" git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>" @@ -129,16 +129,17 @@ jobs: else git checkout -b "$branch_name" fi - + # Commit and push changes git commit -a -m "$commit_message" git push --force origin "$branch_name" - + # Create PR pr_body="Upgrades Docker version from ${{ needs.check-versions.outputs.DOCKER_CURRENT_VERSION }} to ${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }} and Docker Buildx version from ${{ needs.check-versions.outputs.BUILDX_CURRENT_VERSION }} to ${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}.\n\n" pr_body+="Release notes: https://docs.docker.com/engine/release-notes/\n\n" pr_body+="---\n\nAutogenerated by [Docker/Buildx Version Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/docker-buildx-upgrade.yml)" - + gh pr create -B main -H "$branch_name" \ --title "$pr_title" \ - --body "$pr_body" + --body "$pr_body" \ + --label "dependency" diff --git a/.github/workflows/dotnet-upgrade.yml b/.github/workflows/dotnet-upgrade.yml index 80049e64338..bd6dd08b5cf 100644 --- a/.github/workflows/dotnet-upgrade.yml +++ b/.github/workflows/dotnet-upgrade.yml @@ -2,13 +2,13 @@ name: "DotNet SDK Upgrade" on: schedule: - - cron: '0 0 * * 1' + - cron: "0 0 * * 1" workflow_dispatch: jobs: dotnet-update: runs-on: ubuntu-latest - outputs: + outputs: SHOULD_UPDATE: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE }} BRANCH_EXISTS: ${{ steps.fetch_latest_version.outputs.BRANCH_EXISTS }} DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION: ${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} @@ -37,7 +37,7 @@ jobs: # check if git branch already exists for the upgrade branch_already_exists=0 - + if git ls-remote --heads --exit-code origin refs/heads/feature/dotnetsdk-upgrade/${latest_patch_version}; then branch_already_exists=1 @@ -89,17 +89,17 @@ jobs: if: ${{ needs.dotnet-update.outputs.SHOULD_UPDATE == 1 && needs.dotnet-update.outputs.BRANCH_EXISTS == 0 }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - with: - ref: feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} - - name: Create Pull Request - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr create -B main -H feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} --title "Update dotnet sdk to latest version @${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}" --body " - https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ needs.dotnet-update.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version - - - --- + - uses: actions/checkout@v5 + with: + ref: feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} + - name: Create Pull Request + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr create -B main -H feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} --title "Update dotnet sdk to latest version @${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}" --label "dependency" --body " + https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ needs.dotnet-update.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version - Autogenerated by [DotNet SDK Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/dotnet-upgrade.yml)" + + --- + + Autogenerated by [DotNet SDK Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/dotnet-upgrade.yml)" diff --git a/.github/workflows/node-upgrade.yml b/.github/workflows/node-upgrade.yml new file mode 100644 index 00000000000..9661e0e098d --- /dev/null +++ b/.github/workflows/node-upgrade.yml @@ -0,0 +1,92 @@ +name: Auto Update Node Version + +on: + schedule: + - cron: "0 6 * * 1" # Weekly, every Monday + workflow_dispatch: + +jobs: + update-node: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Get latest Node versions + id: node-versions + run: | + # Get latest versions from the versions manifest + VERSIONS_JSON=$(curl -s https://raw.githubusercontent.com/actions/node-versions/main/versions-manifest.json) + + # Get latest v20 and v24 versions + LATEST_NODE20=$(echo "$VERSIONS_JSON" | jq -r '.[] | select(.version | startswith("20.")) | .version' | head -1) + LATEST_NODE24=$(echo "$VERSIONS_JSON" | jq -r '.[] | select(.version | startswith("24.")) | .version' | head -1) + + echo "latest_node20=$LATEST_NODE20" >> $GITHUB_OUTPUT + echo "latest_node24=$LATEST_NODE24" >> $GITHUB_OUTPUT + + # Check current versions in externals.sh + CURRENT_NODE20=$(grep "NODE20_VERSION=" src/Misc/externals.sh | cut -d'"' -f2) + CURRENT_NODE24=$(grep "NODE24_VERSION=" src/Misc/externals.sh | cut -d'"' -f2) + + echo "current_node20=$CURRENT_NODE20" >> $GITHUB_OUTPUT + echo "current_node24=$CURRENT_NODE24" >> $GITHUB_OUTPUT + + # Determine if updates are needed + NEEDS_UPDATE20="false" + NEEDS_UPDATE24="false" + + if [ "$CURRENT_NODE20" != "$LATEST_NODE20" ]; then + NEEDS_UPDATE20="true" + fi + + if [ "$CURRENT_NODE24" != "$LATEST_NODE24" ]; then + NEEDS_UPDATE24="true" + fi + + echo "needs_update20=$NEEDS_UPDATE20" >> $GITHUB_OUTPUT + echo "needs_update24=$NEEDS_UPDATE24" >> $GITHUB_OUTPUT + + - name: Update externals.sh and create PR + if: steps.node-versions.outputs.needs_update20 == 'true' || steps.node-versions.outputs.needs_update24 == 'true' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Update the files + if [ "${{ steps.node-versions.outputs.needs_update20 }}" == "true" ]; then + sed -i 's/NODE20_VERSION="[^"]*"/NODE20_VERSION="${{ steps.node-versions.outputs.latest_node20 }}"/' src/Misc/externals.sh + fi + + if [ "${{ steps.node-versions.outputs.needs_update24 }}" == "true" ]; then + sed -i 's/NODE24_VERSION="[^"]*"/NODE24_VERSION="${{ steps.node-versions.outputs.latest_node24 }}"/' src/Misc/externals.sh + fi + + # Configure git + git config --global user.name "github-actions[bot]" + git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>" + + # Create branch and commit changes + branch_name="chore/update-node" + git checkout -b "$branch_name" + git commit -a -m "chore: update Node versions (20: ${{ steps.node-versions.outputs.latest_node20 }}, 24: ${{ steps.node-versions.outputs.latest_node24 }})" + git push --force origin "$branch_name" + + # Create PR body using here-doc for proper formatting + cat > pr_body.txt << 'EOF' + Automated Node.js version update: + + - Node 20: ${{ steps.node-versions.outputs.current_node20 }} → ${{ steps.node-versions.outputs.latest_node20 }} + - Node 24: ${{ steps.node-versions.outputs.current_node24 }} → ${{ steps.node-versions.outputs.latest_node24 }} + + This update ensures we're using the latest stable Node.js versions for security and performance improvements. + + **Note**: When updating Node versions, remember to also create a new release of alpine_nodejs at the updated version following the instructions at: https://github.com/actions/alpine_nodejs + + --- + + Autogenerated by [Node Version Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/node-upgrade.yml) + EOF + + # Create PR + gh pr create -B main -H "$branch_name" \ + --title "chore: update Node versions" \ + --label "dependency" \ + --body-file pr_body.txt \ No newline at end of file diff --git a/.github/workflows/npm-audit-ts-fix.yml b/.github/workflows/npm-audit-ts-fix.yml new file mode 100644 index 00000000000..2372a07c6b3 --- /dev/null +++ b/.github/workflows/npm-audit-ts-fix.yml @@ -0,0 +1,132 @@ +name: NPM Audit Fix + +on: + schedule: + - cron: "0 7 * * 1" # Weekly on Monday at 7 AM UTC + workflow_dispatch: + +jobs: + npm-audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: NPM install and audit fix + working-directory: src/Misc/expressionFunc/hashFiles + run: | + npm install + + # Check what vulnerabilities exist + echo "=== Checking current vulnerabilities ===" + npm audit || true + + # Apply audit fix --force to get security updates + echo "=== Applying npm audit fix --force ===" + npm audit fix --force + + # Test if build still works and set status + echo "=== Testing build compatibility ===" + if npm run all; then + echo "✅ Build successful after audit fix" + echo "AUDIT_FIX_STATUS=success" >> $GITHUB_ENV + else + echo "❌ Build failed after audit fix - will create PR with fix instructions" + echo "AUDIT_FIX_STATUS=build_failed" >> $GITHUB_ENV + fi + + - name: Create PR if changes exist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Check if there are any changes + if [ -n "$(git status --porcelain)" ]; then + # Configure git + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # Create branch and commit changes + branch_name="chore/npm-audit-fix-$(date +%Y%m%d)" + git checkout -b "$branch_name" + git add . + git commit -m "chore: npm audit fix for hashFiles dependencies" --no-verify + git push origin "$branch_name" + + # Create PR body based on what actually happened + if [ "$AUDIT_FIX_STATUS" = "success" ]; then + cat > pr_body.txt << 'EOF' + Automated npm audit fix for security vulnerabilities in hashFiles dependencies. + + **✅ Full Fix Applied Successfully** + This update addresses npm security advisories and ensures dependencies are secure and up-to-date. + + **Changes made:** + - Applied `npm audit fix --force` to resolve security vulnerabilities + - Updated package-lock.json with security patches + - Verified build compatibility with `npm run all` + + **Next steps:** + - Review the dependency changes + - Verify the hashFiles functionality still works as expected + - Merge when ready + + --- + + Autogenerated by [NPM Audit Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit.yml) + EOF + elif [ "$AUDIT_FIX_STATUS" = "build_failed" ]; then + cat > pr_body.txt << 'EOF' + Automated npm audit fix for security vulnerabilities in hashFiles dependencies. + + **⚠️ Security Fixes Applied - Build Issues Need Manual Resolution** + This update applies important security patches but causes build failures that require manual fixes. + + **Changes made:** + - Applied `npm audit fix --force` to resolve security vulnerabilities + - Updated package-lock.json with security patches + + **⚠️ Build Issues Detected:** + The build fails after applying security fixes, likely due to TypeScript compatibility issues with updated `@types/node`. + + **Required Manual Fixes:** + 1. Review TypeScript compilation errors in the build output + 2. Update TypeScript configuration if needed + 3. Consider pinning `@types/node` to a compatible version + 4. Run `npm run all` locally to verify fixes + + **Next steps:** + - **DO NOT merge until build issues are resolved** + - Apply manual fixes for TypeScript compatibility + - Test the hashFiles functionality still works as expected + - Merge when build passes + + --- + + Autogenerated by [NPM Audit Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit.yml) + EOF + else + # Fallback case + cat > pr_body.txt << 'EOF' + Automated npm audit attempted for security vulnerabilities in hashFiles dependencies. + + **ℹ️ No Changes Applied** + No security vulnerabilities were found or no changes were needed. + + --- + + Autogenerated by [NPM Audit Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit.yml) + EOF + fi + + # Create PR + gh pr create -B main -H "$branch_name" \ + --title "chore: npm audit fix for hashFiles dependencies" \ + --label "dependency" \ + --body-file pr_body.txt + else + echo "✅ No changes to commit - npm audit fix did not modify any files" + fi diff --git a/.github/workflows/setup-labels.yml b/.github/workflows/setup-labels.yml new file mode 100644 index 00000000000..2d2d7155742 --- /dev/null +++ b/.github/workflows/setup-labels.yml @@ -0,0 +1,32 @@ +name: Setup Repository Labels + +on: + workflow_dispatch: + +jobs: + setup-labels: + runs-on: ubuntu-latest + steps: + - name: Create necessary labels + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Create dependency label + gh label create "dependency" \ + --description "Dependency updates and security fixes" \ + --color "0366d6" \ + --repo ${{ github.repository }} || echo "dependency label already exists" + + # Create typescript label + gh label create "typescript" \ + --description "TypeScript related changes" \ + --color "3178C6" \ + --repo ${{ github.repository }} || echo "typescript label already exists" + + # Create needs-manual-review label + gh label create "needs-manual-review" \ + --description "Requires manual review and intervention" \ + --color "D93F0B" \ + --repo ${{ github.repository }} || echo "needs-manual-review label already exists" + + echo "✅ Labels created successfully" diff --git a/docs/dependency-management.md b/docs/dependency-management.md new file mode 100644 index 00000000000..6e73ac38f54 --- /dev/null +++ b/docs/dependency-management.md @@ -0,0 +1,145 @@ +# Runner Dependency Management Process + +## Overview + +This document outlines the automated dependency management process for the GitHub Actions Runner, designed to ensure we maintain up-to-date and secure dependencies while providing predictable release cycles. + +## Release Schedule + +- **Monthly Runner Releases**: New runner versions are released monthly +- **Weekly Dependency Checks**: Automated workflows check for dependency updates every Monday +- **Security Patches**: Critical security vulnerabilities are addressed immediately outside the regular schedule + +## Automated Workflows + +### 1. Node.js Version Updates +- **Workflow**: `.github/workflows/node-upgrade.yml` +- **Schedule**: Mondays at 6:00 AM UTC +- **Purpose**: Updates Node.js 20 and 24 versions in `src/Misc/externals.sh` +- **Source**: [actions/node-versions](https://github.com/actions/node-versions) + +### 2. NPM Security Audit +- **Workflow**: `.github/workflows/npm-upgrade.yml` +- **Schedule**: Mondays at 7:00 AM UTC +- **Purpose**: Runs `npm audit fix` on hashFiles dependencies +- **Location**: `src/Misc/expressionFunc/hashFiles/` + +### 3. .NET SDK Updates +- **Workflow**: `.github/workflows/dotnet-upgrade.yml` +- **Schedule**: Mondays at 12:00 AM UTC +- **Purpose**: Updates .NET SDK patch versions in `src/global.json` + +### 4. Docker/Buildx Updates +- **Workflow**: `.github/workflows/docker-buildx-upgrade.yml` +- **Schedule**: Mondays at 12:00 AM UTC +- **Purpose**: Updates Docker and Docker Buildx versions in `images/Dockerfile` + +### 5. Dependency Status Check +- **Workflow**: `.github/workflows/dependency-check.yml` +- **Schedule**: Mondays at 8:00 AM UTC +- **Purpose**: Provides comprehensive status report of all dependencies + +## Release Process Integration + +### Pre-Release Checklist + +Before each monthly runner release: + +1. **Check Dependency PRs**: + ```bash + # List open dependency PRs + gh pr list --label "dependency" --state open + ``` + +2. **Run Manual Dependency Check**: + - Go to Actions tab → "Dependency Status Check" → "Run workflow" + - Review the summary for any outdated dependencies + +3. **Review and Merge Updates**: + - Prioritize security-related updates + - Test dependency updates in development environment + - Merge approved dependency PRs + +### Vulnerability Response + +#### Critical Security Vulnerabilities +- **Response Time**: Within 24 hours +- **Process**: + 1. Assess impact on runner security + 2. Create hotfix branch if runner data security is affected + 3. Expedite patch release if necessary + 4. Document in security advisory if applicable + +#### Non-Critical Vulnerabilities +- **Response Time**: Next monthly release +- **Process**: + 1. Evaluate if vulnerability affects runner functionality + 2. Include fix in regular dependency update cycle + 3. Document in release notes + +## Monitoring and Alerts + +### GitHub Actions Workflow Status +- All dependency workflows create PRs with the `dependency` label +- Failed workflows should be investigated immediately +- Weekly dependency status reports are generated automatically + +### Manual Checks +You can manually trigger dependency checks: +- **Full Status**: Run "Dependency Status Check" workflow +- **Specific Component**: Use the dropdown to check individual dependencies + +## Dependency Labels + +All automated dependency PRs are tagged with the `dependency` label for easy filtering: +- Node.js updates: `chore/update-node` branch +- NPM security fixes: `chore/npm-audit-fix` branch +- .NET updates: `feature/dotnetsdk-upgrade/*` branch +- Docker updates: Branch named with versions + +## Special Considerations + +### Node.js Updates +When updating Node.js versions, remember to: +1. Create a corresponding release in [actions/alpine_nodejs](https://github.com/actions/alpine_nodejs) +2. Follow the alpine_nodejs getting started guide +3. Test container builds with new Node versions + +### .NET SDK Updates +- Only patch versions are auto-updated within the same major.minor version +- Major/minor version updates require manual review and testing + +### Docker Updates +- Updates include both Docker Engine and Docker Buildx +- Verify compatibility with runner container workflows + +## Troubleshooting + +### Common Issues + +1. **NPM Audit Workflow Fails**: + - Check if `package.json` exists in `src/Misc/expressionFunc/hashFiles/` + - Verify Node.js setup step succeeded + +2. **Version Detection Fails**: + - Check if upstream APIs are available + - Verify parsing logic for version extraction + +3. **PR Creation Fails**: + - Ensure `GITHUB_TOKEN` has sufficient permissions + - Check if branch already exists + +### Contact + +For questions about the dependency management process: +- Create an issue with the `dependencies` label +- Review existing dependency management workflows +- Consult the runner team for security-related concerns + +## Metrics and KPIs + +Track these metrics to measure dependency management effectiveness: +- Number of open dependency PRs at release time +- Time to merge dependency updates +- Number of security vulnerabilities by severity +- Release cycle adherence (monthly target)