├── .github ├── dependabot.yml └── workflows │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── bin.js ├── index.js ├── package-lock.json └── package.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | groups: 8 | production-dependencies: 9 | dependency-type: "production" 10 | update-types: 11 | - "minor" 12 | - "patch" 13 | development-dependencies: 14 | dependency-type: "development" 15 | update-types: 16 | - "minor" 17 | - "patch" -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: NPM Publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | with: 12 | ref: ${{ github.event.release.target_commitish }} 13 | - name: Use Node.js 12 14 | uses: actions/setup-node@v1 15 | with: 16 | node-version: 12 17 | registry-url: https://registry.npmjs.org/ 18 | - run: npm ci 19 | - run: git config --global user.name "Michael Heap" 20 | - run: git config --global user.email "m@michaelheap.com" 21 | - run: npm version ${{ github.event.release.tag_name }} 22 | - run: npm run build --if-present 23 | - run: npm test --if-present 24 | - run: npm publish 25 | env: 26 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 27 | - run: git push 28 | env: 29 | github-token: ${{ secrets.GITHUB_TOKEN }} 30 | - run: git tag -f ${{ github.event.release.tag_name }} ${{ github.event.release.target_commitish }} 31 | env: 32 | github-token: ${{ secrets.GITHUB_TOKEN }} 33 | - run: git push origin ${{ github.event.release.tag_name }} --force 34 | env: 35 | github-token: ${{ secrets.GITHUB_TOKEN }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License Copyright (c) 2020 Michael Heap 2 | 3 | Permission is hereby granted, free 4 | of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, copy, modify, merge, 7 | publish, distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to the 9 | following conditions: 10 | 11 | The above copyright notice and this permission notice 12 | (including the next paragraph) shall be included in all copies or substantial 13 | portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 18 | EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # github-update-secret 2 | 3 | This CLI tool allows you to update the value of a GitHub Secret on multiple repositories at once. This is useful if you're using a `user` account and not an `org`, as users do not have the concept of user level secrets 4 | 5 | ## How it works 6 | 7 | - Fetch a list of all repos to which the authenticated user has admin access for the provided user/org 8 | - Fetch the list of secrets on each repository 9 | - For each repository that has a secret named the same as the provided `SECRET_NAME`, update the value of that secret 10 | - Check if the provided target is an organisation. 11 | - If so: 12 | - Check if there is an org secret named `SECRET_NAME` 13 | - If there is, update the value 14 | 15 | ## Usage 16 | 17 | ``` 18 | DEBUG=github-update-secret npx github-update-secret 19 | ``` 20 | 21 | Any repos that you do not have `admin` access to will be skipped, as will `forks`, `templates` and `archived` repos. 22 | -------------------------------------------------------------------------------- /bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const yargs = require("yargs/yargs"); 4 | const { hideBin } = require("yargs/helpers"); 5 | 6 | const argv = yargs(hideBin(process.argv)) 7 | .option("pat", { 8 | type: "string", 9 | description: 10 | "GitHub Personal Access Token. Required if GITHUB_TOKEN env variable is not set", 11 | }) 12 | .command( 13 | "$0 ", 14 | "Update a secret in all repositories that use it", 15 | (yargs) => { 16 | yargs 17 | .positional("target", { 18 | describe: "The user, org or team to update", 19 | }) 20 | .positional("name", { 21 | describe: "The name of the secret to update", 22 | }) 23 | .positional("value", { 24 | describe: "The new value for the secret", 25 | }); 26 | }, 27 | async (argv) => { 28 | await require(".")(argv); 29 | } 30 | ) 31 | .demandOption(["target", "name", "value"]).argv; 32 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | let { Octokit } = require("@octokit/rest"); 2 | Octokit = Octokit.plugin(require("octokit-fetch-all-repos")); 3 | 4 | const sodium = require("tweetsodium"); 5 | const debug = require("debug")("github-update-secret"); 6 | 7 | module.exports = async function (argv) { 8 | const { target, value } = argv; 9 | const name = argv.name.toLowerCase(); 10 | 11 | // Fetch list of repos 12 | const token = argv.pat || process.env.GITHUB_TOKEN; 13 | 14 | const octokit = new Octokit({ 15 | auth: token, 16 | }); 17 | 18 | // List all repos 19 | debug("Fetching repo list"); 20 | let repos = await octokit.repos.fetchAll({ 21 | owner: target, 22 | visibility: "all", 23 | minimum_access: "admin", 24 | include_forks: false, 25 | include_archived: false, 26 | include_templates: false, 27 | }); 28 | 29 | // Reformat into the format we need 30 | repos = repos.map((r) => { 31 | return { 32 | repo: r.name, 33 | owner: r.owner.login, 34 | }; 35 | }); 36 | debug("Processed repo list"); 37 | 38 | // Filter down to repos that have the secret that we're looking for 39 | debug(`Building list of repos using [${name}]`); 40 | const reposWithSecret = await repos.reduce(async (acc, { owner, repo }) => { 41 | const { data: secrets } = await octokit.actions.listRepoSecrets({ 42 | owner, 43 | repo, 44 | }); 45 | 46 | const matching = secrets.secrets.filter((s) => { 47 | return s.name.toLowerCase() === name; 48 | }); 49 | 50 | if (matching.length === 0) { 51 | return acc; 52 | } 53 | 54 | return (await acc).concat({ owner, repo }); 55 | }, []); 56 | debug(`Found [${reposWithSecret.length}] repos with the secret [${name}]`); 57 | 58 | // For each repo that does have the secret, update it 59 | for (let { owner, repo } of reposWithSecret) { 60 | debug(`Updating ${repo}`); 61 | const key = await getKeyForRepo(octokit, owner, repo); 62 | const encrypted_value = encrypt(key.key, value); 63 | 64 | await octokit.actions.createOrUpdateRepoSecret({ 65 | owner, 66 | repo, 67 | secret_name: name, 68 | encrypted_value, 69 | key_id: key.key_id, 70 | }); 71 | debug(`Updated ${repo}`); 72 | } 73 | 74 | // If this is an org, we need to check org secrets too 75 | debug("Check if provided user is an org"); 76 | const { 77 | data: { type: owner_type }, 78 | } = await octokit.users.getByUsername({ 79 | username: target, 80 | }); 81 | 82 | if (owner_type !== "Organization") { 83 | debug("User is not an org. Skipping org secret update"); 84 | return; 85 | } 86 | 87 | try { 88 | // Does the org have this secret? Octokit will throw if not 89 | debug("Secret exists?"); 90 | const { data: secret } = await octokit.actions.getOrgSecret({ 91 | org: target, 92 | secret_name: name, 93 | }); 94 | 95 | debug("Fetch org public key"); 96 | const { data: key } = await octokit.actions.getOrgPublicKey({ 97 | org: target, 98 | }); 99 | 100 | const encrypted_value = encrypt(key.key, value); 101 | 102 | debug("Update org secret"); 103 | await octokit.actions.createOrUpdateOrgSecret({ 104 | org: target, 105 | secret_name: name, 106 | encrypted_value, 107 | key_id: key.key_id, 108 | visibility: secret.visibility, 109 | }); 110 | debug("Org secret updated"); 111 | } catch (e) { 112 | // The secret doesn't exist on the org 113 | if (e.status !== 404) { 114 | throw e; 115 | } 116 | debug("Org secret does not exist"); 117 | } 118 | }; 119 | 120 | async function getKeyForRepo(octokit, owner, repo) { 121 | const { data: key } = await octokit.actions.getRepoPublicKey({ 122 | owner, 123 | repo, 124 | }); 125 | 126 | return key; 127 | } 128 | 129 | function encrypt(key, value) { 130 | // Convert the message and key to Uint8Array's (Buffer implements that interface) 131 | const messageBytes = Buffer.from(value); 132 | const keyBytes = Buffer.from(key, "base64"); 133 | 134 | // Encrypt using LibSodium. 135 | const encryptedBytes = sodium.seal(messageBytes, keyBytes); 136 | 137 | // Base64 the encrypted secret 138 | return Buffer.from(encryptedBytes).toString("base64"); 139 | } 140 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-update-secret", 3 | "version": "1.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@octokit/auth-token": { 8 | "version": "2.4.5", 9 | "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.5.tgz", 10 | "integrity": "sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==", 11 | "requires": { 12 | "@octokit/types": "^6.0.3" 13 | } 14 | }, 15 | "@octokit/core": { 16 | "version": "3.2.5", 17 | "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.2.5.tgz", 18 | "integrity": "sha512-+DCtPykGnvXKWWQI0E1XD+CCeWSBhB6kwItXqfFmNBlIlhczuDPbg+P6BtLnVBaRJDAjv+1mrUJuRsFSjktopg==", 19 | "requires": { 20 | "@octokit/auth-token": "^2.4.4", 21 | "@octokit/graphql": "^4.5.8", 22 | "@octokit/request": "^5.4.12", 23 | "@octokit/types": "^6.0.3", 24 | "before-after-hook": "^2.1.0", 25 | "universal-user-agent": "^6.0.0" 26 | } 27 | }, 28 | "@octokit/endpoint": { 29 | "version": "6.0.11", 30 | "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", 31 | "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", 32 | "requires": { 33 | "@octokit/types": "^6.0.3", 34 | "is-plain-object": "^5.0.0", 35 | "universal-user-agent": "^6.0.0" 36 | } 37 | }, 38 | "@octokit/graphql": { 39 | "version": "4.6.0", 40 | "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.0.tgz", 41 | "integrity": "sha512-CJ6n7izLFXLvPZaWzCQDjU/RP+vHiZmWdOunaCS87v+2jxMsW9FB5ktfIxybRBxZjxuJGRnxk7xJecWTVxFUYQ==", 42 | "requires": { 43 | "@octokit/request": "^5.3.0", 44 | "@octokit/types": "^6.0.3", 45 | "universal-user-agent": "^6.0.0" 46 | } 47 | }, 48 | "@octokit/openapi-types": { 49 | "version": "5.3.1", 50 | "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.3.1.tgz", 51 | "integrity": "sha512-TvVk2QuIA0lQZcIMd6xbdGaGDVeNYIOa3l1ZVagAIk5K3t/WMYbcg4BISNDhzdVhm/TgQB26frAgd/GV81aHJA==" 52 | }, 53 | "@octokit/plugin-paginate-rest": { 54 | "version": "2.11.0", 55 | "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.11.0.tgz", 56 | "integrity": "sha512-7L9xQank2G3r1dGqrVPo1z62V5utbykOUzlmNHPz87Pww/JpZQ9KyG5CHtUzgmB4n5iDRKYNK/86A8D98HP0yA==", 57 | "requires": { 58 | "@octokit/types": "^6.11.0" 59 | } 60 | }, 61 | "@octokit/plugin-request-log": { 62 | "version": "1.0.3", 63 | "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", 64 | "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==" 65 | }, 66 | "@octokit/plugin-rest-endpoint-methods": { 67 | "version": "4.13.4", 68 | "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.4.tgz", 69 | "integrity": "sha512-MGxptzVfiP8O+aydC/riheYzS/yJ9P16M29OuvtZep/sF5sKuOCQP8Wf83YCKXRsQF+ZpYfke2snbPPSIMZKzg==", 70 | "requires": { 71 | "@octokit/types": "^6.12.0", 72 | "deprecation": "^2.3.1" 73 | } 74 | }, 75 | "@octokit/request": { 76 | "version": "5.4.14", 77 | "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.14.tgz", 78 | "integrity": "sha512-VkmtacOIQp9daSnBmDI92xNIeLuSRDOIuplp/CJomkvzt7M18NXgG044Cx/LFKLgjKt9T2tZR6AtJayba9GTSA==", 79 | "requires": { 80 | "@octokit/endpoint": "^6.0.1", 81 | "@octokit/request-error": "^2.0.0", 82 | "@octokit/types": "^6.7.1", 83 | "deprecation": "^2.0.0", 84 | "is-plain-object": "^5.0.0", 85 | "node-fetch": "^2.6.1", 86 | "once": "^1.4.0", 87 | "universal-user-agent": "^6.0.0" 88 | } 89 | }, 90 | "@octokit/request-error": { 91 | "version": "2.0.5", 92 | "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", 93 | "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", 94 | "requires": { 95 | "@octokit/types": "^6.0.3", 96 | "deprecation": "^2.0.0", 97 | "once": "^1.4.0" 98 | } 99 | }, 100 | "@octokit/rest": { 101 | "version": "18.3.4", 102 | "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.4.tgz", 103 | "integrity": "sha512-NES0pHbwyFB1D0jrLkdnIXgEmze/gLE0JoSNgfAe4vwD77/qaQGO/lRWNuPPsoBVBjiW6mmA9CU5cYHujJTKQA==", 104 | "requires": { 105 | "@octokit/core": "^3.2.3", 106 | "@octokit/plugin-paginate-rest": "^2.6.2", 107 | "@octokit/plugin-request-log": "^1.0.2", 108 | "@octokit/plugin-rest-endpoint-methods": "4.13.4" 109 | } 110 | }, 111 | "@octokit/types": { 112 | "version": "6.12.0", 113 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.12.0.tgz", 114 | "integrity": "sha512-KwOf16soD7aDEEi/PgNeJlHzjZPfrmmNy+7WezSdrpnqZ7YImBJcNnX9+5RUHt1MnA4h8oISRHTqaZDGsX9DRQ==", 115 | "requires": { 116 | "@octokit/openapi-types": "^5.3.0" 117 | } 118 | }, 119 | "ansi-regex": { 120 | "version": "5.0.0", 121 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 122 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" 123 | }, 124 | "ansi-styles": { 125 | "version": "4.3.0", 126 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 127 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 128 | "requires": { 129 | "color-convert": "^2.0.1" 130 | } 131 | }, 132 | "before-after-hook": { 133 | "version": "2.2.0", 134 | "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.0.tgz", 135 | "integrity": "sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ==" 136 | }, 137 | "blakejs": { 138 | "version": "1.1.0", 139 | "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", 140 | "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" 141 | }, 142 | "cliui": { 143 | "version": "7.0.4", 144 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 145 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 146 | "requires": { 147 | "string-width": "^4.2.0", 148 | "strip-ansi": "^6.0.0", 149 | "wrap-ansi": "^7.0.0" 150 | } 151 | }, 152 | "color-convert": { 153 | "version": "2.0.1", 154 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 155 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 156 | "requires": { 157 | "color-name": "~1.1.4" 158 | } 159 | }, 160 | "color-name": { 161 | "version": "1.1.4", 162 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 163 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 164 | }, 165 | "debug": { 166 | "version": "4.3.1", 167 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 168 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 169 | "requires": { 170 | "ms": "2.1.2" 171 | } 172 | }, 173 | "deprecation": { 174 | "version": "2.3.1", 175 | "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", 176 | "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" 177 | }, 178 | "emoji-regex": { 179 | "version": "8.0.0", 180 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 181 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 182 | }, 183 | "escalade": { 184 | "version": "3.1.1", 185 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 186 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" 187 | }, 188 | "get-caller-file": { 189 | "version": "2.0.5", 190 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 191 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 192 | }, 193 | "is-fullwidth-code-point": { 194 | "version": "3.0.0", 195 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 196 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 197 | }, 198 | "is-plain-object": { 199 | "version": "5.0.0", 200 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", 201 | "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" 202 | }, 203 | "ms": { 204 | "version": "2.1.2", 205 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 206 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 207 | }, 208 | "node-fetch": { 209 | "version": "2.6.1", 210 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 211 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" 212 | }, 213 | "octokit-fetch-all-repos": { 214 | "version": "1.0.6", 215 | "resolved": "https://registry.npmjs.org/octokit-fetch-all-repos/-/octokit-fetch-all-repos-1.0.6.tgz", 216 | "integrity": "sha512-74cKlF3DL0rTubmXfTBtyxJ6/ukY7dzSyXOOvW0YzsvBLIU6bDwamGNJXNV67w3zP5e7+atYfabaeU2uVUv8bw==" 217 | }, 218 | "once": { 219 | "version": "1.4.0", 220 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 221 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 222 | "requires": { 223 | "wrappy": "1" 224 | } 225 | }, 226 | "require-directory": { 227 | "version": "2.1.1", 228 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 229 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 230 | }, 231 | "string-width": { 232 | "version": "4.2.2", 233 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 234 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 235 | "requires": { 236 | "emoji-regex": "^8.0.0", 237 | "is-fullwidth-code-point": "^3.0.0", 238 | "strip-ansi": "^6.0.0" 239 | } 240 | }, 241 | "strip-ansi": { 242 | "version": "6.0.0", 243 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 244 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 245 | "requires": { 246 | "ansi-regex": "^5.0.0" 247 | } 248 | }, 249 | "tweetnacl": { 250 | "version": "1.0.3", 251 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", 252 | "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" 253 | }, 254 | "tweetsodium": { 255 | "version": "0.0.5", 256 | "resolved": "https://registry.npmjs.org/tweetsodium/-/tweetsodium-0.0.5.tgz", 257 | "integrity": "sha512-T3aXZtx7KqQbutTtBfn+P5By3HdBuB1eCoGviIrRJV2sXeToxv2X2cv5RvYqgG26PSnN5m3fYixds22Gkfd11w==", 258 | "requires": { 259 | "blakejs": "^1.1.0", 260 | "tweetnacl": "^1.0.1" 261 | } 262 | }, 263 | "universal-user-agent": { 264 | "version": "6.0.0", 265 | "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", 266 | "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" 267 | }, 268 | "wrap-ansi": { 269 | "version": "7.0.0", 270 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 271 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 272 | "requires": { 273 | "ansi-styles": "^4.0.0", 274 | "string-width": "^4.1.0", 275 | "strip-ansi": "^6.0.0" 276 | } 277 | }, 278 | "wrappy": { 279 | "version": "1.0.2", 280 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 281 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 282 | }, 283 | "y18n": { 284 | "version": "5.0.5", 285 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", 286 | "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==" 287 | }, 288 | "yargs": { 289 | "version": "16.2.0", 290 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 291 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 292 | "requires": { 293 | "cliui": "^7.0.2", 294 | "escalade": "^3.1.1", 295 | "get-caller-file": "^2.0.5", 296 | "require-directory": "^2.1.1", 297 | "string-width": "^4.2.0", 298 | "y18n": "^5.0.5", 299 | "yargs-parser": "^20.2.2" 300 | } 301 | }, 302 | "yargs-parser": { 303 | "version": "20.2.6", 304 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.6.tgz", 305 | "integrity": "sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA==" 306 | } 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-update-secret", 3 | "version": "1.0.1", 4 | "description": "Update a GitHub Secret in all repos + org secrets", 5 | "main": "index.js", 6 | "bin": { 7 | "github-update-secret": "./bin.js" 8 | }, 9 | "scripts": {}, 10 | "keywords": [ 11 | "GitHub", 12 | "Actions", 13 | "Secrets" 14 | ], 15 | "author": "Michael Heap ", 16 | "license": "MIT", 17 | "dependencies": { 18 | "@octokit/rest": "^18.0.12", 19 | "debug": "^4.3.1", 20 | "octokit-fetch-all-repos": "^1.0.4", 21 | "tweetsodium": "^0.0.5", 22 | "yargs": "^16.2.0" 23 | } 24 | } 25 | --------------------------------------------------------------------------------