Skip to content

Commit 9cfe685

Browse files
Hugo Docs Modification (linode#1127)
Hugo Docs Modification
1 parent 389f9ac commit 9cfe685

File tree

1,186 files changed

+82213
-46193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,186 files changed

+82213
-46193
lines changed

docs/.gitignore renamed to .gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
__pycache__/
2+
.cache/
3+
.scrapy
4+
.pynb_checkpoints
5+
.env
6+
.venv
7+
18
.DS_Store
29
.DS_Store?
310
._*

.travis.yml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
language: python
2+
cache:
3+
pip: true
4+
directories:
5+
- node_modules
6+
matrix:
7+
include:
8+
- python: "3.6"
9+
10+
before_install:
11+
- echo "Installing Hugo 0.30.2"
12+
# - curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
13+
# - sudo apt install nodejs
14+
- wget https://github.com/gohugoio/hugo/releases/download/v0.30.2/hugo_0.30.2_Linux-64bit.deb
15+
- sudo dpkg -i hugo*.deb
16+
- hugo version
17+
# - sudo npm install --global gulp-cli
18+
# - npm install
19+
20+
install:
21+
- echo "Install pytest and pip"
22+
- pip install -r ci/requirements.txt
23+
24+
before_script:
25+
- echo "Setting up local development server"
26+
- hugo server &
27+
- sleep 7
28+
29+
script:
30+
- echo "Checking for style guidelines"
31+
- python -m pytest -n 2
32+

archetypes/content.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
author:
3+
name: Linode Community
4+
email: docs@linode.com
5+
description: 'Two to three sentences describing your guide.'
6+
keywords: ['list','of','keywords','and key phrases']
7+
license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
8+
published: {{ .Date }}
9+
modified: {{ .Date }}
10+
expiry_date: {{ .Date }}
11+
deprecated: {{ .Date > $.Page.Params.expiry_date }}
12+
modified_by:
13+
name: Linode
14+
title: "{{ replace .TranslationBaseName "-" " " | title }}"
15+
contributor:
16+
name: Your Name
17+
link: Github/Twitter Link
18+
external_resources:
19+
- '[Link Title 1](http://www.example.com)'
20+
- '[Link Title 2](http://www.example.net)'
21+
---
22+
23+
*This is a Linode Community guide. If you're an expert on something for which we need a guide, you too can [get paid to write for us](/docs/contribute).*
24+
25+
----
26+
27+
<!--- See https://www.linode.com/docs/style-guide for more details on guide formatting. --->
28+
29+
30+
## Before You Begin
31+
32+
1. Familiarize yourself with our [Getting Started](/docs/getting-started) guide and complete the steps for setting your Linode's hostname and timezone.
33+
34+
2. This guide will use `sudo` wherever possible. Complete the sections of our [Securing Your Server](/docs/security/securing-your-server) to create a standard user account, harden SSH access and remove unnecessary network services. Do **not** follow the Configure a Firewall section yet--this guide includes firewall rules specifically for an OpenVPN server.
35+
36+
3. Update your system:
37+
38+
sudo apt-get update && sudo apt-get upgrade
39+
40+
<!-- Include one of the following notes if appropriate. --->
41+
42+
{{< note >}}
43+
This guide is written for a non-root user. Commands that require elevated privileges are prefixed with `sudo`. If you’re not familiar with the `sudo` command, see the [Users and Groups](/docs/tools-reference/linux-users-and-groups) guide.
44+
{{< /note >}}
45+
46+
{{< note >}}
47+
The steps in this guide require root privileges. Be sure to run the steps below as `root` or with the `sudo` prefix. For more information on privileges, see our [Users and Groups](/docs/tools-reference/linux-users-and-groups) guide.
48+
{{< /note >}}
49+
50+
51+
{{< caution >}}
52+
Highlight warnings that could adversely affect a user's system with the Caution style.
53+
{{< /caution >}}
54+
55+
{{< file "/etc/hosts" aconf >}}
56+
192.0.2.0/24 # Sample IP addresses
57+
198.51.100.0/24
58+
203.0.113.0/24
59+
{{< /file >}}

archetypes/default.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
title: "{{ replace .TranslationBaseName "-" " " | title }}"
3+
date: {{ .Date }}
4+
draft: true
5+
---
6+

ci/README.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Running on a virtual environment is recommended.
2+
3+
Install pip requirments:
4+
5+
`pip install -r requirements.txt`
6+
7+
Start the Hugo development server. Runs on `localhost:1313/docs/` by default:
8+
9+
`hugo server`
10+
11+
Run the test environment from the root directory. Python 3 is required.
12+
13+
`python -m pytest`
14+
15+
To use multiple cores when running tests, add `-n` (2 is enough for current tests):
16+
17+
`python -m pytest -n <Additional Cores>`
18+

ci/conftest.py

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import pytest
2+
import os
3+
import fnmatch
4+
from functools import wraps
5+
6+
7+
LOCALHOST = "http://localhost:1313/docs/"
8+
9+
def file_io(func):
10+
"""
11+
Open and close file objects for tests
12+
"""
13+
@wraps(func)
14+
def wrapper(md_filepaths):
15+
# Before test
16+
f = open(md_filepaths, 'r')
17+
# After test
18+
r = func(f)
19+
f.close()
20+
return r
21+
return wrapper
22+
23+
24+
@pytest.fixture(scope='module', autouse=True)
25+
def md_index(path='.', extension='*.md'):
26+
"""
27+
Traverses root directory
28+
"""
29+
index = []
30+
exclude = ['node_modules']
31+
for root, dirnames, filenames in os.walk(path):
32+
dirnames[:] = [d for d in dirnames if d not in exclude]
33+
for filename in fnmatch.filter(filenames, extension):
34+
index.append(os.path.join(root, filename))
35+
return index
36+
37+
38+
@pytest.fixture(params=md_index())
39+
def md_filepaths(request):
40+
return request.param
41+
42+
43+
#@pytest.fixture(params=[open(i) for i in md_index()])
44+
#def md_files(request):
45+
# return request.param
46+
47+

ci/requirements.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
regex>=2017.4.5
2+
requests>.2.14.2
3+
scrapy>=1.4.0
4+
pytest-xdist>=1.20.1
5+
PyYAML>=3.12

ci/test_404.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import pytest
2+
3+
import logging
4+
import scrapy
5+
from scrapy import Item, Field
6+
from scrapy.linkextractors import LinkExtractor
7+
from scrapy.spiders import CrawlSpider, Rule
8+
from scrapy.crawler import CrawlerProcess
9+
10+
class Docs404Item(Item):
11+
referer = Field()
12+
status = Field()
13+
url = Field()
14+
15+
class Docs404Spider(CrawlSpider):
16+
17+
def __init__(self, *args, **kwargs):
18+
loggers = ['scrapy.core.engine',
19+
'scrapy.downloadermiddlewares.redirect',
20+
'scrapy.spidermiddlewares.offsite',
21+
'scrapy.middleware']
22+
for l in loggers:
23+
logger = logging.getLogger(l)
24+
logger.setLevel(logging.WARNING)
25+
super().__init__(*args, **kwargs)
26+
27+
# Delay if server is returning lots of 500s
28+
# DOWNLOAD_DELAY=0.1
29+
name = 'docs404'
30+
allowed_domains = ['localhost' ]
31+
start_urls = ['http://localhost:1313/docs']
32+
handle_httpstatus_list = [404]
33+
34+
rules = (
35+
Rule(LinkExtractor(allow=r'/docs/', deny=r'/docs/contribute'),
36+
callback='parse_item', follow=True),
37+
)
38+
39+
def parse_item(self, response):
40+
item = Docs404Item()
41+
42+
if response.status == 404:
43+
item['referer'] = response.request.headers.get('Referer')
44+
item['status'] = response.status
45+
item['url'] = response.url
46+
return item
47+
48+
49+
def test_404():
50+
import os
51+
process = CrawlerProcess({ 'USER_AGENT': 'docs404',
52+
'FEED_URI': 'temp.csv',
53+
'FEED_FORMAT': 'csv' })
54+
process.crawl(Docs404Spider)
55+
process.start()
56+
f = open('temp.csv')
57+
os.remove('temp.csv')
58+
assert sum([1 for line in f]) == 1,'404 response in HTML - see scraper logs'
59+
60+

ci/test_alias.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import pytest
2+
3+
from contextlib import redirect_stdout
4+
import re
5+
import ast
6+
from datetime import datetime
7+
import urllib.request
8+
from urllib.error import HTTPError, URLError
9+
from conftest import file_io, LOCALHOST
10+
11+
12+
@file_io
13+
def test_alias(md_filepaths):
14+
aliases = []
15+
valid_alias = True
16+
for line in md_filepaths:
17+
# Check if file is expired
18+
today = datetime.now()
19+
has_exp_header = re.match(r'^expiryDate: ', line)
20+
if has_exp_header:
21+
exp_date = datetime.strptime(line.split()[1], '%Y-%m-%d')
22+
if exp_date <= today:
23+
pytest.skip("Marked expired not checked")
24+
25+
match = re.match(r'^aliases: \[.*\]', line)
26+
if match:
27+
new_line = match.group()
28+
# Literal evaluation of brackets in alias
29+
aliases += ast.literal_eval(new_line[new_line.find("["):])
30+
31+
#Check case where alias points back to URL
32+
if md_filepaths.name.lstrip('./content/')[:-3] in \
33+
[a.rstrip('/') for a in aliases]:
34+
valid_alias = False
35+
print('Circular alias: ' + path)
36+
for alias in aliases:
37+
try:
38+
urllib.request.urlopen(LOCALHOST + alias).getcode()
39+
except HTTPError:
40+
valid_alias = False
41+
print('404 alias: ' + alias)
42+
assert valid_alias == True,'Not a valid alias'
43+

ci/test_filename.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import pytest
2+
3+
def test_filename(md_filepaths):
4+
if any(e in md_filepaths for e in ['README.md', 'CHANGELOG.md']):
5+
assert True
6+
else:
7+
assert md_filepaths.islower() == True,'Filename should be lowercase'

ci/test_whitespace.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import pytest
2+
3+
from contextlib import redirect_stdout
4+
import regex
5+
from conftest import file_io
6+
7+
@file_io
8+
def test_whitespace(md_filepaths):
9+
has_whitespace = False
10+
for line_number, line in enumerate(md_filepaths, 1):
11+
match = regex.search(r'[\t]+$', line)
12+
if match:
13+
has_whitespace = True
14+
print("Trailing whitespace at " + str(line_number) + \
15+
":" + str(match.start()))
16+
assert has_whitespace == False
17+

ci/test_yaml.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import pytest
2+
3+
import regex
4+
from dateutil.parser import parse
5+
import sys
6+
import yaml
7+
import json
8+
from conftest import file_io
9+
10+
with open('ci/yaml_rules.json') as json_data:
11+
requirements = json.load(json_data)
12+
13+
14+
@file_io
15+
def test_yaml(md_filepaths):
16+
for filestring in md_filepaths:
17+
reg = regex.compile(r'^---(.*?)---',flags=regex.DOTALL)
18+
match = regex.search(reg, filestring)
19+
# Hack until README.md files won't be passed in
20+
# assert match
21+
if not match: return
22+
yaml_text = match.group(1)
23+
parsed_yaml = yaml.load(yaml_text)
24+
for requirement in requirements:
25+
req = requirements[requirement]
26+
if req['required']:
27+
assert requirement in parsed_yaml, 'YAML metadata missing required element: ' + requirement
28+
if req['type'] is 'link':
29+
regexp = regex.compile(r'\[(.*)\]\((.*)\)')
30+
assert regex.match(regexp,parsed_yaml[requirement]), 'YAML metadata formatting error: ' + requirement
31+
if req['type'] is 'date':
32+
try:
33+
parse(str(parsed_yaml[requirement]))
34+
except ValueError:
35+
assert False, 'YAML metadata formatting error: ' + requirement + ' date parse failed.'
36+

ci/yaml_rules.json

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"author": {
3+
"required": true,
4+
"elements":["name","email"],
5+
"type":"dict"
6+
},
7+
"title": {
8+
"required": true,
9+
"elements": false,
10+
"type":"text"
11+
},
12+
"description": {
13+
"required": true,
14+
"elements": false,
15+
"type":"text"
16+
},
17+
"keywords": {
18+
"required": true,
19+
"elements":"list",
20+
"type":"list"
21+
},
22+
"license": {
23+
"required": true,
24+
"elements": false,
25+
"type":"link"
26+
},
27+
"modified": {
28+
"required": true,
29+
"elements": false,
30+
"type":"date"
31+
},
32+
"modified_by": {
33+
"required": true,
34+
"elements": false,
35+
"type":"text"
36+
},
37+
"published": {
38+
"required": true,
39+
"type":"date",
40+
"elements": false
41+
}
42+
}
43+
44+
45+

0 commit comments

Comments
 (0)