[Github Action] Update CHANGELOG.md #6625
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Close Matching Issue on PR Merge | |
| on: | |
| pull_request: | |
| types: | |
| - closed | |
| jobs: | |
| close_issue: | |
| if: github.event.pull_request.merged == true && github.repository == 'community-scripts/ProxmoxVE' | |
| runs-on: self-hosted | |
| steps: | |
| - name: Checkout target repo (merge commit) | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: community-scripts/ProxmoxVE | |
| ref: ${{ github.event.pull_request.merge_commit_sha }} | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract and Process PR Title | |
| id: extract_title | |
| run: | | |
| title=$(echo "${{ github.event.pull_request.title }}" | sed 's/^New Script://g' | tr '[:upper:]' '[:lower:]' | sed 's/ //g' | sed 's/-//g') | |
| echo "Processed Title: $title" | |
| echo "title=$title" >> $GITHUB_ENV | |
| - name: Get slugs from merged PR | |
| id: get_slugs | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| pr_files=$(gh pr view ${{ github.event.pull_request.number }} --repo community-scripts/ProxmoxVE --json files -q '.files[].path' 2>/dev/null || true) | |
| slugs="" | |
| for path in $pr_files; do | |
| [[ -f "$path" ]] || continue | |
| if [[ "$path" == frontend/public/json/*.json ]]; then | |
| s=$(jq -r '.slug // empty' "$path" 2>/dev/null) | |
| [[ -n "$s" ]] && slugs="$slugs $s" | |
| elif [[ "$path" == ct/*.sh ]] || [[ "$path" == install/*.sh ]] || [[ "$path" == tools/*.sh ]] || [[ "$path" == turnkey/*.sh ]] || [[ "$path" == vm/*.sh ]]; then | |
| base=$(basename "$path" .sh) | |
| if [[ "$path" == install/* && "$base" == *-install ]]; then | |
| s="${base%-install}" | |
| else | |
| s="$base" | |
| fi | |
| [[ -n "$s" ]] && slugs="$slugs $s" | |
| fi | |
| done | |
| slugs=$(echo $slugs | xargs -n1 | sort -u | tr '\n' ' ') | |
| if [[ -z "$slugs" && -n "$title" ]]; then | |
| slugs="$title" | |
| fi | |
| if [[ -z "$slugs" ]]; then | |
| echo "count=0" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "$slugs" > pocketbase_slugs.txt | |
| echo "count=$(echo $slugs | wc -w)" >> "$GITHUB_OUTPUT" | |
| - name: Search for Issues with Similar Titles | |
| id: find_issue | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| issues=$(gh issue list --repo community-scripts/ProxmoxVED --json number,title --jq '.[] | {number, title}') | |
| best_match_score=0 | |
| best_match_number=0 | |
| for issue in $(echo "$issues" | jq -r '. | @base64'); do | |
| _jq() { | |
| echo ${issue} | base64 --decode | jq -r ${1} | |
| } | |
| issue_title=$(_jq '.title' | tr '[:upper:]' '[:lower:]' | sed 's/ //g' | sed 's/-//g') | |
| issue_number=$(_jq '.number') | |
| match_score=$(echo "$title" | grep -o "$issue_title" | wc -l) | |
| if [ "$match_score" -gt "$best_match_score" ]; then | |
| best_match_score=$match_score | |
| best_match_number=$issue_number | |
| fi | |
| done | |
| if [ "$best_match_number" != "0" ]; then | |
| echo "issue_number=$best_match_number" >> $GITHUB_ENV | |
| else | |
| echo "No matching issue found." | |
| exit 0 | |
| fi | |
| - name: Comment on the Best-Matching Issue and Close It | |
| if: env.issue_number != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.PAT_MICHEL }} | |
| run: | | |
| gh issue comment $issue_number --repo community-scripts/ProxmoxVED --body "Merged with #${{ github.event.pull_request.number }} in ProxmoxVE" | |
| gh issue close $issue_number --repo community-scripts/ProxmoxVED | |
| - name: Set is_dev to false in PocketBase | |
| if: steps.get_slugs.outputs.count != '0' | |
| env: | |
| POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }} | |
| POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }} | |
| POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }} | |
| POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }} | |
| PR_URL: ${{ github.server_url }}/${{ github.repository }}/pull/${{ github.event.pull_request.number }} | |
| run: | | |
| node << 'ENDSCRIPT' | |
| (async function() { | |
| const fs = require('fs'); | |
| const https = require('https'); | |
| const http = require('http'); | |
| const url = require('url'); | |
| function request(fullUrl, opts) { | |
| return new Promise(function(resolve, reject) { | |
| const u = url.parse(fullUrl); | |
| const isHttps = u.protocol === 'https:'; | |
| const body = opts.body; | |
| const options = { | |
| hostname: u.hostname, | |
| port: u.port || (isHttps ? 443 : 80), | |
| path: u.path, | |
| method: opts.method || 'GET', | |
| headers: opts.headers || {} | |
| }; | |
| if (body) options.headers['Content-Length'] = Buffer.byteLength(body); | |
| const lib = isHttps ? https : http; | |
| const req = lib.request(options, function(res) { | |
| let data = ''; | |
| res.on('data', function(chunk) { data += chunk; }); | |
| res.on('end', function() { | |
| resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data }); | |
| }); | |
| }); | |
| req.on('error', reject); | |
| if (body) req.write(body); | |
| req.end(); | |
| }); | |
| } | |
| const raw = process.env.POCKETBASE_URL.replace(/\/$/, ''); | |
| const apiBase = /\/api$/i.test(raw) ? raw : raw + '/api'; | |
| const coll = process.env.POCKETBASE_COLLECTION; | |
| const slugsText = fs.readFileSync('pocketbase_slugs.txt', 'utf8').trim(); | |
| const slugs = slugsText ? slugsText.split(/\s+/).filter(Boolean) : []; | |
| if (slugs.length === 0) { | |
| console.log('No slugs to update.'); | |
| return; | |
| } | |
| const authUrl = apiBase + '/collections/users/auth-with-password'; | |
| const authBody = JSON.stringify({ | |
| identity: process.env.POCKETBASE_ADMIN_EMAIL, | |
| password: process.env.POCKETBASE_ADMIN_PASSWORD | |
| }); | |
| const authRes = await request(authUrl, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: authBody | |
| }); | |
| if (!authRes.ok) { | |
| throw new Error('Auth failed: ' + authRes.body); | |
| } | |
| const token = JSON.parse(authRes.body).token; | |
| const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records'; | |
| const prUrl = process.env.PR_URL || ''; | |
| for (const slug of slugs) { | |
| const filter = "(slug='" + slug.replace(/'/g, "''") + "')"; | |
| const listRes = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', { | |
| headers: { 'Authorization': token } | |
| }); | |
| const list = JSON.parse(listRes.body); | |
| const record = list.items && list.items[0]; | |
| if (!record) { | |
| console.log('Slug not in DB, skipping: ' + slug); | |
| continue; | |
| } | |
| const patchRes = await request(recordsUrl + '/' + record.id, { | |
| method: 'PATCH', | |
| headers: { 'Authorization': token, 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| name: record.name || record.slug, | |
| last_update_commit: prUrl, | |
| is_dev: false | |
| }) | |
| }); | |
| if (!patchRes.ok) { | |
| console.warn('PATCH failed for slug ' + slug + ': ' + patchRes.body); | |
| continue; | |
| } | |
| console.log('Set is_dev=false for slug: ' + slug); | |
| } | |
| console.log('Done.'); | |
| })().catch(e => { console.error(e); process.exit(1); }); | |
| ENDSCRIPT | |
| shell: bash |