Skip to content

Commit 50a30cb

Browse files
committed
v0.0.1
1 parent 0b17bc3 commit 50a30cb

File tree

7 files changed

+374
-0
lines changed

7 files changed

+374
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.env
2+
.DS_Store
3+
node_modules

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
11
# netlify-plugin-sitrep
22
A Netlify build plugin to display debug information in dev or staging environments
3+
4+
# Install
5+
6+
Please install this plugin from the Netlify app.
7+
8+
Create an application token and store it as an environment variable called `BUILD_SITREP_TOKEN`
9+
10+
# Configuration
11+
12+
The following `inputs` options are available.
13+
14+
name: `allow_prod`
15+
description: If true, debug data will be injected in the production context.
16+
17+
[[plugins]]
18+
package = "."
19+
[plugins.inputs]
20+
"allow_prod" = "true"

index.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// TODO
2+
// README
3+
4+
// Netlify doesn't expose live vars in the CLI, so we need to
5+
// confgure SITE_ID and BUILD_SITREP_TOKEN locally for development
6+
require('dotenv').config()
7+
let ejs = require('ejs');
8+
9+
const fetch = require('node-fetch');
10+
const {
11+
env: {
12+
// Must be configured by the user as a Netlify environment var
13+
BUILD_SITREP_TOKEN,
14+
// These are provided by Netlify and are read-only
15+
CONTEXT,
16+
SITE_ID,
17+
COMMIT_REF,
18+
DEPLOY_ID,
19+
BUILD_ID
20+
}
21+
} = require('process')
22+
23+
// Configure the required API vars
24+
let authToken = BUILD_SITREP_TOKEN;
25+
let authString = 'Bearer ' + authToken
26+
let baseURL = `https://api.netlify.com/api/v1/sites/${SITE_ID}/snippets`
27+
28+
module.exports = {
29+
onPreBuild: ({ inputs, utils: { build: { failPlugin } } }) => {
30+
// Make sure the token has been set
31+
if (typeof authToken == 'undefined') {
32+
return failPlugin('The BUILD_SITREP_TOKEN environment var has not been set.');
33+
}
34+
35+
// Make sure we don't run in disallowed contexts
36+
console.log('Verfying allowable contexts...');
37+
38+
let allow_prod = inputs.allow_prod;
39+
switch (allow_prod) {
40+
case 'false':
41+
if (CONTEXT == 'production') {
42+
return failPlugin('Production debug is disabled. This can be changed in netlify.toml');
43+
break;
44+
}
45+
case 'true':
46+
console.log('Production debug is enabled. This can be changed in netlify.toml')
47+
break;
48+
}
49+
},
50+
51+
onBuild({ utils: { build: { failPlugin } } }) {
52+
console.log('Building the tag UI...')
53+
54+
let data = {build_id: BUILD_ID, context: CONTEXT, commit_ref: COMMIT_REF, deploy_id: DEPLOY_ID};
55+
let output = ejs.renderFile(__dirname + './templates/template.ejs', data, function(err, data) {
56+
if (err) {
57+
return failPlugin ('Something went wrong when processing the display template.');
58+
}
59+
60+
let renderToBase64 = new Buffer.from(data);
61+
let encodedRender = renderToBase64.toString('base64');
62+
63+
var tagOpen = '<script>' +
64+
'window.onload = function() {' +
65+
'var ifrm = document.createElement(\'iframe\');' +
66+
'ifrm.setAttribute(\'id\', \'ifrm\');' +
67+
'ifrm.setAttribute(\'style\', \'position: fixed; bottom: 0; right: 0; border: 0;\');' +
68+
'document.body.appendChild(ifrm);'
69+
70+
var tagData = 'ifrm.setAttribute(\'src\', \'data:text/html;base64,' + encodedRender + '\');'
71+
var tagEnd = '}' +
72+
'</script>'
73+
74+
global.tagComplete = tagOpen + tagData + tagEnd
75+
console.log('Successfully built the tag UI.')
76+
77+
});
78+
},
79+
80+
async onSuccess({ utils: { build: { failPlugin, failBuild } } }) {
81+
82+
console.log('Here we go...');
83+
84+
try {
85+
86+
console.log('Checking to see if a snippet already exists...');
87+
88+
await fetch(baseURL, { method: 'GET', headers: {'Authorization': authString}})
89+
.then((res) => {
90+
return res.json()
91+
})
92+
93+
.then((json) => {
94+
var findSnippet = json.filter(function(item) {
95+
return item.title == "netlify-build-sitrep";
96+
});
97+
98+
// TODO: this is super sketchy, needs to be addressed
99+
if (findSnippet === undefined || findSnippet.length == 0) {
100+
console.log('Couldn\'t find an existing snippet.');
101+
extendedURL = baseURL;
102+
fetchMethod = 'POST'
103+
} else {
104+
var snippetID = findSnippet[0]['id'];
105+
extendedURL = baseURL + '/' + snippetID;
106+
console.log('Found snippet with id: ' + snippetID);
107+
fetchMethod = 'PUT'
108+
}
109+
})
110+
111+
const { status, statusText } = await fetch(extendedURL, {
112+
method: fetchMethod,
113+
headers: {
114+
'Authorization': authString,
115+
"Content-type": "application/json",
116+
"Accept": "application/json",
117+
"Accept-Charset": "utf-8"
118+
},
119+
body: JSON.stringify({
120+
title: "netlify-build-sitrep",
121+
general: tagComplete,
122+
general_position: "body",
123+
})
124+
})
125+
126+
if (status == 201) {
127+
console.log('Snippet was added.');
128+
} else if (status == 200) {
129+
console.log('Snippet was updated.');
130+
} else {
131+
return failPlugin('Something went wrong. Netlify said: ' + status + statusText);
132+
}
133+
}
134+
catch (error) {
135+
return failBuild('Something catastrophic happened.', { error })
136+
}
137+
}
138+
}

