├── .husky ├── .gitignore └── pre-commit ├── .tool-versions ├── _img ├── labels.png ├── topics.png └── repolist.png ├── public ├── favicon.png ├── index.html └── global.css ├── Jenkinsfile_k8s ├── src ├── main.js ├── App.svelte ├── PluginLabels.svelte ├── RepoList.svelte └── GithubLabels.svelte ├── graphql ├── getLabels.graphql ├── updateTopics.graphql └── getTopics.graphql ├── .editorconfig ├── Dockerfile ├── .do └── deploy.template.yaml ├── NOTES.md ├── .eslintrc.js ├── Makefile ├── README.md ├── bin └── www ├── labels.yaml ├── package.json ├── .gitignore ├── .eslintignore ├── .dockerignore ├── webpack.config.js ├── scripts └── setupTypeScript.js ├── index.js └── app └── routes.js /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 14.9.0 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run lint 5 | -------------------------------------------------------------------------------- /_img/labels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkins-infra/docker-plugins-self-service/main/_img/labels.png -------------------------------------------------------------------------------- /_img/topics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkins-infra/docker-plugins-self-service/main/_img/topics.png -------------------------------------------------------------------------------- /_img/repolist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkins-infra/docker-plugins-self-service/main/_img/repolist.png -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkins-infra/docker-plugins-self-service/main/public/favicon.png -------------------------------------------------------------------------------- /Jenkinsfile_k8s: -------------------------------------------------------------------------------- 1 | parallelDockerUpdatecli([imageName: 'plugins-self-service', rebuildImageOnPeriodicJob: false]) 2 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | props: { } 6 | }); 7 | 8 | export default app; 9 | -------------------------------------------------------------------------------- /graphql/getLabels.graphql: -------------------------------------------------------------------------------- 1 | query getLabels($owner: String!, $name: String!) { 2 | repository(owner: $owner, name: $name) { 3 | id 4 | labels (first:100) { 5 | nodes { 6 | id 7 | name 8 | color 9 | description 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /graphql/updateTopics.graphql: -------------------------------------------------------------------------------- 1 | mutation($clientMutationId: String!, $repositoryId: ID!, $topicNames: [String!]!) { 2 | updateTopics(input: { 3 | clientMutationId: $clientMutationId, 4 | repositoryId: $repositoryId, 5 | topicNames: $topicNames 6 | }) { 7 | clientMutationId 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /graphql/getTopics.graphql: -------------------------------------------------------------------------------- 1 | query getTopics($owner: String!, $name: String!) { 2 | repository(owner: $owner, name: $name) { 3 | id 4 | repositoryTopics (first:100) { 5 | nodes { 6 | id 7 | topic { 8 | id 9 | name 10 | } 11 | url 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | charset = utf-8 13 | 14 | [Makefile] 15 | indent_style = tab 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14 as build 2 | WORKDIR /home/node 3 | 4 | ENV NODE_ENV=development 5 | COPY package*.json ./ 6 | RUN npm install 7 | COPY . . 8 | RUN npm run build 9 | 10 | FROM node:14 11 | 12 | ENV NODE_ENV=production 13 | USER node 14 | WORKDIR /home/node 15 | RUN mkdir sessions 16 | COPY package*.json ./ 17 | RUN npm install 18 | COPY . . 19 | COPY --from=build /home/node/public/build ./public/build/ 20 | 21 | CMD ["npm","run","start"] 22 | -------------------------------------------------------------------------------- /.do/deploy.template.yaml: -------------------------------------------------------------------------------- 1 | name: plugins-self-service 2 | region: nyc 3 | services: 4 | - dockerfile_path: Dockerfile 5 | envs: 6 | - key: GITHUB_CLIENT_ID 7 | type: SECRET 8 | - key: GITHUB_CLIENT_SECRET 9 | type: SECRET 10 | github: 11 | branch: master 12 | deploy_on_push: true 13 | repo: halkeye/plugins-self-service 14 | http_port: 5000 15 | instance_count: 1 16 | instance_size_slug: basic-xs 17 | name: plugins-self-service 18 | routes: 19 | - path: / 20 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | https://github.com/octokit/graphql.js/issues/61#issuecomment-643392492 2 | https://www.npmjs.com/package/@octokit/graphql#send-a-simple-query 3 | 4 | * App 5 | * -> Has JWT Token? 6 | * -> Show Repos.svelte 7 | * -> Show Welcome Dialog with action button to Redirect to /login 8 | 9 | 10 | * Repos.svelte 11 | * -> Add in button to set common topics 12 | * -> Just a hard coded list 13 | * -> Maybe pull https://plugins.jenkins.io/api/labels 14 | * -> Prefix topics with jenkins-? 15 | * 16 | 17 | https://material-components.github.io/material-components-web-components/demos/top-app-bar-fixed/ maybe? 18 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Plugin Self Service 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserOptions: { 3 | ecmaVersion: 2019, 4 | sourceType: 'module' 5 | }, 6 | extends: [ 7 | 'eslint:recommended', 8 | 'standard' 9 | ], 10 | env: { 11 | es6: true, 12 | browser: true 13 | }, 14 | plugins: [ 15 | 'svelte3', 16 | 'import' 17 | ], 18 | overrides: [ 19 | { 20 | files: ['*.svelte'], 21 | processor: 'svelte3/svelte3', 22 | rules: { 23 | 'import/first': 0, 24 | 'import/no-duplicates': 0, 25 | 'import/no-mutable-exports': 0, 26 | 'import/no-unresolved': 0, 27 | 'no-multiple-empty-lines': 0 28 | } 29 | } 30 | ], 31 | rules: { 32 | semi: ['error', 'always'] 33 | }, 34 | settings: { 35 | // ... 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!make 2 | .DEFAULT_GOAL := build 3 | 4 | ifndef REGISTRY 5 | override REGISTRY = halkeye 6 | endif 7 | NAME := $(shell basename $(CURDIR)) 8 | VERSION := latest 9 | NAME_VERSION := $(NAME):$(VERSION) 10 | TAGNAME := $(REGISTRY)/$(NAME_VERSION) 11 | 12 | .PHONY: build 13 | build: ## Build docker image 14 | docker build -t $(TAGNAME) . 15 | 16 | .PHONY: push 17 | push: ## push to docker hub 18 | docker push $(TAGNAME) 19 | 20 | .PHONY: push 21 | kill: ## kill the running process 22 | docker kill $(NAME) 23 | 24 | .SHELL := /bin/bash 25 | .PHONY: run 26 | run: ## run the docker hub 27 | docker run \ 28 | -it \ 29 | --rm \ 30 | -p 3000:5000 \ 31 | -e GITHUB_CLIENT_ID \ 32 | -e GITHUB_CLIENT_SECRET \ 33 | --name $(NAME) \ 34 | $(TAGNAME) 35 | 36 | .PHONY: help 37 | help: 38 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 39 | -------------------------------------------------------------------------------- /src/App.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | 20 | 21 |
Plugins Self Service
22 | 23 | 24 |
25 | 26 | {#if $hasAny} 27 | 28 | 29 |

Working

30 |
31 | {/if} 32 |
33 |
34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Archived, see https://github.com/jenkins-infra/helpdesk/issues/4175 2 | 3 | # plugins-self-service 4 | 5 | [![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/jenkins-infra/plugins-self-service/tree/master) 6 | 7 | Little app to manage some once in a while tasks for plugin maintainers 8 | 9 | ## Screenshots 10 | 11 | ![Screenshot of first screen - repository list](./_img/repolist.png) 12 | 13 | ![Screenshot of github labels management](./_img/labels.png) 14 | 15 | ![Screenshot of plugin labels management](./_img/topics.png) 16 | 17 | ## Running 18 | 19 | ### Installing 20 | 21 | ```npm install``` 22 | 23 | ### Running 24 | 25 | ``` 26 | export GITHUB_CLIENT_ID= 27 | export GITHUB_CLIENT_SECRET= 28 | npm run start 29 | ``` 30 | 31 | ## Development 32 | 33 | ### Installing 34 | 35 | ```npm install``` 36 | 37 | ### Running 38 | 39 | ``` 40 | export GITHUB_CLIENT_ID= 41 | export GITHUB_CLIENT_SECRET= 42 | npm run dev 43 | ``` 44 | -------------------------------------------------------------------------------- /public/global.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | } 6 | 7 | body { 8 | color: #333; 9 | margin: 0; 10 | padding: 0; 11 | box-sizing: border-box; 12 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; 13 | } 14 | 15 | a { 16 | color: rgb(0,100,200); 17 | text-decoration: none; 18 | } 19 | 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | 24 | a:visited { 25 | color: rgb(0,80,160); 26 | } 27 | 28 | label { 29 | display: block; 30 | } 31 | 32 | input, button, select, textarea { 33 | font-family: inherit; 34 | font-size: inherit; 35 | -webkit-padding: 0.4em 0; 36 | padding: 0.4em; 37 | margin: 0 0 0.5em 0; 38 | box-sizing: border-box; 39 | border: 1px solid #ccc; 40 | border-radius: 2px; 41 | } 42 | 43 | input:disabled { 44 | color: #ccc; 45 | } 46 | 47 | button { 48 | color: #333; 49 | background-color: #f4f4f4; 50 | outline: none; 51 | } 52 | 53 | button:disabled { 54 | color: #999; 55 | } 56 | 57 | button:not(:disabled):active { 58 | background-color: #ddd; 59 | } 60 | 61 | button:focus { 62 | border-color: #666; 63 | } 64 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const app = require('../index'); 8 | const debug = require('debug')('a:server'); 9 | const http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | const port = normalizePort(process.env.PORT || '5000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | const server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort (val) { 37 | const port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError (error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | const bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | case 'EADDRINUSE': 71 | console.error(bind + ' is already in use'); 72 | process.exit(1); 73 | default: 74 | throw error; 75 | } 76 | } 77 | 78 | /** 79 | * Event listener for HTTP server "listening" event. 80 | */ 81 | 82 | function onListening () { 83 | const addr = server.address(); 84 | const bind = typeof addr === 'string' 85 | ? 'pipe ' + addr 86 | : 'port ' + addr.port; 87 | debug('Listening on ' + bind); 88 | } 89 | -------------------------------------------------------------------------------- /labels.yaml: -------------------------------------------------------------------------------- 1 | labels: 2 | - name: good first issue 3 | color: '7057ff' 4 | - name: hackathon 5 | color: '85f920' 6 | - name: help wanted 7 | color: '008672' 8 | - name: question 9 | color: 'D876E3' 10 | - name: wontfix 11 | color: 'FFFFFF' 12 | - name: duplicate 13 | color: 'CFD3D7' 14 | - name: bug 15 | color: 'D73A4A' 16 | - name: documentation 17 | color: '0e8a16' 18 | description: A PR that adds to documentation - used by Release Drafter 19 | - name: hacktoberfest 20 | color: 'bdff3a' 21 | description: 'Hacktoberfest. https://jenkins.io/blog/2018/10/01/hacktoberfest/' 22 | - name: feature 23 | color: '1d00ff' 24 | description: A PR that adds a feature - used by Release Drafter 25 | - name: bugfix 26 | oldname: fix 27 | color: 'c9e85c' 28 | description: A PR that fixes a bug - used by Release Drafter 29 | - name: chore 30 | color: 'c9abea' 31 | description: a PR that adds to maintenance - used by Release Drafter 32 | - name: test 33 | color: 'd6e819' 34 | description: A PR that adds to testing - used by Release Drafter 35 | - name: pinned 36 | color: '5ed5e5' 37 | description: 'Used to avoid stale[bot] marking a issue/PR stale' 38 | - name: plugin-compatibility 39 | color: '8425c4' 40 | - name: stale 41 | color: 'ffffff' 42 | description: 'Used by stale[bot] to mark a issue/PR stale' 43 | - name: skip-changelog 44 | color: 'f44271' 45 | description: A PR that is excluded from Release draft - used by Release Drafter 46 | - name: removed 47 | color: 'aa0f1c' 48 | description: A PR that removes code - used by Release Drafter 49 | - name: deprecated 50 | color: 'e2b626' 51 | description: A PR that deprecates code - used by Release Drafter 52 | - name: breaking 53 | color: '640910' 54 | description: A PR that is a breaking change - used by Release Drafter 55 | - name: dependencies 56 | color: '0366d6' 57 | description: A PR that updates dependencies - used by Release Drafter 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plugins-self-service", 3 | "description": "Plugins Self Service", 4 | "private": true, 5 | "license": "MIT", 6 | "version": "1.0.0", 7 | "scripts": { 8 | "build": "webpack-cli", 9 | "dev": "nodemon -w index.js -w graphql -w app -e js,mjs,json,graphql ./bin/www", 10 | "start": "node ./bin/www", 11 | "lint": "eslint --cache ." 12 | }, 13 | "devDependencies": { 14 | "autoprefixer": "^10.2.4", 15 | "babel-loader": "^8.2.2", 16 | "clean-webpack-plugin": "^3.0.0", 17 | "css-loader": "^5.0.2", 18 | "eslint": "^7.21.0", 19 | "eslint-config-standard": "^16.0.2", 20 | "eslint-plugin-import": "^2.22.1", 21 | "eslint-plugin-node": "^11.1.0", 22 | "eslint-plugin-promise": "^4.3.1", 23 | "eslint-plugin-svelte3": "^3.1.2", 24 | "husky": "^4.3.8", 25 | "lint-staged": "^10.5.4", 26 | "mini-css-extract-plugin": "^1.3.8", 27 | "nodemon": "^2.0.7", 28 | "postcss-loader": "^5.0.0", 29 | "svelte": "^3.0.0", 30 | "svelte-loader": "^3.0.0", 31 | "svelte-preprocess": "^4.6.9", 32 | "webpack": "^5.23.0", 33 | "webpack-cli": "^4.5.0", 34 | "webpack-dev-middleware": "^4.1.0" 35 | }, 36 | "dependencies": { 37 | "@material/mwc-button": "^0.20.0", 38 | "@material/mwc-circular-progress": "^0.20.0", 39 | "@material/mwc-dialog": "^0.20.0", 40 | "@material/mwc-icon-button": "^0.20.0", 41 | "@material/mwc-list": "^0.20.0", 42 | "@material/mwc-snackbar": "^0.20.0", 43 | "@material/mwc-top-app-bar": "^0.20.0", 44 | "@octokit/graphql": "^4.6.0", 45 | "@webcomponents/webcomponentsjs": "^2.5.0", 46 | "cookie-parser": "^1.4.5", 47 | "cors": "^2.8.5", 48 | "express": "^4.17.1", 49 | "express-session": "^1.17.1", 50 | "js-yaml": "^4.0.0", 51 | "morgan": "^1.10.0", 52 | "node-fetch": "^2.6.1", 53 | "passport": "^0.4.1", 54 | "passport-github2": "^0.1.12", 55 | "session-file-store": "^1.5.0", 56 | "svelte-fetch": "^0.2.0", 57 | "uuid": "^8.3.2" 58 | }, 59 | "husky": { 60 | "hooks": { 61 | "pre-commit": "lint-staged" 62 | } 63 | }, 64 | "lint-staged": { 65 | "*.js": "eslint --cache --fix" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/PluginLabels.svelte: -------------------------------------------------------------------------------- 1 | 49 | 50 | 55 | 56 |
57 | 58 | {#await fetchTopics(owner, name)} 59 |

...grabbing a list labels for {name}

60 | {:then} 61 | 62 | {#each possibleTopics as topic} 63 | 64 | {topic.id} 65 | {#if topic.title} 66 | {topic.title} 67 | {/if} 68 | 69 | {/each} 70 | 71 | {:catch error} 72 |

An error occurred!

73 |
74 |         
75 |           {error}
76 |         
77 |       
78 | {/await} 79 | Apply 80 | Cancel 81 |
82 |
83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/node 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional stylelint cache 62 | .stylelintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variables file 80 | .env 81 | .env.test 82 | .env*.local 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | .parcel-cache 87 | 88 | # Next.js build output 89 | .next 90 | 91 | # Nuxt.js build / generate output 92 | .nuxt 93 | dist 94 | 95 | # Gatsby files 96 | .cache/ 97 | # Comment in the public line in if your project uses Gatsby and not Next.js 98 | # https://nextjs.org/blog/next-9-1#public-directory-support 99 | # public 100 | 101 | # vuepress build output 102 | .vuepress/dist 103 | 104 | # Serverless directories 105 | .serverless/ 106 | 107 | # FuseBox cache 108 | .fusebox/ 109 | 110 | # DynamoDB Local files 111 | .dynamodb/ 112 | 113 | # TernJS port file 114 | .tern-port 115 | 116 | # Stores VSCode versions used for testing VSCode extensions 117 | .vscode-test 118 | 119 | # End of https://www.toptal.com/developers/gitignore/api/node 120 | sessions/ 121 | public/build/ 122 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/node 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional stylelint cache 62 | .stylelintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variables file 80 | .env 81 | .env.test 82 | .env*.local 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | .parcel-cache 87 | 88 | # Next.js build output 89 | .next 90 | 91 | # Nuxt.js build / generate output 92 | .nuxt 93 | dist 94 | 95 | # Gatsby files 96 | .cache/ 97 | # Comment in the public line in if your project uses Gatsby and not Next.js 98 | # https://nextjs.org/blog/next-9-1#public-directory-support 99 | # public 100 | 101 | # vuepress build output 102 | .vuepress/dist 103 | 104 | # Serverless directories 105 | .serverless/ 106 | 107 | # FuseBox cache 108 | .fusebox/ 109 | 110 | # DynamoDB Local files 111 | .dynamodb/ 112 | 113 | # TernJS port file 114 | .tern-port 115 | 116 | # Stores VSCode versions used for testing VSCode extensions 117 | .vscode-test 118 | 119 | # End of https://www.toptal.com/developers/gitignore/api/node 120 | sessions/ 121 | public/build/ 122 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/node 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=node 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional stylelint cache 62 | .stylelintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variables file 80 | .env 81 | .env.test 82 | .env*.local 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | .parcel-cache 87 | 88 | # Next.js build output 89 | .next 90 | 91 | # Nuxt.js build / generate output 92 | .nuxt 93 | dist 94 | 95 | # Gatsby files 96 | .cache/ 97 | # Comment in the public line in if your project uses Gatsby and not Next.js 98 | # https://nextjs.org/blog/next-9-1#public-directory-support 99 | # public 100 | 101 | # vuepress build output 102 | .vuepress/dist 103 | 104 | # Serverless directories 105 | .serverless/ 106 | 107 | # FuseBox cache 108 | .fusebox/ 109 | 110 | # DynamoDB Local files 111 | .dynamodb/ 112 | 113 | # TernJS port file 114 | .tern-port 115 | 116 | # Stores VSCode versions used for testing VSCode extensions 117 | .vscode-test 118 | 119 | # End of https://www.toptal.com/developers/gitignore/api/node 120 | sessions/ 121 | Dockerfile 122 | .git 123 | public/build/ 124 | -------------------------------------------------------------------------------- /src/RepoList.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | 29 | 30 | 31 | 57 | 58 |
59 | {#await fetchRepos()} 60 |

...grabbing a list of plugins you have admin on

61 | {:then repos} 62 | {#each repos as repo} 63 |
64 | 65 |
66 |
67 |
68 | {/each} 69 | {#if selected && selected.type === 'githubLabels'} 70 | 71 | {/if} 72 | {#if selected && selected.type === 'pluginLabels'} 73 | 74 | {/if} 75 | {:catch error} 76 |

An error occurred!

77 |
78 |         
79 |           {error}
80 |         
81 |       
82 | {/await} 83 |
84 | 85 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // https://github.com/baileyherbert/svelte-webpack-starter/blob/master/webpack.config.ts 2 | const SveltePreprocess = require('svelte-preprocess'); 3 | const Autoprefixer = require('autoprefixer'); 4 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 5 | const path = require('path'); 6 | 7 | const mode = process.env.NODE_ENV || 'development'; 8 | const isProduction = mode === 'production'; 9 | const isDevelopment = !isProduction; 10 | const sourceMapsInProduction = true; 11 | 12 | module.exports = { 13 | entry: { 14 | bundle: ['./src/main.js'] 15 | }, 16 | mode: isProduction ? 'production' : 'development', 17 | output: { 18 | path: path.resolve(__dirname, 'public/build'), 19 | publicPath: '/build/', 20 | filename: '[name].js', 21 | chunkFilename: '[name].[id].js' 22 | }, 23 | resolve: { 24 | extensions: ['.mjs', '.js', '.ts', '.svelte'], 25 | mainFields: ['svelte', 'browser', 'module', 'main'] 26 | }, 27 | module: { 28 | rules: [ 29 | // Rule: Svelte 30 | { 31 | test: /\.svelte$/, 32 | use: { 33 | loader: 'svelte-loader', 34 | options: { 35 | compilerOptions: { 36 | // Dev mode must be enabled for HMR to work! 37 | dev: isDevelopment 38 | }, 39 | emitCss: isProduction, 40 | hotReload: isDevelopment, 41 | hotOptions: { 42 | // List of options and defaults: https://www.npmjs.com/package/svelte-loader-hot#usage 43 | noPreserveState: false, 44 | optimistic: true 45 | }, 46 | preprocess: SveltePreprocess({ 47 | scss: false, 48 | sass: false, 49 | postcss: { 50 | plugins: [ 51 | Autoprefixer 52 | ] 53 | } 54 | }) 55 | } 56 | } 57 | }, 58 | // Rule: CSS 59 | { 60 | test: /\.css$/, 61 | use: [ 62 | { 63 | loader: MiniCssExtractPlugin.loader 64 | }, 65 | 'css-loader' 66 | ] 67 | }, 68 | 69 | // Rule: TypeScript 70 | { 71 | test: /\.ts$/, 72 | use: 'ts-loader', 73 | exclude: /node_modules/ 74 | } 75 | ] 76 | }, 77 | devServer: { 78 | hot: true, 79 | stats: 'none', 80 | contentBase: 'public', 81 | watchContentBase: true 82 | }, 83 | target: isDevelopment ? 'web' : 'browserslist', 84 | plugins: [ 85 | new MiniCssExtractPlugin({ 86 | filename: '[name].css' 87 | }) 88 | ], 89 | devtool: isProduction && !sourceMapsInProduction ? false : 'source-map', 90 | stats: { 91 | chunks: false, 92 | chunkModules: false, 93 | modules: false, 94 | assets: true, 95 | entrypoints: false 96 | } 97 | }; 98 | -------------------------------------------------------------------------------- /src/GithubLabels.svelte: -------------------------------------------------------------------------------- 1 | 29 | 30 | 46 | 47 |
48 | 49 | {#await fetchLabels(owner, name)} 50 |

...grabbing a list labels for {name}

51 | {:then labels} 52 | 53 | {#each Object.keys(labels.newLabels).sort() as label} 54 | 55 | 68 | 71 | 80 | 81 | {/each} 82 |
56 | 57 | 58 | {#if labels.existingLabels[label]} 59 | {labels.existingLabels[label].name || ''} 60 | {labels.existingLabels[label].description || ''} 61 | {#if labels.existingLabels[label].color} 62 | info 63 | {/if} 64 | {/if} 65 | 66 | 67 | 69 | double_arrow 70 | 72 | 73 | 74 | {labels.newLabels[label].name || ''} 75 | {labels.newLabels[label].description || ''} 76 | info 77 | 78 | 79 |
83 | {:catch error} 84 |

An error occurred!

85 |
86 |         
87 |           {error}
88 |         
89 |       
90 | {/await} 91 | Apply 92 | Cancel 93 |
94 |
95 | -------------------------------------------------------------------------------- /scripts/setupTypeScript.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** This script modifies the project to support TS code in .svelte files like: 4 | 5 | 8 | 9 | As well as validating the code for CI. 10 | */ 11 | 12 | /** To work on this script: 13 | rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template 14 | */ 15 | 16 | const fs = require('fs'); 17 | const path = require('path'); 18 | const { argv } = require('process'); 19 | 20 | const projectRoot = argv[2] || path.join(__dirname, '..'); 21 | 22 | // Add deps to pkg.json 23 | const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8')); 24 | packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { 25 | 'svelte-check': '^1.0.0', 26 | 'svelte-preprocess': '^4.0.0', 27 | '@rollup/plugin-typescript': '^8.0.0', 28 | typescript: '^4.0.0', 29 | tslib: '^2.0.0', 30 | '@tsconfig/svelte': '^1.0.0' 31 | }); 32 | 33 | // Add script for checking 34 | packageJSON.scripts = Object.assign(packageJSON.scripts, { 35 | validate: 'svelte-check' 36 | }); 37 | 38 | // Write the package JSON 39 | fs.writeFileSync(path.join(projectRoot, 'package.json'), JSON.stringify(packageJSON, null, ' ')); 40 | 41 | // mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too 42 | const beforeMainJSPath = path.join(projectRoot, 'src', 'main.js'); 43 | const afterMainTSPath = path.join(projectRoot, 'src', 'main.ts'); 44 | fs.renameSync(beforeMainJSPath, afterMainTSPath); 45 | 46 | // Switch the app.svelte file to use TS 47 | const appSveltePath = path.join(projectRoot, 'src', 'App.svelte'); 48 | let appFile = fs.readFileSync(appSveltePath, 'utf8'); 49 | appFile = appFile.replace('