diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index ec71c4f32e..2e78ebc26a 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -14,3 +14,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }} + freeze-date: '2024-01-08T12:00:00Z' diff --git a/.github/workflows/service-checker.yml b/.github/workflows/service-checker.yml new file mode 100644 index 0000000000..0b2f2c463c --- /dev/null +++ b/.github/workflows/service-checker.yml @@ -0,0 +1,14 @@ +name: Service Checker + +on: + schedule: + - cron: "0 0-23/4 * * 0-6" + workflow_dispatch: + +jobs: + pr-reviews-reminder: + runs-on: ubuntu-latest + steps: + - uses: Aniket-Engg/pr-reviews-reminder-action@master + with: + sc-webhook-url: ${{ secrets.SERVICECHECKER_WEBHOOK_URL }} diff --git a/apps/circuit-compiler/src/app/components/configurations.tsx b/apps/circuit-compiler/src/app/components/configurations.tsx index 34b5075b69..a9583c093a 100644 --- a/apps/circuit-compiler/src/app/components/configurations.tsx +++ b/apps/circuit-compiler/src/app/components/configurations.tsx @@ -1,8 +1,8 @@ -import { CustomTooltip } from "@remix-ui/helper" +import { CustomTooltip, RenderIf } from "@remix-ui/helper" import { FormattedMessage } from "react-intl" import { ConfigurationsProps, PrimeValue } from "../types" -export function Configurations ({primeValue, setPrimeValue}: ConfigurationsProps) { +export function Configurations ({primeValue, setPrimeValue, versionValue}: ConfigurationsProps) { return (
@@ -14,7 +14,7 @@ export function Configurations ({primeValue, setPrimeValue}: ConfigurationsProps placement={"auto"} tooltipId="circuitPrimeLabelTooltip" tooltipClasses="text-nowrap" - tooltipText={{'To choose the prime number to use to generate the circuit. Receives the name of the curve (bn128, bls12381, goldilocks) [default: bn128]'}} + tooltipText={{'To choose the prime number to use to generate the circuit. Receives the name of the curve (bn128, bls12381, goldilocks, grumpkin, pallas, vesta)'}} >
diff --git a/apps/circuit-compiler/src/app/components/container.tsx b/apps/circuit-compiler/src/app/components/container.tsx index d56036e44d..fa7467f69c 100644 --- a/apps/circuit-compiler/src/app/components/container.tsx +++ b/apps/circuit-compiler/src/app/components/container.tsx @@ -29,6 +29,7 @@ export function Container () { } const handleVersionSelect = (version: string) => { + circuitApp.plugin.compilerVersion = version circuitApp.dispatch({ type: 'SET_COMPILER_VERSION', payload: version }) } @@ -44,7 +45,8 @@ export function Container () { } } - const handlePrimeChange = (value: string) => { + const handlePrimeChange = (value: PrimeValue) => { + circuitApp.plugin.compilerPrime = value circuitApp.dispatch({ type: 'SET_PRIME_VALUE', payload: value as PrimeValue }) } @@ -75,7 +77,7 @@ export function Container () { - + 0}> diff --git a/apps/circuit-compiler/src/app/services/circomPluginClient.ts b/apps/circuit-compiler/src/app/services/circomPluginClient.ts index 0eccddb281..b4c3ecc9ad 100644 --- a/apps/circuit-compiler/src/app/services/circomPluginClient.ts +++ b/apps/circuit-compiler/src/app/services/circomPluginClient.ts @@ -2,19 +2,22 @@ import { PluginClient } from '@remixproject/plugin' import { createClient } from '@remixproject/plugin-webview' import EventManager from 'events' import pathModule from 'path' -import { parse, compile, generate_witness, generate_r1cs, compiler_list } from 'circom_wasm' +import { compiler_list } from 'circom_wasm' +import * as compilerV216 from 'circom_wasm/v2.1.6' +import * as compilerV215 from 'circom_wasm/v2.1.5' import { extractNameFromKey, extractParentFromKey } from '@remix-ui/helper' -import { CompilationConfig, CompilerReport, ResolverOutput } from '../types' +import { CompilationConfig, CompilerReport, PrimeValue, ResolverOutput } from '../types' export class CircomPluginClient extends PluginClient { public internalEvents: EventManager private _compilationConfig: CompilationConfig = { - version: "2.1.5", + version: "2.1.6", prime: "bn128" } private lastCompiledCircuitPath: string = '' private lastParsedFiles: Record = {} private lastCompiledFile: string = '' + private compiler: typeof compilerV215 | typeof compilerV216 = compilerV216 constructor() { super() @@ -32,13 +35,26 @@ export class CircomPluginClient extends PluginClient { this.internalEvents.emit('circom_activated') } + set compilerVersion (version: string) { + if (!compiler_list.versions.includes(version)) throw new Error("Unsupported compiler version") + this._compilationConfig.version = version + if (version === '2.1.5') this.compiler = compilerV215 + else if (version === '2.1.6') this.compiler = compilerV216 + } + + set compilerPrime (prime: PrimeValue) { + if ((prime !== "bn128") && (prime !== "bls12381") && (prime !== "goldilocks") && (this._compilationConfig.version === '2.1.5')) throw new Error('Invalid prime value') + if ((prime !== "bn128") && (prime !== "bls12381") && (prime !== "goldilocks") && (prime !== "grumpkin") && (prime !== "pallas") && (prime !== "vesta") && (this._compilationConfig.version === '2.1.6')) throw new Error('Invalid prime value') + this._compilationConfig.prime = prime + } + async parse(path: string, fileContent?: string): Promise<[CompilerReport[], Record]> { if (!fileContent) { // @ts-ignore fileContent = await this.call('fileManager', 'readFile', path) } this.lastParsedFiles = await this.resolveDependencies(path, fileContent, { [path]: { content: fileContent, parent: null } }) - const parsedOutput = parse(path, this.lastParsedFiles) + const parsedOutput = this.compiler.parse(path, this.lastParsedFiles) try { const result: CompilerReport[] = JSON.parse(parsedOutput.report()) @@ -122,12 +138,10 @@ export class CircomPluginClient extends PluginClient { if (compilationConfig) { const { prime, version } = compilationConfig - if ((prime !== "bn128") && (prime !== "bls12381") && (prime !== "goldilocks")) throw new Error('Invalid prime value') - if (!compiler_list.versions.includes(version)) throw new Error("Unsupported compiler version") - this._compilationConfig.prime = prime - this._compilationConfig.version = version + this.compilerVersion = version + this.compilerPrime = prime } - const circuitApi = compile(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) + const circuitApi = this.compiler.compile(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) const circuitProgram = circuitApi.program() if (circuitProgram.length < 1) { @@ -172,12 +186,10 @@ export class CircomPluginClient extends PluginClient { if (compilationConfig) { const { prime, version } = compilationConfig - if ((prime !== "bn128") && (prime !== "bls12381") && (prime !== "goldilocks")) throw new Error('Invalid prime value') - if (!compiler_list.versions.includes(version)) throw new Error("Unsupported compiler version") - this._compilationConfig.prime = prime - this._compilationConfig.version = version + this.compilerVersion = version + this.compilerPrime = prime } - const r1csApi = generate_r1cs(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) + const r1csApi = this.compiler.generate_r1cs(path, this.lastParsedFiles, { prime: this._compilationConfig.prime }) const r1csProgram = r1csApi.program() if (r1csProgram.length < 1) { @@ -202,7 +214,7 @@ export class CircomPluginClient extends PluginClient { // @ts-ignore const buffer: any = await this.call('fileManager', 'readFile', wasmPath, { encoding: null }) const dataRead = new Uint8Array(buffer) - const witness = await generate_witness(dataRead, input) + const witness = await this.compiler.generate_witness(dataRead, input) // @ts-ignore await this.call('fileManager', 'writeFile', wasmPath.replace('.wasm', '.wtn'), witness, true) this.internalEvents.emit('circuit_computing_witness_done') diff --git a/apps/circuit-compiler/src/app/types/index.ts b/apps/circuit-compiler/src/app/types/index.ts index 71e1dbfced..3b6f7a57b4 100644 --- a/apps/circuit-compiler/src/app/types/index.ts +++ b/apps/circuit-compiler/src/app/types/index.ts @@ -45,7 +45,7 @@ export type CompilationConfig = { version: string } -export type PrimeValue = "bn128" | "bls12381" | "goldilocks" +export type PrimeValue = "bn128" | "bls12381" | "goldilocks" | "grumpkin" | "pallas" | "vesta" export type CompilerFeedbackProps = { feedback: string | CompilerReport[], @@ -76,7 +76,8 @@ export type FeedbackAlertProps = { export type ConfigurationsProps = { setPrimeValue: (prime: PrimeValue) => void, - primeValue: PrimeValue + primeValue: PrimeValue, + versionValue: string } export type CompileOptionsProps = { diff --git a/apps/remix-ide-e2e/src/tests/circom.test.ts b/apps/remix-ide-e2e/src/tests/circom.test.ts index 0cad3052f3..6f57533b3e 100644 --- a/apps/remix-ide-e2e/src/tests/circom.test.ts +++ b/apps/remix-ide-e2e/src/tests/circom.test.ts @@ -107,7 +107,7 @@ module.exports = { .waitForElementPresent('[data-id="circuit_feedback"]') .waitForElementVisible('[data-id="circuit_feedback"]') .assert.hasClass('[data-id="circuit_feedback"]', 'alert-warning') - .waitForElementContainsText('[data-id="circuit_feedback"]', 'File circuits/simple.circom does not include pragma version. Assuming pragma version (2, 1, 5)') + .waitForElementContainsText('[data-id="circuit_feedback"]', 'File circuits/simple.circom does not include pragma version. Assuming pragma version (2, 1, 6)') }, 'Should hide/show warnings for compiled circuit #group4': function (browser: NightwatchBrowser) { browser @@ -115,7 +115,7 @@ module.exports = { .waitForElementNotPresent('[data-id="circuit_feedback"]') .click('[data-id="hide_circuit_warnings_checkbox_input"]') .waitForElementVisible('[data-id="circuit_feedback"]') - .waitForElementContainsText('[data-id="circuit_feedback"]', 'File circuits/simple.circom does not include pragma version. Assuming pragma version (2, 1, 5)') + .waitForElementContainsText('[data-id="circuit_feedback"]', 'File circuits/simple.circom does not include pragma version. Assuming pragma version (2, 1, 6)') }, 'Should display error for invalid circuit #group4': function (browser: NightwatchBrowser) { browser diff --git a/apps/remix-ide/src/app/tabs/locales/en/homeReleaseDetails.json b/apps/remix-ide/src/app/tabs/locales/en/homeReleaseDetails.json deleted file mode 100644 index 06a2f565d7..0000000000 --- a/apps/remix-ide/src/app/tabs/locales/en/homeReleaseDetails.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "homeReleaseDetails.title": "v0.38.0 RELEASE HIGHLIGHTS", - "homeReleaseDetails.highlight1": "Alpha release for Solidity co-pilot", - "homeReleaseDetails.highlight2": "Define Solidity remappings in remappings.txt file", - "homeReleaseDetails.highlight3": "Run free function for any selected environment", - "homeReleaseDetails.highlight4": "New Circom ZKP templates: Hash Checker & Rate Limiting Nullifier", - "homeReleaseDetails.more": "Read More" -} - - - diff --git a/apps/remix-ide/src/app/tabs/locales/en/index.js b/apps/remix-ide/src/app/tabs/locales/en/index.js index 7f347165db..8da7dd179f 100644 --- a/apps/remix-ide/src/app/tabs/locales/en/index.js +++ b/apps/remix-ide/src/app/tabs/locales/en/index.js @@ -1,7 +1,6 @@ import debuggerJson from './debugger.json'; import filePanelJson from './filePanel.json'; import homeJson from './home.json'; -import homeReleaseDetailsJson from './homeReleaseDetails.json'; import panelJson from './panel.json'; import pluginManagerJson from './pluginManager.json'; import searchJson from './search.json'; @@ -21,7 +20,6 @@ export default { ...debuggerJson, ...filePanelJson, ...homeJson, - ...homeReleaseDetailsJson, ...panelJson, ...pluginManagerJson, ...searchJson, diff --git a/apps/remix-ide/src/app/tabs/settings-tab.tsx b/apps/remix-ide/src/app/tabs/settings-tab.tsx index e9a77080b7..8bbf8b2c8a 100644 --- a/apps/remix-ide/src/app/tabs/settings-tab.tsx +++ b/apps/remix-ide/src/app/tabs/settings-tab.tsx @@ -92,11 +92,9 @@ module.exports = class SettingsTab extends ViewPlugin { this.config.set('settings/matomo-analytics', isChecked) this.useMatomoAnalytics = isChecked if (!isChecked) { - _paq.push(['optUserOut']) // revoke tracking consent _paq.push(['forgetConsentGiven']); } else { - _paq.push(['forgetUserOptOut']) // user has given consent to process their data _paq.push(['setConsentGiven']); } diff --git a/apps/remix-ide/src/assets/js/loader.js b/apps/remix-ide/src/assets/js/loader.js index 5938aeaf9c..4abdfc6526 100644 --- a/apps/remix-ide/src/assets/js/loader.js +++ b/apps/remix-ide/src/assets/js/loader.js @@ -18,17 +18,14 @@ if (domains[window.location.hostname]) { _paq.push(["setExcludedQueryParams", ["code","gist"]]); _paq.push(["setExcludedReferrers", ["etherscan.io"]]); _paq.push(['enableJSErrorTracking']); - // require user tracking consent before processing data - _paq.push(['requireConsent']); _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); _paq.push(['enableHeartBeatTimer']); if (!window.localStorage.getItem('config-v0.8:.remix.config') || (window.localStorage.getItem('config-v0.8:.remix.config') && !window.localStorage.getItem('config-v0.8:.remix.config').includes('settings/matomo-analytics'))) { - _paq.push(['optUserOut']) - + // require user tracking consent before processing data + _paq.push(['requireConsent']); } else { - _paq.push(['forgetUserOptOut']) // user has given consent to process their data _paq.push(['setConsentGiven']) } diff --git a/apps/vyper/src/app/components/WarnRemote.tsx b/apps/vyper/src/app/components/WarnRemote.tsx index ee0d4b9422..5038b61fb9 100644 --- a/apps/vyper/src/app/components/WarnRemote.tsx +++ b/apps/vyper/src/app/components/WarnRemote.tsx @@ -10,7 +10,7 @@ function WarnRemoteLabel({environment}: Props) { } return ( - The remote compiler should only be used for testing NOT for production environments. For production, use a local compiler. + Do not use the remote compiler in a production environment, it is only for testing purposes. For production, use a local compiler. ) } diff --git a/createPRToBeta.ts b/createPRToBeta.ts new file mode 100644 index 0000000000..98237c6545 --- /dev/null +++ b/createPRToBeta.ts @@ -0,0 +1,48 @@ +// This script can be used to open a PR for base branch 'remix_beta' using an existing pull request +// Pull request number should be provided while running this script +// It will use the reference branch same as the shared PR +// To create a new PR, Github auth token with scope 'repo' needs to be provided +// Command to run this script: fromPR=4369 authToken=abc123 yarn run createPRToBeta + +import { Octokit } from "octokit" + +async function createPR (prNumber, baseBranch) { + try { + if (!prNumber) throw new Error(`Please provide a PR number with 'fromPR' env variable`) + + const octokit = new Octokit({ + auth: process.env.authToken || '' + }) + + const owner = 'ethereum' + const repo = 'remix-project' + + const prData = await octokit.request('GET /repos/{owner}/{repo}/pulls/{pull_number}', { + owner: owner, + repo: repo, + pull_number: prNumber, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }) + + const response = await octokit.request('POST /repos/{owner}/{repo}/pulls', { + owner: owner, + repo: repo, + title: prData.data.title + ' (for beta)', + body: prData.data.body + ' (for beta)', + head: prData.data.head.ref, + base: baseBranch, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }) + + console.log('Pull Request Created!!! See: ', response.data.html_url) + + } catch (error) { + console.error('Error during PR creation: ', error.message) + } +} + +createPR(process.env.fromPR, 'remix_beta') diff --git a/gulpfile.js b/gulpfile.js index 8347a147db..f5d0819a9f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,15 +5,29 @@ const { task } = require('gulp'); const fs = require('fs'); const util = require('util'); const promisifyExec = util.promisify(require('child_process').exec); +const axios = require('axios'); var packageJSON = require('./package.json'); /** - * @dev Task to create git tag using version from package.json and pushing this specific tag + * @dev Task to create git tag using version from package.json of remix_beta branch and pushing this specific tag */ -task('publishTag', async function () { - const tag = "v" + packageJSON.version - await promisifyExec(`git tag ${tag}; git push origin ${tag}`); +task('publishTagfromBeta', async function () { + try { + let cmdOp = await promisifyExec(`git checkout remix_beta`) + console.log(cmdOp.stdout) + cmdOp = await promisifyExec(`git pull origin remix_beta`) + console.log(cmdOp.stdout) + const betaPackageJSON = fs.readFileSync(__dirname + '/package.json', 'utf8') + const tag = "v" + JSON.parse(betaPackageJSON).version + console.log(`Creating tag ${tag} from remix_beta branch`) + cmdOp = await promisifyExec(`git tag ${tag}`) + console.log(cmdOp.stdout) + cmdOp = await promisifyExec(`git push --tags`) + console.log(cmdOp.stdout) + }catch(error) { + console.error(error) + } }); /** @@ -61,4 +75,40 @@ task('syncLibVersions', async function () { fs.writeFileSync(__dirname + '/libs/' + lib + '/package.json', JSON.stringify(distPackageJSON, null, 2), 'utf8') }) await Promise.resolve(); -}); \ No newline at end of file +}); + +async function setBranchHead(branchName, head) { + try { + console.log(`Setting ${branchName} branch head to ${head}`) + let cmdOp = await promisifyExec(`git checkout ${branchName}`) + console.log(cmdOp.stdout) + cmdOp = await promisifyExec(`git pull origin ${branchName}`) + console.log(cmdOp.stdout) + cmdOp = await promisifyExec(`git reset --hard ${head}`) + console.log(cmdOp.stdout) + cmdOp = await promisifyExec(`git push -f origin ${branchName}`) + console.log(cmdOp.stdout) + }catch(error) { + console.error(error) + } +} + +/* +* @dev Task to set remix_beta branch up to date with master +*/ +task('updateBetaToMaster', async function () { + const masterBranchDetails = await axios.get('https://api.github.com/repos/ethereum/remix-project/branches/master') + const masterBranchHead = masterBranchDetails.data.commit.sha + await setBranchHead('remix_beta', masterBranchHead) + await Promise.resolve(); +}); + +/* +* @dev Task to set remix_live branch up to date with remix_beta +*/ +task('updateLiveToBeta', async function () { + const betaBranchDetails = await axios.get('https://api.github.com/repos/ethereum/remix-project/branches/remix_beta') + const betaBranchHead = betaBranchDetails.data.commit.sha + await setBranchHead('remix_live', betaBranchHead) + await Promise.resolve(); + }); \ No newline at end of file diff --git a/libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx b/libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx index 59391d1e09..8148602796 100644 --- a/libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/components/modals/matomo.tsx @@ -61,14 +61,12 @@ const MatomoDialog = (props: MatomoDialogProps) => { const declineModal = async () => { settings.updateMatomoAnalyticsChoice(false) - _paq.push(['optUserOut']) // revoke tracking consent _paq.push(['forgetConsentGiven']); setVisible(false) } const handleModalOkClick = async () => { - _paq.push(['forgetUserOptOut']) // user has given consent to process their data _paq.push(['setConsentGiven']); settings.updateMatomoAnalyticsChoice(true) diff --git a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx index 91b254f913..864819c62b 100644 --- a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx @@ -128,7 +128,7 @@ const RemixApp = (props: IRemixAppUi) => { break } case UsageTypes.Advance: { - _paq.push(['trackEvent', 'enterDialog', 'usageType', 'tutor']) + _paq.push(['trackEvent', 'enterDialog', 'usageType', 'advanced']) break } case UsageTypes.Prototyper: { diff --git a/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx b/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx index 4f1d72bfad..2568f88bf5 100644 --- a/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx +++ b/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx @@ -4,6 +4,7 @@ import {FormattedMessage} from 'react-intl' import {ThemeContext, themes} from '../themeContext' import Carousel from 'react-multi-carousel' import 'react-multi-carousel/lib/styles.css' +import * as releaseDetails from './../../../../../../releaseDetails.json' const _paq = (window._paq = window._paq || []) // eslint-disable-line @@ -73,28 +74,26 @@ function HomeTabFeatured() {
- +
-
- -
+
{releaseDetails.version} {releaseDetails.title}
    -
  • -
  • -
  • -
  • + { releaseDetails.highlight1 ?
  • {releaseDetails.highlight1}
  • : '' } + { releaseDetails.highlight2 ?
  • {releaseDetails.highlight2}
  • : '' } + { releaseDetails.highlight3 ?
  • {releaseDetails.highlight3}
  • : '' } + { releaseDetails.highlight4 ?
  • {releaseDetails.highlight4}
  • : '' }
_paq.push(['trackEvent', 'hometab', 'featuredSection', 'seeFullChangelog'])} target="__blank" - href="https://medium.com/remix-ide/remix-release-v0-38-0-dccd551b6f1e" + href={releaseDetails.moreLink} > - + {releaseDetails.more}
diff --git a/libs/remix-ui/settings/src/lib/settingsAction.ts b/libs/remix-ui/settings/src/lib/settingsAction.ts index cc5b096ee0..6e59d25ffb 100644 --- a/libs/remix-ui/settings/src/lib/settingsAction.ts +++ b/libs/remix-ui/settings/src/lib/settingsAction.ts @@ -43,9 +43,11 @@ export const useMatomoAnalytics = (config, checked, dispatch) => { config.set('settings/matomo-analytics', checked) dispatch({ type: 'useMatomoAnalytics', payload: { isChecked: checked, textClass: checked ? textDark : textSecondary } }) if (checked) { - _paq.push(['forgetUserOptOut']) + // user has given consent to process their data + _paq.push(['setConsentGiven']); } else { - _paq.push(['optUserOut']) + // revoke tracking consent + _paq.push(['forgetConsentGiven']); } } diff --git a/package.json b/package.json index 9a0dbe0cdc..dbe64a65ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "remix-project", - "version": "0.39.0-dev", + "version": "0.40.0-dev", "license": "MIT", "description": "Ethereum Remix Monorepo", "main": "index.js", @@ -51,6 +51,7 @@ "lint:libs": "nx run-many --target=lint --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remix-ws-templates,remixd,remix-ui-tree-view,remix-ui-modal-dialog,remix-ui-toaster,remix-ui-helper,remix-ui-debugger-ui,remix-ui-workspace,remix-ui-static-analyser,remix-ui-checkbox,remix-ui-settings,remix-core-plugin,remix-ui-renderer,remix-ui-publish-to-storage,remix-ui-solidity-compiler,solidity-unit-testing,remix-ui-plugin-manager,remix-ui-terminal,remix-ui-editor,remix-ui-app,remix-ui-tabs,remix-ui-panel,remix-ui-run-tab,remix-ui-permission-handler,remix-ui-search,remix-ui-file-decorators,remix-ui-tooltip-popup,ghaction-helper", "build:libs": "nx run-many --target=build --parallel=false --with-deps=true --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-solidity,remix-tests,remix-url-resolver,remix-ws-templates,remixd,ghaction-helper", "test:libs": "nx run-many --target=test --projects=remix-analyzer,remix-astwalker,remix-debug,remix-lib,remix-simulator,remix-tests,remix-url-resolver", + "publish:remixd": "yarn build remixd && cd ./dist/libs/remixd && yarn publish", "publish:libs": "yarn run build:libs && lerna publish --skip-git && yarn run bumpVersion:libs", "publishDev:libs": "yarn run build:libs && lerna publish --npm-tag alpha --skip-git && yarn run bumpVersion:libs", "build:e2e": "node apps/remix-ide-e2e/src/buildGroupTests.js && tsc -p apps/remix-ide-e2e/tsconfig.e2e.json", @@ -58,6 +59,10 @@ "babel": "babel", "watch:e2e": "nodemon", "bumpVersion:libs": "gulp & gulp syncLibVersions;", + "updateBeta": "gulp & gulp updateBetaToMaster;", + "updateLive": "gulp & gulp updateLiveToBeta;", + "publishTagfromBeta": "gulp & gulp publishTagfromBeta;", + "createPRToBeta": "npx ts-node createPRToBeta.ts", "browsertest": "sleep 5 && yarn run nightwatch_local", "csslint": "csslint --ignore=order-alphabetical --errors='errors,duplicate-properties,empty-rules' --exclude-list='apps/remix-ide/src/assets/css/font-awesome.min.css' apps/remix-ide/src/assets/css/", "downloadsolc_assets_e2e": "node ./apps/remix-ide/ci/download_e2e_assets.js", @@ -157,7 +162,7 @@ "brace": "^0.8.0", "change-case": "^4.1.1", "chokidar": "^2.1.8", - "circom_wasm": "^0.1.0", + "circom_wasm": "^0.2.0", "color-support": "^1.1.3", "commander": "^9.4.1", "core-js": "^3.6.5", @@ -193,6 +198,7 @@ "latest-version": "^5.1.0", "merge": "^2.1.1", "npm-install-version": "^6.0.2", + "octokit": "^3.1.2", "openai": "^3.3.0", "path-browserify": "^1.0.1", "prettier": "^2.8.4", diff --git a/release-process.md b/release-process.md index a427255efc..f475ee9257 100644 --- a/release-process.md +++ b/release-process.md @@ -11,6 +11,12 @@ This document includes the release instructions for: ## Feature Freeze Once feature freeze is done, `remix_beta` should be updated latest to the master which will automatically update `remix-beta.ethereum.org` through a CI job. +Use this unified command: + + - `yarn run updateBeta` + +or individually: + - `git checkout remix_beta` - `git pull origin remix_beta` - `git reset --hard ` (`master-commit-hash` will be latest commit id from `master` branch) @@ -21,39 +27,45 @@ Testing is performed after the Feature Freeze on `remix-beta.ethereum.org`. `bui Once ready to run, it can be run using the Node.js: `node build-qa-doc.js` -Find out the four release highlights and update in this file: `remix-project/apps/remix-ide/src/app/tabs/locales/en/homeReleaseDetails.json` along with the version in `title` string +Find out the latest release highlights and update in `releaseDetails.json` file along with the `version` string. Also, update release blog link under `moreLink` field. This will set latest release details in the slide of `Featured` section. -Update the GitHub release link in this file: `remix-project/libs/remix-ui/home-tab/src/lib/components/homeTabFeatured.tsx` at line 44 & 63 +## Remix Project NPM packages publishing -This will set latest release details in the first slide of `Featured` section. +Once testing is completed, release will start by publishing Remix NPM packages. -## remixd NPM release -Once testing is completed, release will start by publishing `remixd`.if required, `remixd` can be also released individually + - Make sure you are on `master` branch: `git checkout master` + - Pull the latest: `git pull origin master` + - Create a branch: `git checkout -b bumpLibsVersion` - - Bump version for remixd in `./libs/remixd/package.json` - - Run: `yarn build remixd` - - Move to build directory: `cd ./dist/libs/remixd` - - Publish to NPM: `npm publish` (Make sure you are logged in to NPM) - - create bump PR to master +### remixd NPM release -## Remix libraries NPM release - - Make sure you are on latest `master` branch - - `git pull origin master` - - `git checkout -b bumpLibsVersion` - - `yarn run publish:libs ` + `yarn run publish:remixd` + +This command will ask for a new version. + +### Other libraries NPM release + + `yarn run publish:libs ` This command uses `lerna` and is solely responsible for publishing all the remix libraries. It will ask for a new version of each library. Make sure you are logged in to NPM. -Once this command has been run, the versions for each remix library will be updated to latest in the libs' package.json file. +Once these command run successfully, the version for each remix library will be updated to latest in the libs' package.json file. + - Create and merge bump PR to master ## Remix IDE Release -Make sure release highlights and full changelog link is updated to show them on Home tab. +:point_right: Make sure release highlights and blog link are updated to show them on Home tab, Featured section. ### Part 1. Bump the version and update Beta #### Make sure `remix_beta` is up-to-date with `master` branch: +Use this unified command: + + - `yarn run updateBeta` + +or individually: + - `git checkout remix_beta` - `git pull origin remix_beta` - `git reset --hard ` @@ -68,16 +80,29 @@ Make sure release highlights and full changelog link is updated to show them on #### Create git tag from beta branch: +Use this unified command: + + - `yarn run publishTagfromBeta` + +or individually: + - `git checkout remix_beta` - `git pull origin remix_beta` - Create tag: `git tag v`, `` should be same as in package.json of `remix_beta` branch - Push tag: `git push --tags` - - Publish a new release on GitHub and generate automated changelog by selecting the appropriate tag + +Publish a new release on GitHub using created tag and generate automated changelog by selecting the appropriate previous tag ### Part 2. Update the Remix Live Updating the `remix_live` branch latest to the `remix_beta` runs the CircleCI build which updates liver version of Remix IDE on `remix.ethereum.org` +Use this unified command: + + - `yarn run updateLive` + +or individually: + - `git checkout remix_live` - `git pull origin remix_live` - `git reset --hard ` or `` sometimes @@ -96,6 +121,7 @@ Updating the `remix_live` branch latest to the `remix_beta` runs the CircleCI bu - `git pull origin master` - Create a new branch from `master`: `git checkout -b bumpDevVersion` - Bump the package.json version, add the tag `-dev` if not already present. + - Update new feature freeze date under `freeze-date` in `.github/workflows/pr-reminder.yml` file - Create and merge PR to `master` diff --git a/releaseDetails.json b/releaseDetails.json new file mode 100644 index 0000000000..18c131baac --- /dev/null +++ b/releaseDetails.json @@ -0,0 +1,10 @@ +{ + "version": "v0.38.0", + "title": "RELEASE HIGHLIGHTS", + "highlight1": "Alpha release for Solidity co-pilot", + "highlight2": "Define Solidity remappings in remappings.txt file", + "highlight3": "Run free function for any selected environment", + "highlight4": "New Circom ZKP templates: Hash Checker & Rate Limiting Nullifier", + "more": "Read More", + "moreLink": "https://medium.com/remix-ide/remix-release-v0-38-0-dccd551b6f1e" + } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 028f8d98ea..e771f4a3e9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, + "resolveJsonModule": true, "experimentalDecorators": true, "importHelpers": true, "target": "ES6", diff --git a/yarn.lock b/yarn.lock index fa79dc15e8..c752eb33d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4715,6 +4715,69 @@ yargs "^17.6.2" yargs-parser "21.1.1" +"@octokit/app@^14.0.2": + version "14.0.2" + resolved "https://registry.yarnpkg.com/@octokit/app/-/app-14.0.2.tgz#b47c52020221351fb58640f113eb38b2ad3998fe" + integrity sha512-NCSCktSx+XmjuSUVn2dLfqQ9WIYePGP95SDJs4I9cn/0ZkeXcPkaoCLl64Us3dRKL2ozC7hArwze5Eu+/qt1tg== + dependencies: + "@octokit/auth-app" "^6.0.0" + "@octokit/auth-unauthenticated" "^5.0.0" + "@octokit/core" "^5.0.0" + "@octokit/oauth-app" "^6.0.0" + "@octokit/plugin-paginate-rest" "^9.0.0" + "@octokit/types" "^12.0.0" + "@octokit/webhooks" "^12.0.4" + +"@octokit/auth-app@^6.0.0": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-6.0.2.tgz#d12b6867e9425ebda07cd3e3c4b5508260b1397f" + integrity sha512-HYuRX3Fvhs2y9i7a4F8f+A5HWfacRWmpERHGBEOtgvKVjJkOQZKUY2v6HiSszYecHAF8Ojqngp2iraSP3SvNpQ== + dependencies: + "@octokit/auth-oauth-app" "^7.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + deprecation "^2.3.1" + lru-cache "^10.0.0" + universal-github-app-jwt "^1.1.1" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-app@^7.0.0": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-7.0.1.tgz#30fd8fcb4608ca52c29c265a3fc7032897796c8e" + integrity sha512-RE0KK0DCjCHXHlQBoubwlLijXEKfhMhKm9gO56xYvFmP1QTMb+vvwRPmQLLx0V+5AvV9N9I3lr1WyTzwL3rMDg== + dependencies: + "@octokit/auth-oauth-device" "^6.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/types" "^12.0.0" + "@types/btoa-lite" "^1.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-device@^6.0.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-6.0.1.tgz#38e5f7f8997c5e8b774f283463ecf4a7e42d7cee" + integrity sha512-yxU0rkL65QkjbqQedgVx3gmW7YM5fF+r5uaSj9tM/cQGVqloXcqP2xK90eTyYvl29arFVCW8Vz4H/t47mL0ELw== + dependencies: + "@octokit/oauth-methods" "^4.0.0" + "@octokit/request" "^8.0.0" + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-user@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-4.0.1.tgz#c8267883935c83f78318c726ff91d7e98de05517" + integrity sha512-N94wWW09d0hleCnrO5wt5MxekatqEJ4zf+1vSe8MKMrhZ7gAXKFOKrDEZW2INltvBWJCyDUELgGRv8gfErH1Iw== + dependencies: + "@octokit/auth-oauth-device" "^6.0.0" + "@octokit/oauth-methods" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/types" "^12.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + "@octokit/auth-token@^2.4.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" @@ -4722,6 +4785,32 @@ dependencies: "@octokit/types" "^6.0.3" +"@octokit/auth-token@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" + integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== + +"@octokit/auth-unauthenticated@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-unauthenticated/-/auth-unauthenticated-5.0.1.tgz#d8032211728333068b2e07b53997c29e59a03507" + integrity sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg== + dependencies: + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + +"@octokit/core@^5.0.0": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.0.2.tgz#ae7c5d61fdd98ba348a27c3cc510879a130b1234" + integrity sha512-cZUy1gUvd4vttMic7C0lwPed8IYXWYp8kHIMatyhY8t8n3Cpw2ILczkV5pGMPqef7v0bLo0pOHrEHarsau2Ydg== + dependencies: + "@octokit/auth-token" "^4.0.0" + "@octokit/graphql" "^7.0.0" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + "@octokit/endpoint@^6.0.1": version "6.0.12" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" @@ -4731,16 +4820,73 @@ is-plain-object "^5.0.0" universal-user-agent "^6.0.0" +"@octokit/endpoint@^9.0.0": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.4.tgz#8afda5ad1ffc3073d08f2b450964c610b821d1ea" + integrity sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw== + dependencies: + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^7.0.0": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-7.0.2.tgz#3df14b9968192f9060d94ed9e3aa9780a76e7f99" + integrity sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q== + dependencies: + "@octokit/request" "^8.0.1" + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + +"@octokit/oauth-app@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@octokit/oauth-app/-/oauth-app-6.0.0.tgz#a5c3b7794df4280c6aadbadd843119059d70a2c4" + integrity sha512-bNMkS+vJ6oz2hCyraT9ZfTpAQ8dZNqJJQVNaKjPLx4ue5RZiFdU1YWXguOPR8AaSHS+lKe+lR3abn2siGd+zow== + dependencies: + "@octokit/auth-oauth-app" "^7.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/auth-unauthenticated" "^5.0.0" + "@octokit/core" "^5.0.0" + "@octokit/oauth-authorization-url" "^6.0.2" + "@octokit/oauth-methods" "^4.0.0" + "@types/aws-lambda" "^8.10.83" + universal-user-agent "^6.0.0" + +"@octokit/oauth-authorization-url@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz#cc82ca29cc5e339c9921672f39f2b3f5c8eb6ef2" + integrity sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA== + +"@octokit/oauth-methods@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-4.0.1.tgz#90d22c662387056307778d7e5c4763ff559636c4" + integrity sha512-1NdTGCoBHyD6J0n2WGXg9+yDLZrRNZ0moTEex/LSPr49m530WNKcCfXDghofYptr3st3eTii+EHoG5k/o+vbtw== + dependencies: + "@octokit/oauth-authorization-url" "^6.0.2" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + btoa-lite "^1.0.0" + "@octokit/openapi-types@^11.2.0": version "11.2.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== +"@octokit/openapi-types@^19.1.0": + version "19.1.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-19.1.0.tgz#75ec7e64743870fc73e1ab4bc6ec252ecdd624dc" + integrity sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw== + "@octokit/plugin-enterprise-rest@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw== +"@octokit/plugin-paginate-graphql@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-4.0.0.tgz#b26024fa454039c18b948f13bf754ff86b89e8b9" + integrity sha512-7HcYW5tP7/Z6AETAPU14gp5H5KmCPT3hmJrS/5tO7HIgbwenYmgw4OY9Ma54FDySuxMwD+wsJlxtuGWwuZuItA== + "@octokit/plugin-paginate-rest@^1.1.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz#004170acf8c2be535aba26727867d692f7b488fc" @@ -4748,6 +4894,13 @@ dependencies: "@octokit/types" "^2.0.1" +"@octokit/plugin-paginate-rest@^9.0.0": + version "9.1.5" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.5.tgz#1705bcef4dcde1f4015ee58a63dc61b68648f480" + integrity sha512-WKTQXxK+bu49qzwv4qKbMMRXej1DU2gq017euWyKVudA6MldaSSQuxtz+vGbhxV4CjxpUxjZu6rM2wfc1FiWVg== + dependencies: + "@octokit/types" "^12.4.0" + "@octokit/plugin-request-log@^1.0.0": version "1.0.4" resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" @@ -4761,6 +4914,30 @@ "@octokit/types" "^2.0.1" deprecation "^2.3.1" +"@octokit/plugin-rest-endpoint-methods@^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.2.0.tgz#eeaa4de97a2ae26404dea30ce3e17b11928e027c" + integrity sha512-ePbgBMYtGoRNXDyKGvr9cyHjQ163PbwD0y1MkDJCpkO2YH4OeXX40c4wYHKikHGZcpGPbcRLuy0unPUuafco8Q== + dependencies: + "@octokit/types" "^12.3.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" + integrity sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog== + dependencies: + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + bottleneck "^2.15.3" + +"@octokit/plugin-throttling@^8.0.0": + version "8.1.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-8.1.3.tgz#7fb0e001c0cb9383c6be07740b8ec326ed990f6b" + integrity sha512-pfyqaqpc0EXh5Cn4HX9lWYsZ4gGbjnSmUILeu4u2gnuM50K/wIk9s1Pxt3lVeVwekmITgN/nJdoh43Ka+vye8A== + dependencies: + "@octokit/types" "^12.2.0" + bottleneck "^2.15.3" + "@octokit/request-error@^1.0.2": version "1.2.1" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801" @@ -4779,6 +4956,15 @@ deprecation "^2.0.0" once "^1.4.0" +"@octokit/request-error@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.0.1.tgz#277e3ce3b540b41525e07ba24c5ef5e868a72db9" + integrity sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ== + dependencies: + "@octokit/types" "^12.0.0" + deprecation "^2.0.0" + once "^1.4.0" + "@octokit/request@^5.2.0": version "5.6.2" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" @@ -4791,6 +4977,16 @@ node-fetch "^2.6.1" universal-user-agent "^6.0.0" +"@octokit/request@^8.0.0", "@octokit/request@^8.0.1", "@octokit/request@^8.0.2": + version "8.1.6" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-8.1.6.tgz#a76a859c30421737a3918b40973c2ff369009571" + integrity sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ== + dependencies: + "@octokit/endpoint" "^9.0.0" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + universal-user-agent "^6.0.0" + "@octokit/rest@^16.28.4": version "16.43.2" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.2.tgz#c53426f1e1d1044dee967023e3279c50993dd91b" @@ -4813,6 +5009,13 @@ once "^1.4.0" universal-user-agent "^4.0.0" +"@octokit/types@^12.0.0", "@octokit/types@^12.2.0", "@octokit/types@^12.3.0", "@octokit/types@^12.4.0": + version "12.4.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-12.4.0.tgz#8f97b601e91ce6b9776ed8152217e77a71be7aac" + integrity sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ== + dependencies: + "@octokit/openapi-types" "^19.1.0" + "@octokit/types@^2.0.0", "@octokit/types@^2.0.1": version "2.16.2" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.16.2.tgz#4c5f8da3c6fecf3da1811aef678fda03edac35d2" @@ -4827,6 +5030,26 @@ dependencies: "@octokit/openapi-types" "^11.2.0" +"@octokit/webhooks-methods@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-4.0.0.tgz#d1697930ba3d8e6b6d0f8a2c996bb440d2e1df1b" + integrity sha512-M8mwmTXp+VeolOS/kfRvsDdW+IO0qJ8kYodM/sAysk093q6ApgmBXwK1ZlUvAwXVrp/YVHp6aArj4auAxUAOFw== + +"@octokit/webhooks-types@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks-types/-/webhooks-types-7.1.0.tgz#d533dea253416e02dd6c2bfab25e533295bd5d3f" + integrity sha512-y92CpG4kFFtBBjni8LHoV12IegJ+KFxLgKRengrVjKmGE5XMeCuGvlfRe75lTRrgXaG6XIWJlFpIDTlkoJsU8w== + +"@octokit/webhooks@^12.0.4": + version "12.0.10" + resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-12.0.10.tgz#3dcd3424ae4ff29b62b8fc8408b08c17b8178ece" + integrity sha512-Q8d26l7gZ3L1SSr25NFbbP0B431sovU5r0tIqcvy8Z4PrD1LBv0cJEjvDLOieouzPSTzSzufzRIeXD7S+zAESA== + dependencies: + "@octokit/request-error" "^5.0.0" + "@octokit/webhooks-methods" "^4.0.0" + "@octokit/webhooks-types" "7.1.0" + aggregate-error "^3.1.0" + "@openzeppelin/contracts-upgradeable@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.0.tgz#859c00c55f04b6dda85b3c88bce507d65019888f" @@ -5708,6 +5931,11 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig== +"@types/aws-lambda@^8.10.83": + version "8.10.130" + resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.130.tgz#d4a44201f0e47c8320a5868d845ad654f3b4adc2" + integrity sha512-HxTfLeGvD1wTJqIGwcBCpNmHKenja+We1e0cuzeIDFfbEj3ixnlTInyPR/81zAe0Ss/Ip12rFK6XNeMLVucOSg== + "@types/axios@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46" @@ -5777,6 +6005,11 @@ dependencies: "@types/node" "*" +"@types/btoa-lite@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/btoa-lite/-/btoa-lite-1.0.2.tgz#82bb6aab00abf7cff3ca2825abe010c0cd536ae5" + integrity sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg== + "@types/cacheable-request@^6.0.1": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" @@ -5995,6 +6228,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/jsonwebtoken@^9.0.0": + version "9.0.5" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz#0bd9b841c9e6c5a937c17656e2368f65da025588" + integrity sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA== + dependencies: + "@types/node" "*" + "@types/keyv@*": version "3.1.3" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.3.tgz#1c9aae32872ec1f20dcdaee89a9f3ba88f465e41" @@ -7392,7 +7632,7 @@ agentkeepalive@^4.2.1: depd "^2.0.0" humanize-ms "^1.2.1" -aggregate-error@^3.0.0: +aggregate-error@^3.0.0, aggregate-error@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== @@ -8951,6 +9191,11 @@ before-after-hook@^2.0.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== +before-after-hook@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" + integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== + bfj@^7.0.2: version "7.1.0" resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.1.0.tgz#c5177d522103f9040e1b12980fe8c38cf41d3f8b" @@ -9179,6 +9424,11 @@ borsh@^0.7.0: bs58 "^4.0.0" text-encoding-utf-8 "^1.0.2" +bottleneck@^2.15.3: + version "2.19.5" + resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" + integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== + boxen@5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" @@ -9569,6 +9819,11 @@ buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + buffer-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" @@ -10272,10 +10527,10 @@ circom_runtime@0.1.22: dependencies: ffjavascript "0.2.57" -circom_wasm@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/circom_wasm/-/circom_wasm-0.1.0.tgz#dda76c7ae9046ea6f1e1cd3754c017ad753bd5c1" - integrity sha512-F7ihfVGjfSz+01yFXLHjKocQFm8j9KBageqMw5+olFWB6+7CXHLjnUaFuU6u+7T0FsL7+JuP18jdcAVQEXoQgw== +circom_wasm@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/circom_wasm/-/circom_wasm-0.2.0.tgz#c35537f0b1f5bfd3d88898306f46c3a3457e5589" + integrity sha512-eqDCbAXJQkKnrAg0Ow3bdaGciGTooRKL20941JGzX8IcqgHoGiZxaSLATkYy97dbmJFrxe8Wr+mOGnvdbqN9bw== circular-json@^0.3.0: version "0.3.3" @@ -12458,6 +12713,13 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + editor@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742" @@ -18201,6 +18463,22 @@ jsonpath@^1.1.1: static-eval "2.0.2" underscore "1.12.1" +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + jspdf@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/jspdf/-/jspdf-2.5.1.tgz#00c85250abf5447a05f3b32ab9935ab4a56592cc" @@ -18286,6 +18564,23 @@ just-once@^2.2.0: resolved "https://registry.yarnpkg.com/just-once/-/just-once-2.2.0.tgz#e8ebc8c80838d0fdb0d3c888f1591d88ad4be4d7" integrity sha512-Wo547FgUOUZ98jbrZ1KX8nRezdEdtgIlC2NK1u1RvR1oZ/WoU++FjprP8J8hRbaox776MHyeMZZED4DvhhHVjg== +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + keccak@3.0.2, keccak@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" @@ -18942,6 +19237,11 @@ lodash.get@^4.0.0, lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -18952,16 +19252,41 @@ lodash.isarray@^3.0.0: resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + lodash.isequal@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -18996,6 +19321,11 @@ lodash.omit@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" integrity sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg== +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + lodash.pick@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" @@ -19153,6 +19483,11 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lru-cache@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" + integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + lru-cache@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" @@ -21832,6 +22167,22 @@ octokit-pagination-methods@^1.1.0: resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== +octokit@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/octokit/-/octokit-3.1.2.tgz#e574e4f2f5f8712e10412ce81fb56a74c93d4cfa" + integrity sha512-MG5qmrTL5y8KYwFgE1A4JWmgfQBaIETE/lOlfwNYx1QOtCQHGVxkRJmdUJltFc1HVn73d61TlMhMyNTOtMl+ng== + dependencies: + "@octokit/app" "^14.0.2" + "@octokit/core" "^5.0.0" + "@octokit/oauth-app" "^6.0.0" + "@octokit/plugin-paginate-graphql" "^4.0.0" + "@octokit/plugin-paginate-rest" "^9.0.0" + "@octokit/plugin-rest-endpoint-methods" "^10.0.0" + "@octokit/plugin-retry" "^6.0.0" + "@octokit/plugin-throttling" "^8.0.0" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + on-exit-leak-free@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" @@ -28125,6 +28476,14 @@ unist-util-visit@^4.0.0: unist-util-is "^5.0.0" unist-util-visit-parents "^5.1.1" +universal-github-app-jwt@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.1.tgz#d57cee49020662a95ca750a057e758a1a7190e6e" + integrity sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w== + dependencies: + "@types/jsonwebtoken" "^9.0.0" + jsonwebtoken "^9.0.0" + universal-user-agent@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557"