manifest.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name: 'netlify-plugin-sitrep'
2+
inputs:
3+
- name: allow_prod
4+
description: If true, debug data will be injected in the production context.
5+
required: true
6+
default: false

package-lock.json

Lines changed: 127 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "netlify-plugin-sitrep",
3+
"version": "0.0.1",
4+
"description": "A Netlify build plugin to display debug information in dev or staging environments",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/quarva/netlify-plugin-sitrep.git"
12+
},
13+
"keywords": [
14+
"netlify-plugin",
15+
"netlify",
16+
"netlify-build-plugin",
17+
"netlify-plugins"
18+
],
19+
"author": "Quarva <[email protected]> (https://www.quarva.com/",
20+
"contributors": [
21+
"Shane Cole <[email protected]> (https://www.shanecole.com/)"
22+
],
23+
"license": "MIT",
24+
"bugs": {
25+
"url": "https://github.com/quarva/netlify-plugin-sitrep/issues"
26+
},
27+
"homepage": "https://github.com/quarva/netlify-plugin-sitrep#readme",
28+
"devDependencies": {
29+
"dotenv": "^8.2.0"
30+
},
31+
"dependencies": {
32+
"ejs": "^3.1.5",
33+
"node-fetch": "^2.6.1"
34+
}
35+
}

templates/template.ejs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<style type="text/css">
2+
#ppid {
3+
position: absolute;
4+
bottom: 10px;
5+
right: 10px;
6+
font-size: 12px;
7+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
8+
}
9+
a#togglePPID {
10+
display: block;
11+
float: left;
12+
width: 25px;
13+
height: 25px;
14+
background-size: cover;
15+
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTQycHgiIGhlaWdodD0iMTQycHgiIHZpZXdCb3g9IjAgMCAxNDIgMTQyIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPHRpdGxlPkdyb3VwPC90aXRsZT4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJHcm91cCI+CiAgICAgICAgICAgIDxjaXJjbGUgaWQ9Ik92YWwiIGZpbGw9IiM5MDEzRkUiIGN4PSI3MSIgY3k9IjcxIiByPSI3MSI+PC9jaXJjbGU+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik03MS4xMTIzNTk2LDE3IEM0MS4zMTgwNzkyLDE3IDE3LjExMjM1OTYsNDEuMjA1NDYzMiAxNy4xMTIzNTk2LDcxIEMxNy4xMTIzNTk2LDEwMC42MzkyMjggNDEuMDcxMzkwMSwxMjQuNzQ5NzIxIDcwLjY1MjEzMjMsMTI1IEM3Mi42ODUwOTM2LDEyNSA3My41NjY5MDUsMTI0LjA1MjcxNSA3My41NjY5MDUsMTIyLjI3Njk4OSBDNzMuNTg5ODE4MiwxMDYuNDQzNTY1IDczLjU2Nzc2OSw4OS4xNzk2NTk2IDczLjU2NjkwNSw3NS4yMTg3NSBDNzUuMDIxNDUwMiw3NC4zNjAyNDk0IDc2LjAyMTQ1MDUsNzIuNzg4MTM2NCA3Ni4wMjE0NTA1LDcxIEM3Ni4wMjE0NTA1LDY4LjMxNzc5NTUgNzMuNzk0NjA1OCw2Ni4wOTA5MDkxIDcxLjExMjM1OTYsNjYuMDkwOTA5MSBDNjguNDMwMTEzMyw2Ni4wOTA5MDkxIDY2LjIwMzI2ODYsNjguMzE3Nzk1NSA2Ni4yMDMyNjg2LDcxIEM2Ni4yMDMyNjg2LDcyLjc4ODEzNjQgNjcuMjAzMjY4OSw3NC4zNjAyNDk0IDY4LjY1NzgxNDEsNzUuMjE4NzUgTDY4LjY1NzgxNDEsOTAuNDgyOTU0NSBDNTguOTYxMjA1OSw4OS4yNzA2NjMxIDUxLjQ3NTk5NTksODEuMDM0MTE0MyA1MS40NzU5OTU5LDcxIEM1MS40NzU5OTU5LDYwLjEyNjE1NSA2MC4yMzg0Mjk5LDUxLjM2MzYzNjQgNzEuMTEyMzU5Niw1MS4zNjM2MzY0IEM4MS45ODYyODkyLDUxLjM2MzYzNjQgOTAuNzQ4NzIzMiw2MC4xMjYxNTUgOTAuNzQ4NzIzMiw3MSBDOTAuNzQ4NzIzMiw3NS41NTg4MjczIDg5LjA3NDE3NTgsNzkuNTUzOTY4MiA4Ni4zNzY1NjQxLDgyLjk2NTkwOTEgQzg1LjQzNDU0NzYsODMuOTUwNjM4NCA4NS41NTkzNjI1LDg1Ljc0NDI3MjkgODYuNjI4Njg2NCw4Ni41ODkwNDAzIEM4Ny42OTgwMTE2LDg3LjQzMzgwNjUgODkuNDcxODMxOCw4Ny4xNDAwOTMxIDkwLjIxMTc5MTQsODUuOTk1NzM4NiBDOTMuNDY1NzQzLDgxLjg4MDA3OTUgOTUuNjU3ODE0MSw3Ni43ODI0MTgyIDk1LjY1NzgxNDEsNzEgQzk1LjY1NzgxNDEsNTcuNDczMDYxNCA4NC42MzkzNjgxLDQ2LjQ1NDU0NTUgNzEuMTEyMzU5Niw0Ni40NTQ1NDU1IEM1Ny41ODUzNTEsNDYuNDU0NTQ1NSA0Ni41NjY5MDUsNTcuNDczMDYxNCA0Ni41NjY5MDUsNzEgQzQ2LjU2NjkwNSw4My42OTQ2NTc1IDU2LjI4MzEwNDEsOTQuMTg4MDk3IDY4LjY1NzgxNDEsOTUuNDMwMzk3NyBMNjguNjU3ODE0MSwxMDUuMjg2OTMyIEM1MC44MDEzMjk3LDEwNC4wMzEwNDUgMzYuNzQ4NzIzMiw4OS4xODEyNDE2IDM2Ljc0ODcyMzIsNzEgQzM2Ljc0ODcyMzIsNTEuOTkyMjU3NyA1Mi4xMDQ3ODE3LDM2LjYzNjM2MzYgNzEuMTEyMzU5NiwzNi42MzYzNjM2IEM5MC4xMTk5MzQ5LDM2LjYzNjM2MzYgMTA1LjQ3NTk5Niw1MS45OTIyNTc3IDEwNS40NzU5OTYsNzEgQzEwNS40NzU5OTYsNzkuMzEzNjY4MiAxMDIuNDE1MTQ4LDg2Ljc2NDc0NzcgOTcuNDYwMzcwOSw5Mi43NDU3Mzg2IEM5Ni40NjI2ODY2LDkzLjcwMDM4MzggOTYuNTI5MjQwMyw5NS41MzE3OTYyIDk3LjU5MzU4NCw5Ni40MTE1MDkgQzk4LjY1NzkyNzcsOTcuMjkxMjIwNSAxMDAuNDY5MTI2LDk3LjAxMTgyODIgMTAxLjIxODg5NCw5NS44NTIyNzI3IEMxMDYuODIxOTA3LDg5LjA4ODg5NTUgMTEwLjM4NTA4Nyw4MC41Mjg2NjgyIDExMC4zODUwODcsNzEgQzExMC4zODUwODcsNDkuMzM5MjEzMiA5Mi43NzMwMTM4LDMxLjcyNzI3MjcgNzEuMTEyMzU5NiwzMS43MjcyNzI3IEM0OS40NTE3MDI4LDMxLjcyNzI3MjcgMzEuODM5NjMyMyw0OS4zMzkyMTMyIDMxLjgzOTYzMjMsNzEgQzMxLjgzOTYzMjMsOTEuODQwMzkwNiA0OC4xMzExMTgxLDEwOC45MzEzODggNjguNjU3ODE0MSwxMTAuMTk2MDIzIEw2OC42NTc4MTQxLDEyMC4wNTI1NTcgQzQyLjY1OTA4MDksMTE4Ljc3NzUgMjIuMDIxNDUwNSw5Ny4zMTg3OTEyIDIyLjAyMTQ1MDUsNzEgQzIyLjAyMTQ1MDUsNDMuODU4NTA3NyA0My45NzExMTY0LDIxLjkwOTA5MDkgNzEuMTEyMzU5NiwyMS45MDkwOTA5IEM5OC4yNTM1OTksMjEuOTA5MDkwOSAxMjAuMjAzMjY5LDQzLjg1ODUwNzcgMTIwLjIwMzI2OSw3MSBDMTIwLjIwMzI2OSw4NC4yNDMwMDkxIDExNC43Mzk0Nyw5NS45OTg1MDIzIDEwNi4xNjYzMzcsMTA0Ljg2NTA1NyBDMTA1LjI1NTA0NiwxMDUuNzg1MTExIDEwNS4yNzI4OTcsMTA3LjQ1NjQ3NCAxMDYuMjAzNjM0LDEwOC4zNTY4NTYgQzEwNy4xMzQzNjUsMTA5LjI1NzIzOSAxMDguODA1NDAzLDEwOS4yMTk2ODkgMTA5LjY5NDc1MSwxMDguMjc4NDA5IEMxMTkuMDU3MjI5LDk4LjU5NTU5NTUgMTI1LjExMjM2LDg1LjU5NzE4MTggMTI1LjExMjM2LDcxIEMxMjUuMTEyMzYsNDEuMjA1NDYzMiAxMDAuOTA2NjM2LDE3IDcxLjExMjM1OTYsMTcgWiIgaWQ9IlBhdGgiIGZpbGw9IiNGRkZGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzEuMTEyMzYwLCA3MS4wMDAwMDApIHJvdGF0ZSgxODAuMDAwMDAwKSB0cmFuc2xhdGUoLTcxLjExMjM2MCwgLTcxLjAwMDAwMCkgIj48L3BhdGg+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=")
16+
}
17+
18+
#crt {
19+
background: white;
20+
border-left: 2px solid #832FF4;
21+
padding: 5px;
22+
margin-left: 30px;
23+
}
24+
25+
.ray {
26+
word-break: break-word;
27+
}
28+
</style>
29+
30+
<script>
31+
function togglePPID() {
32+
var crt = document.getElementById("crt");
33+
if (crt.style.display === "none") {
34+
crt.style.display = "block";
35+
} else {
36+
crt.style.display = "none";
37+
}
38+
}</script>
39+
<div id="ppid">
40+
<a id="togglePPID" href="#" onclick="togglePPID()"></a>
41+
<div id="crt" style="display:none;">
42+
<div class="ray"><strong>Build ID: </strong><%= build_id %></div>
43+
<div class="ray"><strong>Context: </strong><%= context %></div>
44+
<div class="ray"><strong>Commit: </strong><%= commit_ref %></div>
45+
<div class="ray"><strong>Deploy ID: </strong><%= deploy_id %></div>
46+
</div>
47+
</div>

0 commit comments

Comments
 (0)