I'm afraid I don't really have an idea how to do this - I want to use variables in a Gitlab Wiki page. is this possible at all using html? Can I run scripts on a page?
For example, this question on using a javascript variable in html - would something like this be possible?
For my specific example, I want a page with a table where the first column is numbers, and I want to take the largest value and display it at the top of the page. So for example the table might have rows like:
1 X
22 Y
15 Z
So at the top of the page I would display "largest number is 22". Does this make sense?
I'm afraid I don't really have an idea how to do this - I want to use variables in a Gitlab Wiki page. is this possible at all using html? Can I run scripts on a page?
For example, this question on using a javascript variable in html - would something like this be possible?
For my specific example, I want a page with a table where the first column is numbers, and I want to take the largest value and display it at the top of the page. So for example the table might have rows like:
1 X
22 Y
15 Z
So at the top of the page I would display "largest number is 22". Does this make sense?
Share Improve this question asked Dec 5, 2019 at 21:43 sw_buddysw_buddy 1251 silver badge9 bronze badges 4- 1 You cannot have a script in your Wikipage, since they sanitize the HTML (See what they allow here). To do what you want, you could generate that page in Gitlab-CI as part of your project's deploy pipeline, using whatever rendering engine and putting that variable in there, and update it automatically using Gitlab's Wiki APIs – blex Commented Dec 5, 2019 at 21:54
- @blex shouldn't your ment be an answer? – Ulysse BN Commented Dec 5, 2019 at 22:23
- 1 @UlysseBN I feel like an answer should have more details of implementation. I don't have time to do that right now, maybe someone else will :) – blex Commented Dec 5, 2019 at 22:33
- I finally took some time to do it. Hope this helps – blex Commented Dec 6, 2019 at 1:05
1 Answer
Reset to default 9You cannot have a script in your Wikipage, since they sanitize the HTML (See what they allow here). To do what you want, you could generate that page in Gitlab-CI as part of your project's deploy pipeline, using whatever rendering engine and putting that variable in there, and update it automatically using Gitlab's Wiki APIs.
How to
I created a demo NodeJS project here, which, when I push to the master
branch, auto-generates the Wiki pages. You can look at the code to see how it works.
This example app exposes a function to get a list of fruit and quantities in stock. We'll automatically add that data in the Wiki.
Step 1 - Create page templates
You can add templates to your project for your Wiki pages. In my example, I used MustacheJS. And I put everything in a wiki
folder (see folder structure at the end of step 5). Your template can look something like this:
wiki/templates/home.mst
# Wele to the supermarket
The biggest quantity we have in stock is for **{{topProduct.label}}**,
with a total of **{{topProduct.stock}}**!
| Fruit | Quantity |
|-----------|--------------|
{{#inventory}}
| {{label}} | {{stock}} |
{{/inventory}}
In this example, the data will e from the project code itself.
Step 2 - Build your pages
Note: The scripts I wrote as a demo use
axios
to make requests to the Gitlab API,mustache
to render the pages, andqs
to format the data as a query string before posting it to Gitlab. You can use other ones or install them as dev dependencies:npm install --save-dev axios mustache qs
Create a js file which will get the data from your app, and render the templates into a build
directory. Something like this:
wiki/build.js
const fs = require('fs');
const Mustache = require('mustache');
const myApp = require('../src/index.js');
const inventory = myApp.getInventory();
// Get the Mustache template
const homeTemplate = fs.readFileSync(__dirname + '/templates/home.mst', 'utf-8');
// Get the fruit with the highest quantity
const topProduct = inventory.reduce((acc, curr) => {
if (acc === null || curr.stock > acc.stock) {
return curr;
} else {
return acc;
}
}, null);
// Render the page using your variables
const homeContent = Mustache.render(homeTemplate, { inventory, topProduct });
// Write the file in a build directory
const buildDir = __dirname + '/../build';
if (!fs.existsSync(buildDir)) {
fs.mkdirSync(buildDir);
}
fs.writeFileSync(buildDir + '/home.md', homeContent);
And in your package.json
, add a mand to run that script:
"scripts": {
// ...
"wiki:build": "node wiki/build.js"
}
Step 3 - Deploy your Wiki pages
Create a script which will upload the pages to your Wiki. This may work as-is without much modification, if you're also using NodeJS.
wiki/deploy.js
const fs = require('fs');
const Axios = require('axios');
const qs = require('qs');
const config = {
gitlabBaseUrl: 'https://gitlab.', // Update this if you're on a private Gitlab
projectId: process.env.CI_PROJECT_ID, // Provided by Gitlab-CI
privateToken: process.env.WIKI_DEPLOY_TOKEN, // Added through Gitlab interface
buildDir: __dirname + '/../build'
};
const axios = Axios.create({
baseURL: config.gitlabBaseUrl,
headers: { 'Private-Token': config.privateToken, Accept: 'application/json' }
});
(async function deploy() {
const existingPages = await getExistingWikiPages();
const updatedPages = getUpdatedPages();
// Pages which existed but are no longer in the build (obsolete)
const pagesToDelete = existingPages.filter(p1 => updatedPages.every(p2 => p2.slug !== p1.slug));
// Pages which didn't exist before
const pagesToCreate = updatedPages.filter(p1 => existingPages.every(p2 => p2.slug !== p1.slug));
// Pages which already exist
const pagesToUpdate = updatedPages.filter(p1 => existingPages.some(p2 => p2.slug === p1.slug));
console.log(
`Found ${pagesToDelete.length} pages to delete, ${pagesToCreate.length} pages to create, ${pagesToUpdate.length} pages to update.`
);
for (let page of pagesToDelete) {
await deletePage(page);
}
for (let page of pagesToCreate) {
await createPage(page);
}
for (let page of pagesToUpdate) {
await updatePage(page);
}
console.log('Deploy plete!');
})();
function getExistingWikiPages() {
return axios.get(`/api/v4/projects/${config.projectId}/wikis`).then(res => res.data);
}
function getUpdatedPages() {
const files = fs.readdirSync(config.buildDir);
return files.map(file => {
const name = file // Remove the file extension
.split('.')
.slice(0, -1)
.join('.');
return {
format: 'markdown', // You could make this depend on the file extension
slug: name,
title: name,
content: fs.readFileSync(`${config.buildDir}/${file}`, 'utf-8')
};
});
}
function deletePage(page) {
console.log(`Deleting ${page.slug}...`);
return axios.delete(`/api/v4/projects/${config.projectId}/wikis/${page.slug}`);
}
function createPage(page) {
console.log(`Creating ${page.slug}...`);
return axios.post(`/api/v4/projects/${config.projectId}/wikis`, qs.stringify(page));
}
function updatePage(page) {
console.log(`Updating ${page.slug}...`);
return axios.put(`/api/v4/projects/${config.projectId}/wikis/${page.slug}`, qs.stringify(page));
}
In the config
at the top, you need to specify which URL your Gitlab is using. CI_PROJECT_ID
will be provided by Gitlab-CI itself as an environment variable. WIKI_DEPLOY_TOKEN
, however, will not. Set it up in step 4.
And in your package.json
, add a mand to run that script:
"scripts": {
// ...
"wiki:build": "node wiki/build.js",
"wiki:deploy": "node wiki/deploy.js"
}
Note: This example will delete obsolete pages, and update or create new ones depending on files it finds in the build folder and the ones the Wiki already contains. If you want to have attachments as well (images), you'll need to make use of this API also.
Step 4 - Setup a private token WIKI_DEPLOY_TOKEN
For this, you'll need to click on your profile picture at the top right corner > Settings. Then in the left menu, Access Tokens, and create a token with the api scope. The name does not matter. Copy this token now, since it will only be shown once.
Then, go to your project. In the menu on the left, click Settings > CI/CD. Expand the Variables section, and use the previously copied token to create a variable called WIKI_DEPLOY_TOKEN
, make it Masked so that it does not appear in any logs, and Save variables:
This will make that token available only in your pipelines, as an environment variable.
Step 5 - Create your pipeline
If you don't already have a pipeline, all you need to do is create a .gitlab-ci.yml
file at the root of your project. Declare a generate_wiki
stage:
.gitlab-ci.yml
stages:
# - tests
# - deploy
# ...
- generate_wiki
generate_wiki:
image: node:10
stage: generate_wiki
script:
- npm install
- npm run wiki:build # build the wiki in a directory
- npm run wiki:deploy # update it in Gitlab
only:
- master # Only when merging or pushing to master branch
# ... rest of your pipeline ...
As you can see, we use the mands wiki:build
and wiki:deploy
declared in steps 2 and 3.
Now, your project structure should look something like this:
/
├───src
│ └── index.js
├───wiki
│ ├── templates
│ │ └── home.mst
│ ├── build.js
│ └── deploy.js
├── .gitlab-ci.yml
└── package.json
Step 6 - Push to master, and enjoy the magic
After pushing, if everything went right, you can click on CI/CD in the left menu, and you should see your pipeline running:
If you click on the little circle, you should see the logs:
And if you go to your Wiki pages, they should be up to date, automagically: