-
Notifications
You must be signed in to change notification settings - Fork 1
[WIP] Expand dependency management and automate updates #49
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,233 @@ | ||||||||||||||||||||||||||||||||||||||
| name: Auto-Update Dependencies | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # This workflow automatically creates Pull Requests to update dependencies | ||||||||||||||||||||||||||||||||||||||
| # when dependency update issues are created or updated | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| 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: Parse issue and create PR | ||||||||||||||||||||||||||||||||||||||
| uses: actions/github-script@v8 | ||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||
| script: | | ||||||||||||||||||||||||||||||||||||||
| 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}`); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Extract version information from issue body | ||||||||||||||||||||||||||||||||||||||
| const body = issue.data.body; | ||||||||||||||||||||||||||||||||||||||
| const labels = issue.data.labels.map(l => l.name); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Determine which type of dependency update this is | ||||||||||||||||||||||||||||||||||||||
| let updateType = ''; | ||||||||||||||||||||||||||||||||||||||
| let branchName = ''; | ||||||||||||||||||||||||||||||||||||||
| let files = []; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (labels.includes('nginx')) { | ||||||||||||||||||||||||||||||||||||||
| updateType = 'NGINX'; | ||||||||||||||||||||||||||||||||||||||
| branchName = `update-nginx-deps-${Date.now()}`; | ||||||||||||||||||||||||||||||||||||||
| files = ['nginx/nginx_installer.sh', 'nginx/nginx_installer.ps1']; | ||||||||||||||||||||||||||||||||||||||
| } else if (labels.includes('ansible')) { | ||||||||||||||||||||||||||||||||||||||
| updateType = 'Ansible'; | ||||||||||||||||||||||||||||||||||||||
| branchName = `update-ansible-deps-${Date.now()}`; | ||||||||||||||||||||||||||||||||||||||
| files = ['ansible/ansible_installer.sh']; | ||||||||||||||||||||||||||||||||||||||
| } else if (labels.includes('kubernetes')) { | ||||||||||||||||||||||||||||||||||||||
| updateType = 'Kubernetes'; | ||||||||||||||||||||||||||||||||||||||
| branchName = `update-kubernetes-deps-${Date.now()}`; | ||||||||||||||||||||||||||||||||||||||
| files = ['kubernetes/kubernetes_installer.sh']; | ||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||
| console.log('Unknown dependency type, skipping PR creation'); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| console.log(`Update type: ${updateType}`); | ||||||||||||||||||||||||||||||||||||||
| console.log(`Branch name: ${branchName}`); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Check if a PR already exists for this issue | ||||||||||||||||||||||||||||||||||||||
| const existingPRs = await github.rest.pulls.list({ | ||||||||||||||||||||||||||||||||||||||
| owner: context.repo.owner, | ||||||||||||||||||||||||||||||||||||||
| repo: context.repo.repo, | ||||||||||||||||||||||||||||||||||||||
| state: 'open', | ||||||||||||||||||||||||||||||||||||||
| head: `${context.repo.owner}:${branchName.split('-').slice(0, -1).join('-')}` | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+80
to
+87
|
||||||||||||||||||||||||||||||||||||||
| // Check if a PR already exists for this issue | |
| const existingPRs = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| head: `${context.repo.owner}:${branchName.split('-').slice(0, -1).join('-')}` | |
| }); |
Copilot
AI
Mar 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The linked-PR detection uses pulls.list without pagination (per_page defaults to 30). In repos with >30 open PRs, this can miss an existing PR that references the issue and create duplicates. Prefer the Search API (querying for repo:... type:pr state:open "#<issueNumber>") or paginate through results.
| // 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}`) | |
| ); | |
| // Search for any open PR that references this issue using the Search API | |
| const searchResults = await github.rest.search.issuesAndPullRequests({ | |
| q: `repo:${context.repo.owner}/${context.repo.repo} type:pr state:open "#${issueNumber}" in:body` | |
| }); | |
| const linkedPRItem = searchResults.data.items.find(item => item.pull_request); | |
| const linkedPR = linkedPRItem; |
Copilot
AI
Mar 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because this workflow runs on both issues.opened and issues.edited, this block will post a new comment every time the issue is edited after a PR exists, which can spam the issue. Consider only commenting on opened, or check for an existing bot comment and update it instead of creating a new one.
| // Add comment to 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}` | |
| }); | |
| // Only add a new comment on issue creation or non-issues events to avoid spam on edits | |
| if (context.eventName !== 'issues' || context.payload.action === 'opened') { | |
| 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}` | |
| }); | |
| } else { | |
| console.log('Skipping duplicate issue comment for edited issue event.'); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line can render invalid JavaScript for non-
workflow_dispatchevents. Onissuesevents,${{ github.event.inputs.issue_number }}expands to an empty value, producingconst issueNumber = ... || ;which is a syntax error and will fail the workflow. Pass the dispatch input viaenvand readprocess.env, or usecontext.payload.inputswhenevent_nameisworkflow_dispatch.