diff --git a/.github/workflows/update-issue-tracker.yml b/.github/workflows/update-issue-tracker.yml index 0c6c972..70d3daa 100644 --- a/.github/workflows/update-issue-tracker.yml +++ b/.github/workflows/update-issue-tracker.yml @@ -1,90 +1,62 @@ -name: Daily Open and Closed Issues Check +name: Update Github Issues -# This workflow is triggered every 24 hours on: workflow_dispatch: + inputs: + branch: + description: 'Branch to update' + required: true + default: 'main' + schedule: - - cron: "0 0 * * *" # Runs daily at midnight UTC + - cron: '0 0 * * *' jobs: - fetch_issues: - runs-on: ubuntu-latest + Update-Github-Issues: + runs-on: ubuntu-latest + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - name: Checkout the repository - uses: actions/checkout@v3 - - - name: Fetch open issues from the repository - id: fetch_open_issues + - name: Show Inputs run: | - # Fetch open issues using GitHub API - curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - "https://api.github.com/repos/nexus-mods/vortex/issues?state=open" > open_issues.json - - # Show fetched open issues - cat open_issues.json + echo "Selected branch: ${{ github.event.inputs.branch }}" - - name: Fetch closed issues from the repository (last 30 days) - id: fetch_closed_issues - run: | - # Calculate the date 30 days ago - last_month=$(date -d "-30 days" +%Y-%m-%d) + - uses: actions/checkout@v4 + with: + submodules: "recursive" + ref: ${{ github.event.inputs.branch }} # Checkout the specified branch - # Fetch closed issues using GitHub API with the 'since' parameter to get those closed in the last month - curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - "https://api.github.com/repos/nexus-mods/vortex/issues?state=closed&since=$last_month" > closed_issues.json - - # Show fetched closed issues - cat closed_issues.json - - - name: Process issues, extract hashes, and log the report + - name: Validate branch exists run: | - echo "Processing open and closed issues (excluding issues by vortexfeedback):" - echo "# Open and Closed Issues on "nexus-mods/vortex" (Updated on $(date))" > issues_report.md - - process_issues() { - issues_file=$1 - - for row in $(jq -c '.[]' $issues_file); do - author=$(echo $row | jq -r '.user.login') - - # Ignore issues by vortexfeedback - if [ "$author" = "VortexFeedback" ]; then - echo "Skipping issue by vortexfeedback" - continue - fi - - issue_number=$(echo $row | jq '.number') - issue_title=$(echo $row | jq '.title' | sed 's/\"//g') - issue_url=$(echo $row | jq '.html_url' | sed 's/\"//g') - issue_body=$(echo $row | jq '.body' | sed 's/\"//g') - issue_state=$(echo $row | jq '.state' | sed 's/\"//g') - issue_labels=$(echo $row | jq -r '.labels[].name' | tr '\n' ',' | sed 's/,$//') - - # Extract the hash value from the issue body if present - issue_hash=$(echo "$issue_body" | grep -oP '(?<=hash: ).*' || echo "No hash found") - - echo "- [Issue #$issue_number: $issue_title]($issue_url)" >> issues_report.md - echo " - State: $issue_state" >> issues_report.md - echo " - Labels: $issue_labels" >> issues_report.md - echo " - Hash: $issue_hash" >> issues_report.md - echo "---" >> issues_report.md - done - } - - # Process both open and closed issues - process_issues open_issues.json - process_issues closed_issues.json - - - name: Commit the results + git fetch --all + if ! git rev-parse --verify "origin/${{ github.event.inputs.branch }}" > /dev/null 2>&1; then + echo "Branch '${{ github.event.inputs.branch }}' does not exist." + exit 1 + fi + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: '18.x' + cache: "yarn" + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Run + run: yarn update-github-issues + + - name: Git commit and push + env: + CI_COMMIT_AUTHOR: Vortex Backend + CI_COMMIT_EMAIL: insomnious@users.noreply.github.com + CI_COMMIT_MESSAGE: Update Github Issues run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git add issues_report.md - git commit -m "Update open and closed issues report with hashes [$(date)]" - git push - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Clean up - run: rm open_issues.json closed_issues.json + git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}" + git config --global user.email "${{ env.CI_COMMIT_EMAIL }}" + git pull origin ${{ github.event.inputs.branch }} # Pull the latest changes from the branch + git add . # Add changes before committing + git commit -m "${{ env.CI_COMMIT_MESSAGE }}" + git push origin ${{ github.event.inputs.branch }} # Push changes to the specified branch diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..32f70e6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}\\src\\github-update-issues.ts", + "outFiles": [ + "${workspaceFolder}/**/*.js" + ] + } + ] +} \ No newline at end of file diff --git a/out/issues_report.json b/out/issues_report.json new file mode 100644 index 0000000..9f7738c --- /dev/null +++ b/out/issues_report.json @@ -0,0 +1,314 @@ +[ + { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16637", + "repository_url": "https://api.github.com/repos/Nexus-Mods/Vortex", + "labels_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16637/labels{/name}", + "comments_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16637/comments", + "events_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16637/events", + "html_url": "https://github.com/Nexus-Mods/Vortex/issues/16637", + "id": 2638852884, + "node_id": "I_kwDOBAT0m86dSbMU", + "number": 16637, + "title": "error: not implemented", + "user": { + "login": "IDCs", + "id": 8960252, + "node_id": "MDQ6VXNlcjg5NjAyNTI=", + "avatar_url": "https://avatars.githubusercontent.com/u/8960252?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IDCs", + "html_url": "https://github.com/IDCs", + "followers_url": "https://api.github.com/users/IDCs/followers", + "following_url": "https://api.github.com/users/IDCs/following{/other_user}", + "gists_url": "https://api.github.com/users/IDCs/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IDCs/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IDCs/subscriptions", + "organizations_url": "https://api.github.com/users/IDCs/orgs", + "repos_url": "https://api.github.com/users/IDCs/repos", + "events_url": "https://api.github.com/users/IDCs/events{/privacy}", + "received_events_url": "https://api.github.com/users/IDCs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2024-11-06T18:08:21Z", + "updated_at": "2024-11-06T18:08:21Z", + "closed_at": null, + "author_association": "CONTRIBUTOR", + "active_lock_reason": null, + "body": "### Application error\r\n#### System\r\n| | |\r\n|------------ | -------------|\r\n|Platform | win32 10.0.22631 |\r\n|Architecture | x64 |\r\n|Application Version | 0.0.1 |\r\n|Process | renderer |\r\n#### Message\r\nnot implemented\r\n#### Title\r\n```\r\nFailed to purge mods\r\n```\r\n\r\n#### Context\r\n```\r\nextension-api = [object Object],gamemode = Vampire the Masquerade\tBloodlines,extension_version = 1.0.2\r\n```\r\n#### Stack\r\n```\r\nnot implemented\r\nError: not implemented\r\n at loadAllManifests (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:64:25)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:208:19\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromiseCtx (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:641:10)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:97:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\nPrior Context:\r\n at C:\\Projects\\vortex\\src\\util\\util.ts:183:22\r\n at withActivationLock (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\activationStore.ts:303:10)\r\n at purgeModsImpl (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:196:28)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:110:16\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:729:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n\r\nReported from:\r\nError: \r\n at showError (C:\\Projects\\vortex\\src\\util\\message.ts:255:21)\r\n at onShowError (C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:156:16)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:97:11\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:725:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n```\r\n\r\n## Steps To Reproduce:\r\n\r\n•a fdafsdf \r\n•asdf \r\n•asdf \r\n•asdf asdf \r\n•asdf as\r\n•fd as\r\n\r\n\r\n\r\nHash: 50aa8eba2a968d7edc6c38ddbe6e20c9", + "closed_by": null, + "reactions": { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16637/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16637/timeline", + "performed_via_github_app": null, + "state_reason": null, + "hash": "50aa8eba2a968d7edc6c38ddbe6e20c9" + }, + { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16636", + "repository_url": "https://api.github.com/repos/Nexus-Mods/Vortex", + "labels_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16636/labels{/name}", + "comments_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16636/comments", + "events_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16636/events", + "html_url": "https://github.com/Nexus-Mods/Vortex/issues/16636", + "id": 2638445755, + "node_id": "I_kwDOBAT0m86dQ3y7", + "number": 16636, + "title": "error: not implemented", + "user": { + "login": "IDCs", + "id": 8960252, + "node_id": "MDQ6VXNlcjg5NjAyNTI=", + "avatar_url": "https://avatars.githubusercontent.com/u/8960252?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IDCs", + "html_url": "https://github.com/IDCs", + "followers_url": "https://api.github.com/users/IDCs/followers", + "following_url": "https://api.github.com/users/IDCs/following{/other_user}", + "gists_url": "https://api.github.com/users/IDCs/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IDCs/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IDCs/subscriptions", + "organizations_url": "https://api.github.com/users/IDCs/orgs", + "repos_url": "https://api.github.com/users/IDCs/repos", + "events_url": "https://api.github.com/users/IDCs/events{/privacy}", + "received_events_url": "https://api.github.com/users/IDCs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2024-11-06T15:33:17Z", + "updated_at": "2024-11-06T17:02:36Z", + "closed_at": "2024-11-06T17:02:36Z", + "author_association": "CONTRIBUTOR", + "active_lock_reason": null, + "body": "### Application error\r\n#### System\r\n| | |\r\n|------------ | -------------|\r\n|Platform | win32 10.0.22631 |\r\n|Architecture | x64 |\r\n|Application Version | 0.0.1 |\r\n|Process | renderer |\r\n#### Message\r\nnot implemented\r\n#### Title\r\n```\r\nFailed to purge mods\r\n```\r\n\r\n#### Context\r\n```\r\nextension-api = [object Object],gamemode = Vampire the Masquerade\tBloodlines,extension_version = 1.0.2\r\n```\r\n#### Stack\r\n```\r\nnot implemented\r\nError: not implemented\r\n at loadAllManifests (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:64:25)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:208:19\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromiseCtx (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:641:10)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:97:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\nPrior Context:\r\n at C:\\Projects\\vortex\\src\\util\\util.ts:183:22\r\n at withActivationLock (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\activationStore.ts:303:10)\r\n at purgeModsImpl (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:196:28)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:110:16\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:729:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n\r\nReported from:\r\nError: \r\n at showError (C:\\Projects\\vortex\\src\\util\\message.ts:255:21)\r\n at onShowError (C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:156:16)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:97:11\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:725:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n```\r\n\r\n## Steps To Reproduce:\r\n\r\n•sfafsdf\r\n•sg\r\n•dg\r\n•sdfg\r\n•sdfgsdfgsdfgsdfgsd•sfafsdf\r\n•sg\r\n•dg\r\n•sdfg\r\n•sdfgsdfgsdfgsdfgsd\r\n\r\n\r\n\r\nHash: 716b3d7b56c0c2582997f4b95de46708", + "closed_by": { + "login": "IDCs", + "id": 8960252, + "node_id": "MDQ6VXNlcjg5NjAyNTI=", + "avatar_url": "https://avatars.githubusercontent.com/u/8960252?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IDCs", + "html_url": "https://github.com/IDCs", + "followers_url": "https://api.github.com/users/IDCs/followers", + "following_url": "https://api.github.com/users/IDCs/following{/other_user}", + "gists_url": "https://api.github.com/users/IDCs/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IDCs/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IDCs/subscriptions", + "organizations_url": "https://api.github.com/users/IDCs/orgs", + "repos_url": "https://api.github.com/users/IDCs/repos", + "events_url": "https://api.github.com/users/IDCs/events{/privacy}", + "received_events_url": "https://api.github.com/users/IDCs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "reactions": { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16636/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16636/timeline", + "performed_via_github_app": null, + "state_reason": "completed", + "hash": "716b3d7b56c0c2582997f4b95de46708" + }, + { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16634", + "repository_url": "https://api.github.com/repos/Nexus-Mods/Vortex", + "labels_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16634/labels{/name}", + "comments_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16634/comments", + "events_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16634/events", + "html_url": "https://github.com/Nexus-Mods/Vortex/issues/16634", + "id": 2637803290, + "node_id": "I_kwDOBAT0m86dOa8a", + "number": 16634, + "title": "error: not implemented", + "user": { + "login": "IDCs", + "id": 8960252, + "node_id": "MDQ6VXNlcjg5NjAyNTI=", + "avatar_url": "https://avatars.githubusercontent.com/u/8960252?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IDCs", + "html_url": "https://github.com/IDCs", + "followers_url": "https://api.github.com/users/IDCs/followers", + "following_url": "https://api.github.com/users/IDCs/following{/other_user}", + "gists_url": "https://api.github.com/users/IDCs/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IDCs/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IDCs/subscriptions", + "organizations_url": "https://api.github.com/users/IDCs/orgs", + "repos_url": "https://api.github.com/users/IDCs/repos", + "events_url": "https://api.github.com/users/IDCs/events{/privacy}", + "received_events_url": "https://api.github.com/users/IDCs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2024-11-06T11:22:06Z", + "updated_at": "2024-11-06T15:33:26Z", + "closed_at": "2024-11-06T15:33:26Z", + "author_association": "CONTRIBUTOR", + "active_lock_reason": null, + "body": "### Application error\r\n#### System\r\n| | |\r\n|------------ | -------------|\r\n|Platform | win32 10.0.22631 |\r\n|Architecture | x64 |\r\n|Application Version | 0.0.1 |\r\n|Process | renderer |\r\n#### Message\r\nnot implemented\r\n#### Title\r\n```\r\nFailed to purge mods\r\n```\r\n\r\n#### Context\r\n```\r\nextension-api = [object Object],gamemode = Vampire the Masquerade\tBloodlines,extension_version = 1.0.2\r\n```\r\n#### Stack\r\n```\r\nnot implemented\r\nError: not implemented\r\n at loadAllManifests (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:64:25)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:208:19\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromiseCtx (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:641:10)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:97:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\nPrior Context:\r\n at C:\\Projects\\vortex\\src\\util\\util.ts:183:22\r\n at withActivationLock (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\activationStore.ts:303:10)\r\n at purgeModsImpl (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:196:28)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:110:16\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:729:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n\r\nReported from:\r\nError: \r\n at showError (C:\\Projects\\vortex\\src\\util\\message.ts:255:21)\r\n at onShowError (C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:156:16)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:97:11\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:725:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n```\r\n\r\n## Steps To Reproduce:\r\n\r\n•test test test \r\n•test test\r\n•test\r\n•teessssssssstttt\r\n\r\n\r\n\r\nHash: 04cc7c525c15033cdedf6b1266024b9e", + "closed_by": { + "login": "IDCs", + "id": 8960252, + "node_id": "MDQ6VXNlcjg5NjAyNTI=", + "avatar_url": "https://avatars.githubusercontent.com/u/8960252?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IDCs", + "html_url": "https://github.com/IDCs", + "followers_url": "https://api.github.com/users/IDCs/followers", + "following_url": "https://api.github.com/users/IDCs/following{/other_user}", + "gists_url": "https://api.github.com/users/IDCs/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IDCs/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IDCs/subscriptions", + "organizations_url": "https://api.github.com/users/IDCs/orgs", + "repos_url": "https://api.github.com/users/IDCs/repos", + "events_url": "https://api.github.com/users/IDCs/events{/privacy}", + "received_events_url": "https://api.github.com/users/IDCs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "reactions": { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16634/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16634/timeline", + "performed_via_github_app": null, + "state_reason": "completed", + "hash": "04cc7c525c15033cdedf6b1266024b9e" + }, + { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16620", + "repository_url": "https://api.github.com/repos/Nexus-Mods/Vortex", + "labels_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16620/labels{/name}", + "comments_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16620/comments", + "events_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16620/events", + "html_url": "https://github.com/Nexus-Mods/Vortex/issues/16620", + "id": 2627404813, + "node_id": "I_kwDOBAT0m86cmwQN", + "number": 16620, + "title": "error: not implemented", + "user": { + "login": "IDCs", + "id": 8960252, + "node_id": "MDQ6VXNlcjg5NjAyNTI=", + "avatar_url": "https://avatars.githubusercontent.com/u/8960252?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IDCs", + "html_url": "https://github.com/IDCs", + "followers_url": "https://api.github.com/users/IDCs/followers", + "following_url": "https://api.github.com/users/IDCs/following{/other_user}", + "gists_url": "https://api.github.com/users/IDCs/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IDCs/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IDCs/subscriptions", + "organizations_url": "https://api.github.com/users/IDCs/orgs", + "repos_url": "https://api.github.com/users/IDCs/repos", + "events_url": "https://api.github.com/users/IDCs/events{/privacy}", + "received_events_url": "https://api.github.com/users/IDCs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2024-10-31T17:16:12Z", + "updated_at": "2024-10-31T17:17:37Z", + "closed_at": "2024-10-31T17:17:37Z", + "author_association": "CONTRIBUTOR", + "active_lock_reason": null, + "body": "### Application error\r\n#### System\r\n| | |\r\n|------------ | -------------|\r\n|Platform | win32 10.0.22631 |\r\n|Architecture | x64 |\r\n|Application Version | 0.0.1 |\r\n|Process | renderer |\r\n#### Message\r\nnot implemented\r\n#### Title\r\n```\r\nFailed to purge mods\r\n```\r\n\r\n#### Context\r\n```\r\ngamemode = Vampire the Masquerade\tBloodlines,extension_version = 1.0.2\r\n```\r\n#### Stack\r\n```\r\nnot implemented\r\nError: not implemented\r\n at loadAllManifests (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:64:25)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:208:19\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromiseCtx (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:641:10)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:97:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\nPrior Context:\r\n at C:\\Projects\\vortex\\src\\util\\util.ts:183:22\r\n at withActivationLock (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\activationStore.ts:303:10)\r\n at purgeModsImpl (C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:196:28)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\util\\deploy.ts:110:16\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:729:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n\r\nReported from:\r\nError: \r\n at showError (C:\\Projects\\vortex\\src\\util\\message.ts:255:21)\r\n at onShowError (C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:156:16)\r\n at C:\\Projects\\vortex\\src\\extensions\\mod_management\\views\\DeactivationButton.tsx:97:11\r\n at tryCatcher (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\util.js:16:23)\r\n at Promise._settlePromiseFromHandler (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:547:31)\r\n at Promise._settlePromise (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:604:18)\r\n at Promise._settlePromise0 (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:649:10)\r\n at Promise._settlePromises (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\promise.js:725:18)\r\n at _drainQueueStep (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:93:12)\r\n at _drainQueue (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:86:9)\r\n at Async._drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:102:5)\r\n at Async.drainQueues (C:\\Projects\\vortex\\node_modules\\bluebird\\js\\release\\async.js:15:14)\r\n```\r\n\r\nhash: 04cc7c525c15033cdedf6b1266024b9e", + "closed_by": { + "login": "IDCs", + "id": 8960252, + "node_id": "MDQ6VXNlcjg5NjAyNTI=", + "avatar_url": "https://avatars.githubusercontent.com/u/8960252?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/IDCs", + "html_url": "https://github.com/IDCs", + "followers_url": "https://api.github.com/users/IDCs/followers", + "following_url": "https://api.github.com/users/IDCs/following{/other_user}", + "gists_url": "https://api.github.com/users/IDCs/gists{/gist_id}", + "starred_url": "https://api.github.com/users/IDCs/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/IDCs/subscriptions", + "organizations_url": "https://api.github.com/users/IDCs/orgs", + "repos_url": "https://api.github.com/users/IDCs/repos", + "events_url": "https://api.github.com/users/IDCs/events{/privacy}", + "received_events_url": "https://api.github.com/users/IDCs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "reactions": { + "url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16620/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/Nexus-Mods/Vortex/issues/16620/timeline", + "performed_via_github_app": null, + "state_reason": "completed", + "hash": "04cc7c525c15033cdedf6b1266024b9e" + } +] \ No newline at end of file diff --git a/package.json b/package.json index 77d1836..eea6aaf 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "version": "1.1.0", "main": "index.js", "dependencies": { + "@actions/core": "^1.11.1", + "@actions/github": "^6.0.0", "@babel/parser": "^7.22.5", "@babel/traverse": "^7.22.5", "@nexusmods/nexus-api": "^1.1.5", @@ -83,6 +85,7 @@ "tree-kill": "^1.2.2", "tsconfig": "^7.0.0", "v8-compile-cache-lib": "^3.0.1", + "vortex-api": "github:Nexus-Mods/vortex-api", "wrappy": "^1.0.2", "xtend": "^4.0.2", "yn": "^3.1.1" @@ -94,6 +97,7 @@ "add-mods-of-month": "ts-node src/add-mods-of-month.ts", "test-slack": "ts-node src/test-slack.ts", "test-github": "ts-node src/test-github.ts", + "update-github-issues": "ts-node src/github-update-issues.ts", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], diff --git a/src/github-update-issues.ts b/src/github-update-issues.ts new file mode 100644 index 0000000..edaac5f --- /dev/null +++ b/src/github-update-issues.ts @@ -0,0 +1,131 @@ +import * as core from '@actions/core'; +import * as crypto from 'crypto'; +import * as fs from 'fs'; +import * as path from 'path'; +import axios from 'axios'; +import { IGithubIssue } from './types'; +import { genHash } from './utils'; + +function extractErrorDetails(issue: IGithubIssue) { + const report = issue.body; + const messagePattern = /^#### Message\s+([\s\S]*?)^(?=####|$)/igm; + const contextPattern = /^#### Context\s+```([\s\S]*?)```/igm; + const stackPattern = /^#### Stack\s+```([\s\S]*?)```/igm; + + const messageMatch = report.match(messagePattern); + const contextMatch = report.match(contextPattern); + const stackMatch = report.match(stackPattern); + + const errorMessage = messageMatch ? messageMatch[0].replace(/^#### Message\s+/, '').trim() : ''; + const context = contextMatch ? contextMatch[0].replace(/^#### Context\s+```/, '').replace(/```$/, '').trim() : ''; + const stack = stackMatch ? stackMatch[0].replace(/^#### Stack\s+```/, '').replace(/```$/, '').trim() : ''; + + return { + errorMessage, + context, + stack + }; +} + +function generateHash(issue: IGithubIssue) { + return genHash(issue.body.slice(0, -30)); +} + + +async function run() { + try { + const GITHUB_TOKEN = process.env.GITHUB_TOKEN; + const repo = 'nexus-mods/vortex'; + const outputDir = path.resolve(__dirname, path.join('..', 'out')); + const issuesReportFile = path.join(outputDir, 'issues_report.json'); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + const mapToGithubIssue = (rawIssue: any): IGithubIssue => { + const hashRegex = new RegExp('hash: ([a-z0-9]+)', 'igm'); + const result = hashRegex.exec(rawIssue.body); + const hash = result ? result[1] : null; + if (hash === null) { + core.info(`Hash not found in issue ${rawIssue.number}`); + } + return { + ...rawIssue, + hash: hash, + }; + } + const fetchIssues = async (state: string, since: string | null) => { + let issues: IGithubIssue[] = []; + let page = 1; + let hasMorePages = true; + + while (hasMorePages) { + const url = `https://api.github.com/repos/${repo}/issues?state=${state}&per_page=100&page=${page}${since ? `&since=${since}` : ''}`; + const response = await axios.get(url, { + headers: { + Authorization: `${GITHUB_TOKEN}` + } + }); + + issues = issues.concat(response.data.reduce((acc: IGithubIssue[], issue: IGithubIssue) => { + if (!issue?.body || issue.pull_request || issue.title.toLowerCase().startsWith('review')) { + return acc; + } + acc.push(mapToGithubIssue(issue)); + return acc; + }, [])); + + if (response.data.length < 100) { + hasMorePages = false; + } else { + page++; + } + } + return issues; + }; + + const openIssues = await fetchIssues('open', null); + const lastMonthDate = new Date(); + lastMonthDate.setMonth(lastMonthDate.getMonth() - 1); + const closedIssues = await fetchIssues('closed', lastMonthDate.toISOString()); + + const issuesReport: IGithubIssue[] = []; + + const processIssues = (issues: IGithubIssue[]) => { + for (const issue of issues) {; + const author = issue.user.login; + const hashMatch = /hash: ([a-z0-9]+)/gmi; + if (author.toLowerCase() === 'vortexfeedback') { + core.info(`Skipping issue by vortexfeedback: ${issue.number}`); + continue; + } + if (!issue.hash && !hashMatch.test(issue.body)) { + // No hash. + continue; + } + + const hash = issue.hash ?? hashMatch?.exec?.(issue.body)?.[1]; + issue.hash = hash + issuesReport.push(issue); + core.info(`Added issue by ${author}: ${issue.number}`); + } + }; + + // Process both open and closed issues + processIssues(openIssues); + processIssues(closedIssues); + + try { + // Remove the existing file + fs.unlinkSync(issuesReportFile); + } catch (err) { + // do nothing + } + // Write issues report to JSON file + fs.writeFileSync(issuesReportFile, JSON.stringify(issuesReport, null, 2)); + core.info(`Issues report written to ${issuesReportFile}`); + } catch (error: any) { + core.setFailed(error); + } +} + +run(); diff --git a/src/types.ts b/src/types.ts index a30e09a..8455ccd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -57,6 +57,39 @@ export interface IGitHubUser { site_admin: boolean; } +export interface IGithubIssue { + url: string; + repository_url: string; + id: number; + number: number; + title: string; + user: IGitHubUser; + labels: Array<{ + id: number; + node_id: string; + url: string; + name: string; + color: string; + default: boolean; + description: string | null; + }>; + state: string; + locked: boolean; + created_at: string; + updated_at: string; + closed_at: string | null; + body: string; + closed_by: string | null; + state_reason: string | null; + pull_request?: { + url: string; + html_url: string; + diff_url: string; + patch_url: string; + }; + hash?: string; +} + export interface IGitHubAsset { browser_download_url: string; content_type: string; @@ -109,7 +142,7 @@ export interface IMOTMEntry { * Generated ID for the video */ id: string; - + /** * YouTube id of the video */ @@ -123,17 +156,17 @@ export interface IMOTMEntry { export class Rejected extends Error { constructor() { - super('Update rejected'); - Error.captureStackTrace(this, this.constructor); + super('Update rejected'); + Error.captureStackTrace(this, this.constructor); - this.name = this.constructor.name; + this.name = this.constructor.name; } } export type DownloadStats = { [modId: string]: { unique: number, total: number } }; export type ModDownloadStats = { - modId: string; - total: number; - unique: number; + modId: string; + total: number; + unique: number; }; diff --git a/src/utils.ts b/src/utils.ts index e89ee51..848a5a5 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -53,3 +53,107 @@ export function getFormattedDate(date: Date): string { return `${year}${month}${day}_${hours}${minutes}`; } + +//#region HashGeneration +export interface IError { + message: string; + title?: string; + subtitle?: string; + code?: string; + details?: string; + stack?: string; + extension?: string; + path?: string; + allowReport?: boolean; + attachLog?: boolean; +} + +// remove the file names from stack lines because they contain local paths +function removeFileNames(input: string): string { + return input + .replace(/(at [^\(]*)\(.*\)$/, '$1') + .replace(/at [A-Z]:\\.*\\([^\\]*)/, 'at $1'); +} + +// remove everything in quotes to get file names and such out of the error message +function removeQuoted(input: string): string { + return input + .replace(/'.*?'($|\s|\.|\,|\;)/g, '').replace(/"[^"]*"/g, '').replace(/'[^']*'/g, ''); +} + +// sanitize certain well known error messages that don't get properly stripped by removing quotes +// or contain localized components +function sanitizeKnownMessages(input: string): string { + return input + .replace(/(Unexpected token ). (in JSON at position) [0-9]+/, '$1$2 ...') + // reported from loot, the rest of these errors is localized + .replace(/(boost::filesystem::file_size:) .*/, '$1') + .replace(/.*(contains invalid WIN32 path characters.)/, '... $1') + .replace(/(Error: Cannot get property '[^']*' on missing remote object) [0-9]+/, '$1') + .replace(/.*(Cipher functions:OPENSSL_internal).*/, '$1') + .replace(/\\\\?\\.*(\\Vortex\\resources)/i, '$1') + ; +} + +// remove stack lines that are known to contain information that doesn't distinguish the issue +// but tends to be variable +function removeKnownVariable(input: string): string { + return input + .replace(/HResult: [0-9\-]*/, '') + .replace(/[0-9]+:error:[0-9a-f]+:(SSL routines:OPENSSL_internal):.*/, '$1') + ; +} + +// replace "at foobar [as somename]" by "at somename" +// TODO: This is mostly necessary because source maps are tranlated incorrectly and in these cases, +// "foobar part" seems to be almost random and non-sensical wheras the "somename part" is mostly +// correct +function replaceFuncName(input: string): string { + return input + .replace(/at [^ ]* \[as (.*?)\]/, 'at $1'); +} + +// this attempts to remove everything "dynamic" about the error message so that +// the hash is only calculated on the static part so we can group them +function sanitizeStackLine(input: string): string { + return replaceFuncName(removeKnownVariable(removeQuoted(removeFileNames(input)))); +} + +export function extractToken(error: IError): string { + if (error.stack === undefined) { + return removeQuoted(error.message); + } + + let hashStack = error.stack.split('\n'); + + let messageLineCount = hashStack.findIndex(line => line.startsWith(' ')); + if (messageLineCount === -1) { + messageLineCount = 1; + } + + hashStack = [ + removeQuoted(sanitizeKnownMessages(hashStack.slice(0, messageLineCount).join(' '))), + ...hashStack.slice(messageLineCount).map(sanitizeStackLine), + ]; + + const idx = hashStack.findIndex( + line => (line.indexOf('Promise._settlePromiseFromHandler') !== -1) + || (line.indexOf('MappingPromiseArray._promiseFulfilled') !== -1)); + if (idx !== -1) { + hashStack.splice(idx); + } + + return hashStack.join('\n'); +} + +export function genHash(input: IError | string): string { + const { createHash } = require('crypto'); + const hash = createHash('md5'); + if (typeof input === 'string') { + return hash.update(input).digest('hex'); + } else { + return hash.update(extractToken(input)).digest('hex'); + } +} + +//#endregion \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 1597771..7d26782 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6,6 +6,44 @@ version "23.0.1" resolved "https://codeload.github.com/Nexus-Mods/7z-bin/tar.gz/09c2bc201f8d00860ffa28b2decd7db26d62d115" +"@actions/core@^1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.11.1.tgz#ae683aac5112438021588030efb53b1adb86f172" + integrity sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A== + dependencies: + "@actions/exec" "^1.1.1" + "@actions/http-client" "^2.0.1" + +"@actions/exec@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611" + integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== + dependencies: + "@actions/io" "^1.0.1" + +"@actions/github@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@actions/github/-/github-6.0.0.tgz#65883433f9d81521b782a64cc1fd45eef2191ea7" + integrity sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g== + dependencies: + "@actions/http-client" "^2.2.0" + "@octokit/core" "^5.0.1" + "@octokit/plugin-paginate-rest" "^9.0.0" + "@octokit/plugin-rest-endpoint-methods" "^10.0.0" + +"@actions/http-client@^2.0.1", "@actions/http-client@^2.2.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.3.tgz#31fc0b25c0e665754ed39a9f19a8611fc6dab674" + integrity sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA== + dependencies: + tunnel "^0.0.6" + undici "^5.25.4" + +"@actions/io@^1.0.1": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.3.tgz#4cdb6254da7962b07473ff5c335f3da485d94d71" + integrity sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q== + "@ampproject/remapping@^2.2.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -240,6 +278,11 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" @@ -379,7 +422,7 @@ "@octokit/request-error" "^5.0.0" "@octokit/types" "^12.0.0" -"@octokit/core@^5.0.0": +"@octokit/core@^5.0.0", "@octokit/core@^5.0.1": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" integrity sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg== @@ -475,6 +518,13 @@ dependencies: "@octokit/types" "^13.5.0" +"@octokit/plugin-rest-endpoint-methods@^10.0.0": + version "10.4.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz#41ba478a558b9f554793075b2e20cd2ef973be17" + integrity sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg== + dependencies: + "@octokit/types" "^12.6.0" + "@octokit/plugin-retry@^6.0.0": version "6.0.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz#3257404f7cc418e1c1f13a7f2012c1db848b7693" @@ -3103,6 +3153,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -3185,6 +3240,13 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici@^5.25.4: + version "5.28.4" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" + integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== + dependencies: + "@fastify/busboy" "^2.0.0" + universal-github-app-jwt@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.2.tgz#8c1867a394d7d9d42cda34f11d1bcb023797d8df" @@ -3252,6 +3314,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +"vortex-api@github:Nexus-Mods/vortex-api": + version "1.8.11" + resolved "https://codeload.github.com/Nexus-Mods/vortex-api/tar.gz/920862d472183b37a2b64fcd1bdbceadbf07c4e9" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"