Skip to content

fix: correct typo in PCRE2 version check (CURRENT_OUTPUT → CURRENT_VE… #5

fix: correct typo in PCRE2 version check (CURRENT_OUTPUT → CURRENT_VE…

fix: correct typo in PCRE2 version check (CURRENT_OUTPUT → CURRENT_VE… #5

name: Auto-Update Dependencies
# This workflow automatically creates Pull Requests with actual code changes
# to update dependencies when dependency update issues are created
on:
issues:
types: [opened, edited]
workflow_dispatch:
inputs:
issue_number:
description: 'Issue number to process'
required: true
type: number
permissions:
contents: write
issues: write
pull-requests: write
jobs:
auto-update:
name: Auto-Update Dependencies
runs-on: ubuntu-latest
# Only run for dependency update issues
if: |
(github.event_name == 'workflow_dispatch') ||
(contains(github.event.issue.labels.*.name, 'dependencies') &&
contains(github.event.issue.title, 'Update Available'))
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Parse issue and update dependencies
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
const { execSync } = require('child_process');
const issueNumber = context.payload.issue?.number || ${{ github.event.inputs.issue_number }};
// Get the issue details
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber
});
console.log(`Processing issue #${issueNumber}: ${issue.data.title}`);
const body = issue.data.body;
const labels = issue.data.labels.map(l => l.name);
// Search for any PR that references this issue
const allPRs = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open'
});
const linkedPR = allPRs.data.find(pr =>
pr.body && pr.body.includes(`#${issueNumber}`)
);
if (linkedPR) {
console.log(`PR #${linkedPR.number} already exists for this issue`);
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: `A pull request already exists to address this update: #${linkedPR.number}`
});
return;
}
// Extract version information from issue body
const versionRegex = /\*\*([^:]+)\*\*:\s+([^\s]+)\s+→\s+([^\s]+)/g;
const updates = {};
let match;
while ((match = versionRegex.exec(body)) !== null) {
const [, component, currentVersion, latestVersion] = match;
updates[component.trim()] = {
current: currentVersion.trim(),
latest: latestVersion.trim()
};
}
console.log('Extracted updates:', JSON.stringify(updates, null, 2));
// Determine update type and files to modify
let updateType = '';
let branchName = '';
let files = [];
let updatesMade = false;
if (labels.includes('ansible')) {
updateType = 'Ansible';
branchName = `automated-update/ansible-${Date.now()}`;
// Update Ansible installer
const ansibleFile = 'ansible/ansible_installer.sh';
let content = fs.readFileSync(ansibleFile, 'utf8');
let modified = false;
if (updates['Python']) {
const pythonRegex = /BUILD_PYTHON_VERSION:-([0-9.]+)/;
content = content.replace(pythonRegex, `BUILD_PYTHON_VERSION:-${updates['Python'].latest}`);
modified = true;
console.log(`Updated Python version to ${updates['Python'].latest}`);
}
if (updates['Ansible']) {
const ansibleRegex = /pip install ansible==([0-9.]+)/;
content = content.replace(ansibleRegex, `pip install ansible==${updates['Ansible'].latest}`);
modified = true;
console.log(`Updated Ansible version to ${updates['Ansible'].latest}`);
}
if (modified) {
fs.writeFileSync(ansibleFile, content);
files.push(ansibleFile);
updatesMade = true;
}
} else if (labels.includes('nginx')) {
updateType = 'NGINX';
branchName = `automated-update/nginx-${Date.now()}`;
// Update NGINX installer (Bash)
const nginxShFile = 'nginx/nginx_installer.sh';
let shContent = fs.readFileSync(nginxShFile, 'utf8');
let shModified = false;
// Update NGINX installer (PowerShell)
const nginxPs1File = 'nginx/nginx_installer.ps1';
let ps1Content = fs.readFileSync(nginxPs1File, 'utf8');
let ps1Modified = false;
if (updates['NGINX']) {
shContent = shContent.replace(/NGINX_VERSION="([0-9.]+)"/, `NGINX_VERSION="${updates['NGINX'].latest}"`);
ps1Content = ps1Content.replace(/\$NGINX_VERSION = "([0-9.]+)"/, `$NGINX_VERSION = "${updates['NGINX'].latest}"`);
shModified = ps1Modified = true;
console.log(`Updated NGINX version to ${updates['NGINX'].latest}`);
}
if (updates['OpenSSL']) {
shContent = shContent.replace(/OPENSSL_VERSION="([0-9.]+)"/, `OPENSSL_VERSION="${updates['OpenSSL'].latest}"`);
ps1Content = ps1Content.replace(/\$OPENSSL_VERSION = "([0-9.]+)"/, `$OPENSSL_VERSION = "${updates['OpenSSL'].latest}"`);
shModified = ps1Modified = true;
console.log(`Updated OpenSSL version to ${updates['OpenSSL'].latest}`);
}
if (updates['PCRE2']) {
shContent = shContent.replace(/PCRE2_VERSION="([0-9.]+)"/, `PCRE2_VERSION="${updates['PCRE2'].latest}"`);
ps1Content = ps1Content.replace(/\$PCRE2_VERSION = "([0-9.]+)"/, `$PCRE2_VERSION = "${updates['PCRE2'].latest}"`);
shModified = ps1Modified = true;
console.log(`Updated PCRE2 version to ${updates['PCRE2'].latest}`);
}
if (updates['Zlib']) {
shContent = shContent.replace(/ZLIB_VERSION="([0-9.]+)"/, `ZLIB_VERSION="${updates['Zlib'].latest}"`);
ps1Content = ps1Content.replace(/\$ZLIB_VERSION = "([0-9.]+)"/, `$ZLIB_VERSION = "${updates['Zlib'].latest}"`);
shModified = ps1Modified = true;
console.log(`Updated Zlib version to ${updates['Zlib'].latest}`);
}
if (shModified) {
fs.writeFileSync(nginxShFile, shContent);
files.push(nginxShFile);
updatesMade = true;
}
if (ps1Modified) {
fs.writeFileSync(nginxPs1File, ps1Content);
files.push(nginxPs1File);
updatesMade = true;
}
} else if (labels.includes('kubernetes')) {
updateType = 'Kubernetes';
branchName = `automated-update/kubernetes-${Date.now()}`;
const k8sFile = 'kubernetes/kubernetes_installer.sh';
let content = fs.readFileSync(k8sFile, 'utf8');
let modified = false;
if (updates['Kubernetes']) {
content = content.replace(/K8S_VERSION:-([v0-9.]+)/, `K8S_VERSION:-${updates['Kubernetes'].latest}`);
modified = true;
console.log(`Updated Kubernetes version to ${updates['Kubernetes'].latest}`);
}
if (modified) {
fs.writeFileSync(k8sFile, content);
files.push(k8sFile);
updatesMade = true;
}
} else {
console.log('Unknown dependency type, skipping PR creation');
return;
}
if (!updatesMade) {
console.log('No updates were made to files');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: `⚠️ Unable to automatically update files. Manual intervention required.\n\nPlease review the issue details and update the files manually.`
});
return;
}
// Create a new branch
const mainBranch = await github.rest.repos.getBranch({
owner: context.repo.owner,
repo: context.repo.repo,
branch: context.payload.repository.default_branch
});
try {
execSync(`git checkout -b ${branchName}`, { stdio: 'inherit' });
console.log(`Created branch ${branchName}`);
} catch (error) {
console.error('Failed to create branch:', error.message);
throw error;
}
// Commit changes
try {
execSync(`git add ${files.join(' ')}`, { stdio: 'inherit' });
const commitMessage = `chore: update ${updateType} dependencies
${Object.entries(updates).map(([comp, vers]) => `- ${comp}: ${vers.current} → ${vers.latest}`).join('\n')}
Automated update from issue #${issueNumber}`;

Check failure on line 247 in .github/workflows/auto-update-dependencies.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/auto-update-dependencies.yml

Invalid workflow file

You have an error in your yaml syntax on line 247
execSync(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
console.log('Committed changes');
} catch (error) {
console.error('Failed to commit:', error.message);
throw error;
}
// Push the branch
try {
execSync(`git push -u origin ${branchName}`, { stdio: 'inherit' });
console.log('Pushed branch');
} catch (error) {
console.error('Failed to push:', error.message);
throw error;
}
// Create PR body
const prBody = `## Automated Dependency Update
This PR automatically updates ${updateType} dependencies as identified in issue #${issueNumber}.
### Changes Made
${Object.entries(updates).map(([component, versions]) =>
`- **${component}**: ${versions.current} → ${versions.latest}`
).join('\n')}
### Files Updated
${files.map(f => `- \`${f}\``).join('\n')}
### ⚠️ Important Notes
${updateType === 'NGINX' ? `
**NGINX requires SHA256 checksum updates:**
After reviewing this PR, you'll need to:
1. Download the new NGINX tarball and calculate its SHA256:
\`\`\`bash
wget https://nginx.org/download/nginx-${updates['NGINX']?.latest}.tar.gz
sha256sum nginx-${updates['NGINX']?.latest}.tar.gz
\`\`\`
2. Update the SHA256 checksums in both installer files
3. Test the installation on a clean system
**The PR cannot be merged until SHA256 checksums are updated.**
` : ''}
### Testing Checklist
- [ ] Version numbers updated correctly
${updateType === 'NGINX' ? '- [ ] SHA256 checksums updated and verified' : ''}
- [ ] Installation tested on clean system
- [ ] All functionality verified
### Verification
Test the installation:
\`\`\`bash
${files[0].includes('ansible') ? './ansible/ansible_installer.sh' :
files[0].includes('nginx') ? './nginx/nginx_installer.sh' :
files[0].includes('kubernetes') ? './kubernetes/kubernetes_installer.sh' : './installer.sh'}
\`\`\`
---
*🤖 This PR was automatically created by the dependency management workflow.*
*Related issue: #${issueNumber}*
Closes #${issueNumber}
`;
// Create the pull request
try {
const pr = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `🔄 Update ${updateType} Dependencies`,
head: branchName,
base: context.payload.repository.default_branch,
body: prBody,
draft: updateType === 'NGINX' // Mark as draft if NGINX (needs SHA256 updates)
});
console.log(`Created PR #${pr.data.number}`);
// Add labels to PR
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.data.number,
labels: ['dependencies', 'automated', ...labels.filter(l => !['enhancement', 'dependencies'].includes(l))]
});
// Add comment to original issue with PR link
const commentBody = updateType === 'NGINX'
? `🤖 **Automated PR Created**
A pull request has been created with automated dependency updates: #${pr.data.number}
⚠️ **Action Required:** The PR is marked as draft because NGINX updates require SHA256 checksum verification. Please:
1. Review the version updates
2. Download and verify SHA256 checksums
3. Update the checksums in the installer files
4. Mark the PR as ready for review`
: `🤖 **Automated PR Created**
A pull request has been created with automated dependency updates: #${pr.data.number}
The changes have been automatically applied. Please review and test before merging.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: commentBody
});
console.log(`Successfully created PR and linked to issue #${issueNumber}`);
} catch (error) {
console.error('Error creating PR:', error);
// Comment on issue about the error
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: `⚠️ **Automated PR Creation Failed**
There was an error creating the automated pull request. Error: ${error.message}
The branch \`${branchName}\` may have been created with updates. Please check and create a pull request manually if needed.`
});
throw error;
}