work
This commit is contained in:
parent
4dd014136a
commit
b844baef81
23
README.md
23
README.md
|
@ -1,16 +1,31 @@
|
|||
# cdadmin
|
||||
|
||||
## Features
|
||||
**cdadmin** is administration app for continuous deployment of static websites.
|
||||
|
||||
**cdadmin** is intended to be used with static websites that are generated after
|
||||
changes are pushed to a Git repository. This works with sites that are being
|
||||
edited in code and tracked in Git, as well as with headless CMSs that are
|
||||
pushing changes via Git.
|
||||
|
||||
cdadmin starts a web server that provides an admin interface as well as an API.
|
||||
|
||||
No authentication is provided, so you'll want to reverse proxy through something
|
||||
that protects the endpoints.
|
||||
|
||||
## Admin
|
||||
|
||||
The main page of the admin show the staging and production rebuild status. It
|
||||
allows the user to queue a rebuild of the staging and production environments.
|
||||
It also allows the user to merge staging into production.
|
||||
|
||||
- Create a webserver that has an API and an admin interface
|
||||
- Passwordless authentication using email, sign-in available for users who are on a list
|
||||
- Handles webhooks that rebuild staging
|
||||
- Gives admin a button to rebuild staging
|
||||
- Gives users feedback on the staging rebuild status
|
||||
- Handles webhooks that rebuild production
|
||||
- Gives admin a button to rebuild production
|
||||
- Gives users feedback on the production rebuild status
|
||||
- Gives users a button to rebase production on staging (did I say that correctly?)
|
||||
- Gives users a button to rebase production on staging (did I say that
|
||||
correctly?)
|
||||
|
||||
## Email
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"node": true,
|
||||
"esversion": 8
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
draft: true
|
||||
---
|
||||
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +0,0 @@
|
|||
baseURL = "http://example.org/"
|
||||
languageCode = "en-us"
|
||||
title = "cdadmin"
|
||||
disableKinds = ["RSS"]
|
||||
|
||||
[permalinks]
|
||||
pages = "/:filename/"
|
|
@ -0,0 +1,77 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>configure cdadmin</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/bootstrap@4.1.0/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>cdadmin</h1>
|
||||
<p>
|
||||
<a href="status.html">Status</a>
|
||||
<a href="merge.html">Merge</a>
|
||||
<a href="configure.html">Configure</a>
|
||||
</p>
|
||||
<h2>Configure</h2>
|
||||
</div>
|
||||
<pre>{{configuration}}</pre>
|
||||
<vue-form-generator
|
||||
:schema="schema"
|
||||
:model="configuration"
|
||||
></vue-form-generator>
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script>
|
||||
<script src="https://unpkg.com/vue-form-generator@2.3.4/dist/vfg.js"></script>
|
||||
<script src="https://unpkg.com/axios@0.20.0/dist/axios.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '.app',
|
||||
components: {
|
||||
'vue-form-generator': VueFormGenerator.component
|
||||
},
|
||||
data: {
|
||||
configuration: {
|
||||
repository: '',
|
||||
production: '',
|
||||
staging: ''
|
||||
},
|
||||
schema: {
|
||||
fields: [
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Repository',
|
||||
model: 'repository',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Production Branch',
|
||||
model: 'production',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Staging Branch',
|
||||
model: 'staging',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
},
|
||||
formOptions: {}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,119 +0,0 @@
|
|||
---
|
||||
title: Sign In
|
||||
type: page
|
||||
---
|
||||
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-box;
|
||||
display: flex;
|
||||
-ms-flex-align: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.app {
|
||||
width: 100%;
|
||||
max-width: 330px;
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.form-signin .checkbox {
|
||||
font-weight: 400;
|
||||
}
|
||||
.form-signin .form-control {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
height: auto;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.form-signin .form-control:focus {
|
||||
z-index: 2;
|
||||
}
|
||||
.form-signin input[type='email'] {
|
||||
margin-bottom: -1px;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
.form-signin input[type='password'] {
|
||||
margin-bottom: 10px;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="app">
|
||||
<form class="form-signin text-center" @submit="submit($event)">
|
||||
<label for="inputEmail" class="sr-only">Email address</label>
|
||||
<input
|
||||
type="email"
|
||||
id="inputEmail"
|
||||
class="form-control"
|
||||
placeholder="Email address"
|
||||
required
|
||||
autofocus
|
||||
v-model="email"
|
||||
/>
|
||||
<br />
|
||||
<button class="btn btn-lg btn-primary btn-block" type="submit">
|
||||
Sign in
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="/axios.js"></script>
|
||||
<script src="/vue.js"></script>
|
||||
<script src="/messages.js"></script>
|
||||
<script>
|
||||
var app = new Vue({
|
||||
data: {
|
||||
email: ''
|
||||
},
|
||||
methods: {
|
||||
submit: function (ev) {
|
||||
var _this = this;
|
||||
if (ev) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
axios
|
||||
.post('/api/authentication/signin', {
|
||||
email: _this.email
|
||||
})
|
||||
.then(function (response) {})
|
||||
.catch(function (error) {
|
||||
console.log(_this.email);
|
||||
window.postMessage('Something went wrong. Please try again.');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
var token = window.localStorage.getItem('token');
|
||||
if (token) {
|
||||
axios
|
||||
.get('/api/authentication/me', {
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + token
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
window.location.href = '/';
|
||||
})
|
||||
.catch(function (error) {
|
||||
window.localStorage.removeItem('token');
|
||||
app.$mount('.app');
|
||||
});
|
||||
} else {
|
||||
app.$mount('.app');
|
||||
}
|
||||
</script>
|
|
@ -1,9 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ .Site.Language.Lang }}">
|
||||
{{ partial "head.html" . }}
|
||||
<body>
|
||||
<!-- prettier-ignore -->
|
||||
{{ block "main" . }}
|
||||
{{ end }}
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
list
|
|
@ -1 +0,0 @@
|
|||
default single
|
|
@ -1 +0,0 @@
|
|||
{{ define "main" }} {{ .Content }} {{ end }}
|
|
@ -1 +0,0 @@
|
|||
<link rel="stylesheet" href="/bootstrap.min.css" />
|
|
@ -1,5 +0,0 @@
|
|||
<header class="header">
|
||||
<div class="container">
|
||||
<h1>cdadmin</h1>
|
||||
</div>
|
||||
</header>
|
|
@ -0,0 +1,97 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>cdadmin</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/bootstrap@4.1.0/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>cdadmin</h1>
|
||||
<p>
|
||||
<a href="status.html">Status</a>
|
||||
<a href="merge.html">Merge</a>
|
||||
<a href="configure.html">Configure</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2>Production</h2>
|
||||
<p>
|
||||
URL: <a href="#">URL</a><br />
|
||||
Status: <br />
|
||||
Branch: <br />
|
||||
Commit:
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-primary">Rebuild</button>
|
||||
</p>
|
||||
</div>
|
||||
<section>
|
||||
<h2>Staging</h2>
|
||||
<p>
|
||||
URL: <a href="#">URL</a><br />
|
||||
Status: <br />
|
||||
Branch: <br />
|
||||
Commit:
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-primary">Rebuild</button>
|
||||
<button class="btn btn-primary">
|
||||
Merge Staging Into Production
|
||||
</button>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script>
|
||||
<script src="https://unpkg.com/vue-form-generator@2.3.4/dist/vfg.js"></script>
|
||||
<script src="https://unpkg.com/axios@0.20.0/dist/axios.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '.app',
|
||||
components: {
|
||||
'vue-form-generator': VueFormGenerator.component
|
||||
},
|
||||
data: {
|
||||
configuration: {
|
||||
repository: '',
|
||||
production: '',
|
||||
staging: ''
|
||||
},
|
||||
schema: {
|
||||
fields: [
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Repository',
|
||||
model: 'repository',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Production Branch',
|
||||
model: 'production',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Staging Branch',
|
||||
model: 'staging',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
},
|
||||
formOptions: {}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "html",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^0.20.0",
|
||||
"bootstrap": "^4.5.2",
|
||||
"vue": "^2.6.12"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
list
|
|
@ -1 +0,0 @@
|
|||
list
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<url>
|
||||
<loc>http://example.org/categories/</loc>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://example.org/</loc>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://example.org/signin/</loc>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>http://example.org/tags/</loc>
|
||||
</url>
|
||||
|
||||
</urlset>
|
|
@ -1 +0,0 @@
|
|||
list
|
1742
html/static/axios.js
1742
html/static/axios.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,14 +0,0 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
var app = new Vue({
|
||||
data: {
|
||||
messages: []
|
||||
}
|
||||
});
|
||||
|
||||
window.cdadmin = window.cdadmin || {};
|
||||
window.cdadmin.pushMessage = function (str) {
|
||||
window.alert(str);
|
||||
};
|
||||
})();
|
11965
html/static/vue.js
11965
html/static/vue.js
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,94 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>cdadmin</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/bootstrap@4.1.0/dist/css/bootstrap.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>cdadmin</h1>
|
||||
<p>
|
||||
<a href="status.html">Status</a>
|
||||
<a href="merge.html">Merge</a>
|
||||
<a href="configure.html">Configure</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<h2>Production</h2>
|
||||
<p>
|
||||
URL: <a href="#">URL</a><br />
|
||||
Status: <br />
|
||||
Branch: <br />
|
||||
Commit:
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-primary">Rebuild</button>
|
||||
</p>
|
||||
</div>
|
||||
<section>
|
||||
<h2>Staging</h2>
|
||||
<p>
|
||||
URL: <a href="#">URL</a><br />
|
||||
Status: <br />
|
||||
Branch: <br />
|
||||
Commit:
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-primary">Rebuild</button>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script>
|
||||
<script src="https://unpkg.com/vue-form-generator@2.3.4/dist/vfg.js"></script>
|
||||
<script src="https://unpkg.com/axios@0.20.0/dist/axios.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '.app',
|
||||
components: {
|
||||
'vue-form-generator': VueFormGenerator.component
|
||||
},
|
||||
data: {
|
||||
configuration: {
|
||||
repository: '',
|
||||
production: '',
|
||||
staging: ''
|
||||
},
|
||||
schema: {
|
||||
fields: [
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Repository',
|
||||
model: 'repository',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Production Branch',
|
||||
model: 'production',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
inputType: 'text',
|
||||
label: 'Staging Branch',
|
||||
model: 'staging',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
},
|
||||
formOptions: {}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
.header {
|
||||
padding: 3rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
.header h2 {
|
||||
font-weight: bold;
|
||||
}
|
||||
.header p {
|
||||
margin: 2rem 0;
|
||||
padding: 0;
|
||||
}
|
||||
.header p a {
|
||||
padding: 0 0.5rem;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"axios": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz",
|
||||
"integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
|
||||
"integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
|
||||
},
|
||||
"vue": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
|
||||
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg=="
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue