Compare commits
93 Commits
Author | SHA1 | Date | |
---|---|---|---|
c6b4f01102 | |||
9592dc58b1 | |||
a6bcfa6b3f | |||
ce3a2c2e1e | |||
c9f9d0b504 | |||
cc7a411613 | |||
2e534c5dd0 | |||
286caa1696 | |||
08bdf09d30 | |||
88b80c412d | |||
3dd7b452a4 | |||
7bd7abd0e4 | |||
ddc871acca | |||
217f159c5c | |||
88af5fedab | |||
ec46764d72 | |||
c6f44892e7 | |||
fee71df75e | |||
006a36ac0c | |||
b4fdcb6183 | |||
247f85c319 | |||
40a92b975f | |||
3fb954faac | |||
a73362abe7 | |||
c3f1ccc8dd | |||
8b041133dc | |||
13b829d0b5 | |||
c50e9a0a6e | |||
15cf04ff32 | |||
c4dd5b4a24 | |||
f811a7acef | |||
3dcca53b09 | |||
3a2968b56a | |||
cfe5de7ed7 | |||
e1d3a33418 | |||
f77363beea | |||
e094f84b15 | |||
7c9c3fcbf0 | |||
45cb623758 | |||
8292b0a6cf | |||
17f97f85bf | |||
f73011d29d | |||
e4999a4462 | |||
0e65f0465b | |||
94ced08565 | |||
65726fda02 | |||
0c7c36d7e1 | |||
7e99d55bda | |||
0d51c8d10b | |||
d67a264ef0 | |||
452fbe1225 | |||
a9237c5950 | |||
98d0acf0ac | |||
85c5d475bb | |||
78c8db9466 | |||
34ff1e34df | |||
b79196335d | |||
95f20fee73 | |||
0e09b249dc | |||
5d75c663a1 | |||
61f3331db0 | |||
9b6b3eb291 | |||
9d9f9c73c8 | |||
54b75f38b4 | |||
d6524ac9cf | |||
72ed1cb440 | |||
93ceceb396 | |||
10a81f0bed | |||
f2969de739 | |||
1a1b77769d | |||
5dfeeb81b1 | |||
653c535b2c | |||
7267f8f2ad | |||
f77b36a138 | |||
2a16ca065c | |||
b0c91fa68b | |||
449ec4a9fc | |||
c2d3a178a5 | |||
830371c691 | |||
3a08f14d74 | |||
893d3dfd5c | |||
59c2593c68 | |||
c6de8bc960 | |||
6667f4f076 | |||
268e076e9a | |||
47bfd4e5cc | |||
f6d6bd627b | |||
c0aa5cbe12 | |||
2460b4c70c | |||
dde0939e1b | |||
a02d2c3bb5 | |||
696138c317 | |||
8fbb9d95ac |
7
.cz.yaml
Normal file
7
.cz.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
commitizen:
|
||||||
|
bump_message: "build(version): bump version $current_version \u2192 $new_version"
|
||||||
|
changelog_incremental: false
|
||||||
|
name: cz_conventional_commits
|
||||||
|
tag_format: v$major.$minor.$patch$prerelease
|
||||||
|
update_changelog_on_bump: true
|
||||||
|
version: 1.0.0rc1
|
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Ignore build Directory
|
||||||
|
build/
|
||||||
|
aux/
|
||||||
|
|
||||||
|
# ignore dev env
|
||||||
|
dev_env
|
||||||
|
__pycache__
|
||||||
|
|
||||||
|
# ignore junit
|
||||||
|
*.junit.xml
|
||||||
|
|
||||||
|
# ignore log files
|
||||||
|
*.log
|
113
.gitlab-ci.yml
113
.gitlab-ci.yml
@ -1,9 +1,11 @@
|
|||||||
stages:
|
stages:
|
||||||
- validation
|
- validation
|
||||||
|
- build
|
||||||
|
- deploy
|
||||||
|
- test
|
||||||
- release
|
- release
|
||||||
- publish
|
- publish
|
||||||
|
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
GIT_SUBMODULE_STRATEGY: recursive
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
MY_PROJECT_ID: "13001358"
|
MY_PROJECT_ID: "13001358"
|
||||||
@ -11,56 +13,87 @@ variables:
|
|||||||
|
|
||||||
include:
|
include:
|
||||||
- project: nofusscomputing/projects/gitlab-ci
|
- project: nofusscomputing/projects/gitlab-ci
|
||||||
ref: 1ef6c41818c40183f8019ea5cde48b4278e4d694
|
ref: ce1cc017e26ff7f6cee586cc7d98e4d292275672
|
||||||
file:
|
file:
|
||||||
- conventional_commits/.gitlab-ci.yml
|
- conventional_commits/.gitlab-ci.yml
|
||||||
|
- mkdocs/.gitlab-ci.yml
|
||||||
|
- validation/.gitlab-ci.yml
|
||||||
- gitlab_release/.gitlab-ci.yml
|
- gitlab_release/.gitlab-ci.yml
|
||||||
|
|
||||||
|
|
||||||
markdown lint:
|
Lint Markdown:
|
||||||
image: node:alpine3.14
|
extends: .Lint_Markdown
|
||||||
stage: validation
|
|
||||||
before_script:
|
|
||||||
- npm install markdownlint-cli2 --global
|
|
||||||
- npm install markdownlint-cli2-formatter-junit --global
|
|
||||||
- mkdir -p "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME"
|
|
||||||
- mkdir -p "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests"
|
|
||||||
script:
|
|
||||||
- markdownlint-cli2 "**/*.md" "!gitlab-ci" 1>&1 || EXITCODE=$?
|
|
||||||
- echo DEBUG EXITCODE[$EXITCODE]
|
|
||||||
- mv markdown.junit.xml $CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests/markdown.junit.xml
|
|
||||||
artifacts:
|
|
||||||
expire_in: 3 days
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- "$CI_PROJECT_DIR/artifacts/*"
|
|
||||||
reports:
|
|
||||||
junit:
|
|
||||||
- "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests/*.junit.xml"
|
|
||||||
rules:
|
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
|
||||||
when: never
|
|
||||||
- if: '$CI_COMMIT_BRANCH'
|
|
||||||
exists:
|
|
||||||
- "**.md"
|
|
||||||
- when: never
|
|
||||||
|
|
||||||
|
|
||||||
|
Static Pages:
|
||||||
|
extends: .MKDocs_Build
|
||||||
|
needs: [ 'Lint Markdown' ]
|
||||||
|
|
||||||
|
|
||||||
|
pages:
|
||||||
|
stage: deploy
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
script:
|
||||||
|
- mv "$CI_PROJECT_DIR/artifacts/build/Static Pages/build" public
|
||||||
|
needs: [ 'Static Pages' ]
|
||||||
|
environment:
|
||||||
|
name: staging
|
||||||
|
url: $CI_PAGES_URL
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "master"'
|
||||||
|
when: always
|
||||||
|
- when: never
|
||||||
|
|
||||||
|
|
||||||
|
.Pytest_template:
|
||||||
|
stage: test
|
||||||
|
image: ubuntu:18.04
|
||||||
|
before_script:
|
||||||
|
- mkdir -p "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME"
|
||||||
|
- mkdir -p "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests"
|
||||||
|
- apt update
|
||||||
|
- apt install -y python3 python3-pip ca-certificates
|
||||||
|
- apt install --no-install-recommends -y chromium-chromedriver
|
||||||
|
- pip3 install --upgrade pip
|
||||||
|
- pip3 install -r test/requirements.txt
|
||||||
|
artifacts:
|
||||||
|
expire_in: 24 hrs
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME/*"
|
||||||
|
reports:
|
||||||
|
junit:
|
||||||
|
- "*.junit.xml"
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH'
|
||||||
|
when: always
|
||||||
|
- when: never
|
||||||
|
|
||||||
|
|
||||||
|
Unit Tests:
|
||||||
|
extends: .Pytest_template
|
||||||
|
needs: [ 'Static Pages' ]
|
||||||
|
script:
|
||||||
|
- mv "$CI_PROJECT_DIR/artifacts/build/Static Pages/build" build
|
||||||
|
- pytest --verbose --junitxml=unit_test.junit.xml --tb=line test/unit
|
||||||
|
- cp *.junit.xml "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME/"
|
||||||
|
- echo "[DEBUG] python_exit[$python_exit]"
|
||||||
|
|
||||||
|
|
||||||
|
#Integration Tests:
|
||||||
|
# extends: .Pytest_template
|
||||||
|
# needs:
|
||||||
|
# - pages
|
||||||
|
# - 'Unit Tests'
|
||||||
|
# script:
|
||||||
|
# - echo "placeholder job for integration tests" > "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME/DETEMEME.txt"
|
||||||
|
|
||||||
Gitlab Release:
|
Gitlab Release:
|
||||||
extends:
|
extends:
|
||||||
- .gitlab_release
|
- .gitlab_release
|
||||||
|
|
||||||
|
|
||||||
pages:
|
|
||||||
stage: publish
|
|
||||||
script:
|
|
||||||
- echo publish page
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
|
|
||||||
|
5
.gitlab/issues/website_issue.md
Normal file
5
.gitlab/issues/website_issue.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
What is the Page URL? <!-- Place the url after this text -->
|
||||||
|
|
||||||
|
### :books: Summary
|
||||||
|
<!-- Please put a detailed summary of what you wish to report under this heading. including any suggestions you would like to make. -->
|
||||||
|
|
27
.gitlab/merge_requests/new_article.md
Normal file
27
.gitlab/merge_requests/new_article.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
### :memo: Summary
|
||||||
|
|
||||||
|
|
||||||
|
### :link: Links / References
|
||||||
|
|
||||||
|
- LinksOrReferencesListed
|
||||||
|
|
||||||
|
#### :construction_worker: Tasks
|
||||||
|
|
||||||
|
- Required Metadata
|
||||||
|
|
||||||
|
- [ ] meta.title
|
||||||
|
|
||||||
|
- [ ] meta.description
|
||||||
|
|
||||||
|
- [ ] meta.date _format YYYY-MM-DD_
|
||||||
|
|
||||||
|
- [ ] meta.tags
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
tags:
|
||||||
|
- tagname1
|
||||||
|
- tagname2
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
/target_branch development
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"outputFormatters": [
|
|
||||||
[ "markdownlint-cli2-formatter-junit", { "name": "markdown.junit.xml" } ]
|
|
||||||
]
|
|
||||||
}
|
|
9
.markdownlint.json
Normal file
9
.markdownlint.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"line-length": false,
|
||||||
|
"MD007": {
|
||||||
|
"indent": 4
|
||||||
|
},
|
||||||
|
"MD033": {
|
||||||
|
"allowed_elements": [ "div", "s", "span", "u" ]
|
||||||
|
}
|
||||||
|
}
|
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"python.pythonPath": "dev_env/bin/python",
|
||||||
|
"python.testing.pytestArgs": [
|
||||||
|
"--verbose", "--junit-xml=${workspaceFolder}/unit_test.junit.xml", "--tb=line", "test"
|
||||||
|
],
|
||||||
|
"python.testing.unittestEnabled": false,
|
||||||
|
"python.testing.pytestEnabled": true
|
||||||
|
}
|
22
.vscode/tasks.json
vendored
Normal file
22
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"command": "bash",
|
||||||
|
"showOutput": "always",
|
||||||
|
"args": [
|
||||||
|
"-c"
|
||||||
|
],
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"suppressTaskName": true,
|
||||||
|
"args": [
|
||||||
|
"cd ${workspaceFolder}; . dev_env/bin/activate; pip install -r gitlab-ci/mkdocs/requirements.txt; pip install -r requirements.txt; mkdocs build --clean --strict"
|
||||||
|
],
|
||||||
|
"problemMatcher": [],
|
||||||
|
"label": "MKDocs Build Static Site",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
86
CHANGELOG.md
Normal file
86
CHANGELOG.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
## v1.0.0rc1 (2022-01-29)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **mkdocs-plugin-tags**: [ddc871ac](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/ddc871accabbbdafe28576265ee66755a5ffe17c) - ensure trailing '/' added to tag hyperlink [ [!5](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/5) ]
|
||||||
|
- **vscode**: [b4fdcb61](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/b4fdcb61834a6d9d1536b2a93aefd855fbe25006) - use correct params for tests [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **blog_metadata**: [a9237c59](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/a9237c59508979f673faa565f086ce0d2782e53d) - set the date to be in a format that is normal [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **mkdocs-plugin-tags**: [54b75f38](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/54b75f38b432050836f1f0f41eb6a9f9235ca88d) - fix markdown generation so it passes linting [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **mkdocs-plugin-tags**: [10a81f0b](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/10a81f0bed073ef865e8c98013ae186d7c70a467) - ensure heading reference in a url is in lower case. [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **mkdocs-plugin-tags**: [653c535b](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/653c535b2cfae1a54e45f27fd5c23950ddbe64ed) - the template not using the specified css class for the tag [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **mkdocs-plugin-tags**: [7267f8f2](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/7267f8f2ad287fafcbae0fc88f3ceb7dadd19035) - Build a relative link for the url to the tag page [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) ]
|
||||||
|
|
||||||
|
### Code Refactor
|
||||||
|
|
||||||
|
- [a6bcfa6b](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/a6bcfa6b3f877489891905adb120f3fa4228e7fd) - update article requirements
|
||||||
|
- **article**: [2e534c5d](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/2e534c5dd01b046f8fb520b9a2c607d432d2c309) - include meta.description [ [!5](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/5) ]
|
||||||
|
- **mkdocs.yml**: [f73011d2](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/f73011d29dbedd3617f37648c2a2fac5501a7a0d) - fix tabbing of plugin
|
||||||
|
- **privacy_test**: [94ced085](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/94ced08565dac3b26c23e66e9f61e929a8f07ddd) - rename test 'test_page_external_requests' -> 'test_page_load_external_requests' [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **syntax**: [d67a264e](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/d67a264ef010b3a182147d6e40407310e37fb099) - updated tags and added title metadata [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **choose_internet_service**: [98d0acf0](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/98d0acf0aca74c904236bc686f72e669009a8363) - removed extra tags and moved archive notice to bottom of page [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- [72ed1cb4](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/72ed1cb4408fcddf202e819cf73c3ce9d9cb2169) - change hover for content tags to yellow text. [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **navigation**: [93ceceb3](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/93ceceb3965f93ae4b0d0d3ffa86c0002927ee4b) - rename tags -> 'Content Tags' [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **markdown_lint**: [f2969de7](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/f2969de739230bc8c5d44c15a65c61bfdfc74027) - correct linting errors [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **mkdocs-plugin-tags**: [5dfeeb81](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/5dfeeb81b10a7e86c30b90dc360a06c3ad429adf) - rebranded plugin to be from nfc [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) ]
|
||||||
|
- [2a16ca06](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/2a16ca065c08759b31ee24f53d1e0ac67a406a9d) - md linting error, ul must be indent four spaces
|
||||||
|
- [449ec4a9](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/449ec4a9fc5d8421eea4cb79477d2124fc0a308c) - linting error. removed trailing empty line in choosing an internet service. [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **article**: [c2d3a178](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/c2d3a178a5ab335bd769a19e9a88839f17021bca) - fixing lists in choosing an internet service [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **markdown_lint**: [3a08f14d](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/3a08f14d74899d2f2200503db3ca1bd96ffa859f) - clean up linting errors. [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
|
||||||
|
### Continious Integration
|
||||||
|
|
||||||
|
- [217f159c](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/217f159c5c6593c33f27f6c36f0b54735fe3703b) - amend to last commit
|
||||||
|
- **integration_test**: [88af5fed](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/88af5fedab608986855ae7f1a29ccadd7a53d0f0) - disable job until developed
|
||||||
|
- **unit_test**: [ec46764d](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/ec46764d72db8de1fc25f8cfb73f56107007932f) - copy report to right location
|
||||||
|
- **pytest**: [c6f44892](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/c6f44892e7300f9e33b79a12df66bea866bfcd86) - fix to collect junit report
|
||||||
|
- [a73362ab](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/a73362abe74f9498c200bb76ac4b744ddf762462) - command only required for unit test [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- [c3f1ccc8](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/c3f1ccc8dd31c0bce3b3f709c54b3c39c1698b3c) - ensure placeholder test runs and passes [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **static_pages**: [8b041133](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/8b041133dce19647310b24a09161338029765a28) - dont run build if MD lint fails [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **tests**: [13b829d0](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/13b829d0b54d06540ea68b801e59139bedf176ea) - rijigged the job order [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **stages**: [c50e9a0a](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/c50e9a0a6ec438aa1211215202eb66363ef22de0) - deploy job to occur after build [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **unit_test**: [c4dd5b4a](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/c4dd5b4a24a383c84bb6759e3c482b8b11784859) - include requests in test pipfile [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) [#7](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/7) ]
|
||||||
|
- **unit_test**: [f811a7ac](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/f811a7aceffbfdea77c4ff429d0edf386023f07f) - capture stdout in JUnit Report [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **unit_test**: [65726fda](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/65726fda02b7001c7b5315f787136a86d7549566) - ensure only unit test jobs run for the 'unit test' job. [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **pytest**: [7e99d55b](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/7e99d55bdab2263b224aa8297e43e5b156e2bc6b) - Added pytest job to run tests against build. [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **gitlab-ci**: [34ff1e34](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/34ff1e34df74437edf5dbb1a05c2ed41215da056) - use gitlab-ci markdown linting job [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **mkdocs**: [b7919633](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/b79196335d8d471ebffd071cc61276e964fd2482) - use gitlab-ci mkdocs job [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **gitlab-ci**: [95f20fee](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/95f20fee7391674730ff5bbe3e4decdfc57de350) - updated to v0.6.0 [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **markdown_lint**: [b0c91fa6](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/b0c91fa68bda0fac2c4492a6fb227d0970a8f1d0) - set unordered list indentation to four.
|
||||||
|
- **markdown_lint**: [893d3dfd](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/893d3dfd5c393131f69fddd7d5e80d3f025b48bb) - disable line length for markdown files [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **pages**: [a02d2c3b](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/a02d2c3bb5fd0e933b42edce96b624ea355dcb69) - ensure the static site artifacts are available for gitlab pages [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **build**: [696138c3](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/696138c317e0f898188b1ba9f0a3e287933f5249) - Added config to build and publish to gitlab pages [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **merge_requests**: [ce3a2c2e](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/ce3a2c2e1e434d4910979fee482d071cc050c2b4) - added article MR template [ [!5](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/5) ]
|
||||||
|
- **vscode**: [cc7a4116](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/cc7a411613c02649fac2e5519079a1cc1b109677) - fix junit path to use workspace folder [ [!5](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/5) ]
|
||||||
|
- **blog_list**: [286caa16](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/286caa1696692216a09d4fe9dbfc3d4126c7dfd7) - layout not to include post content [ [!5](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/5) ]
|
||||||
|
- **blog_post**: [08bdf09d](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/08bdf09d30d7f8bbd1f6728d46835d0401f490c0) - remove meta.description from page [ [!5](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/5) ]
|
||||||
|
- **theme**: [7bd7abd0](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/7bd7abd0e40e56ccb2321a21dd974e8a5ef3de61) - removed post content from 'blog_list' [ [!5](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/5) ]
|
||||||
|
- **sitemap**: [006a36ac](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/006a36ac0cee8450ce0523add551081b87a235c2) - git_revision_date for page change [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **vscode**: [247f85c3](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/247f85c319e7456e5cb256b1e4fc15bff743424d) - added pytest settings [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **vscode**: [40a92b97](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/40a92b975fc706fdef584d40212d5403646f012a) - added build task [ [!4](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/4) ]
|
||||||
|
- **minify**: [8292b0a6](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/8292b0a6cfdfd8812a55775809947a0f4fc9501a) - disable minifying website until site ready to deploy [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **minify**: [e4999a44](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/e4999a446267c134d24bae252e363797fb188c95) - minify the mkdocs static html build files
|
||||||
|
- **mkdocs**: [0e65f046](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/0e65f0465b47f2d58774c44e028b6d6395f7a69c) - minify plugin added to pipfile for usage with build
|
||||||
|
- **emoji**: [0c7c36d7](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/0c7c36d7e1fd46925a805ad3a98fb682614d510f) - removed emoji support until a solution can be found to self-host. [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **blog_post**: [452fbe12](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/452fbe1225d8f0d22f3976b2c90aef9217a2ecd2) - change location of updated date to be in the social metadata. [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **gitlab**: [0e09b249](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/0e09b249dc72292b36e45449aaaf264a41e74140) - added a default issue templete for reporting issues with the website. [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) [#5](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/5) ]
|
||||||
|
- **blog_list**: [5d75c663](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/5d75c663a1c8472462d53a7bf758a91914ecfbfe) - change articles page to be a preview list of articles. [ [!2](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/2) ]
|
||||||
|
- **blog_post**: [61f3331d](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/61f3331db0602241b8a4b68952f38707e2b1043a) - include git revision date plugin
|
||||||
|
- **blog**: [9d9f9c73](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/9d9f9c73c8261cb6a4529acb7c59f4085fd2df27) - added blog capability to posts [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **markdownlint**: [d6524ac9](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/d6524ac9cf2e305218ec5d3862b85d12b341ba48) - specifiy the allowed inline html elements [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **mkdocs**: [1a1b7776](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/1a1b77769d7f924fc018fb303e6f656826c578a1) - use custom plugin from custom-plugins/mkdocs-plugin-tags [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **plugin**: [f77b36a1](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/f77b36a138809b50389dce016557497fbaaf5adb) - cloned plugin tags repo so it can be customized and used [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) ]
|
||||||
|
- **mkdocs**: [830371c6](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/830371c691e283418e373da881f13727ef63ec17) - add lists and task lists to markdown [ [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **sitemap**: [59c2593c](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/59c2593c68fbc3f5b5d9e553e328586ce0811859) - remove sitemap as the changed dates for files is wrong. [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **operations**: [c6de8bc9](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/c6de8bc9600a9c740660b8523f2efdd33a879b9e) - Added markdown syntax page. [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **article**: [6667f4f0](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/6667f4f0761dcba22a1825c9514963931618140e) - migrated choosing an internet service from old wiki [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **contact**: [268e076e](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/268e076e9a04fb071490f4d532aa3cdb53c4ee06) - updated the page content to include how to fix an issue with a page. [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **markdown**: [47bfd4e5](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/47bfd4e5cc9c19da8c82e37eb7513f1b75d68f45) - added ability to colour by brand name. [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **markdown**: [f6d6bd62](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/f6d6bd627b755cafe9e45f9edd17f7436a323b4a) - Support admonations in markdown. [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **footer**: [c0aa5cbe](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/c0aa5cbe12f92cea496a902f68ce4f7114f36d1a) - Add colour to the social icons within the page footer [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **mkdocs**: [2460b4c7](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/2460b4c70cf3a7ccf11da60c8b356fad2fad352d) - add document creation and last edited date. [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
- **mkdocs**: [8fbb9d95](https://gitlab.com/nofusscomputing/infrastructure/website/-/commit/8fbb9d95ac452b550c65cff32a88f7b6c23437d3) - Add the default config and the site layout directory [ [#3](https://gitlab.com/nofusscomputing/infrastructure/website/-/issues/3) [!1](https://gitlab.com/nofusscomputing/infrastructure/website/-/merge_requests/1) ]
|
||||||
|
|
||||||
|
## v1.0.0rc0 (2022-01-29)
|
125
custom-plugins/mkdocs-plugin-tags/.gitignore
vendored
Normal file
125
custom-plugins/mkdocs-plugin-tags/.gitignore
vendored
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
# docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
7
custom-plugins/mkdocs-plugin-tags/LICENSE.md
Normal file
7
custom-plugins/mkdocs-plugin-tags/LICENSE.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# License
|
||||||
|
|
||||||
|
Copyright (C) 2021 No Fuss Computing
|
||||||
|
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Not yet suitable for public release.
|
2
custom-plugins/mkdocs-plugin-tags/MANIFEST.in
Normal file
2
custom-plugins/mkdocs-plugin-tags/MANIFEST.in
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
include versioneer.py
|
||||||
|
include tags/_version.py
|
128
custom-plugins/mkdocs-plugin-tags/README.md
Normal file
128
custom-plugins/mkdocs-plugin-tags/README.md
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
# No Fuss Computing's Tags Plugin for MKDocs
|
||||||
|
|
||||||
|
Modified version from: [github.com/ginsburgnm/mkdocs-plugin-tags](https://github.com/ginsburgnm/mkdocs-plugin-tags)
|
||||||
|
|
||||||
|
## Previous Readme below - tags
|
||||||
|
|
||||||
|
Support for tags in the yaml-metadata in the header of markdown files.
|
||||||
|
|
||||||
|
Extracts this metadata and creates a "Tags" page which lists all tags
|
||||||
|
and all pages for each tag.
|
||||||
|
|
||||||
|
## Quick Demo
|
||||||
|
|
||||||
|
Install this plugin (it will also install mkdocs if required)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install mkdocs-plugin-tags
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a new documentation folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdocs new demo
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit the `.md` files to add initial metadata. Currently, the metadata has to be
|
||||||
|
enclosed in `---` lines, and must include a `title:` property
|
||||||
|
(otherwise the page will appear as "untitled" in the tags page). So, for example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd demo
|
||||||
|
cd docs
|
||||||
|
cat > index.md
|
||||||
|
---
|
||||||
|
title: Welcome
|
||||||
|
tags:
|
||||||
|
- testing
|
||||||
|
- unimportant
|
||||||
|
---
|
||||||
|
# Welcome to MkDocs
|
||||||
|
|
||||||
|
For full documentation visit [mkdocs.org](https://mkdocs.org).
|
||||||
|
|
||||||
|
^D
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `mkdocs.yml` to include this plugin:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
plugins:
|
||||||
|
- tags:
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdocs serve --livereload
|
||||||
|
```
|
||||||
|
|
||||||
|
Visit the URL `/tags` (it should appear in the nav panel).
|
||||||
|
This is an auto-generated page which contains the tags as level 2 headers,
|
||||||
|
and under each tag, a listing of the pages which declare that tag in the
|
||||||
|
metadata section.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
On each build (even with `--livereload`), all the `.md` files composing the
|
||||||
|
site are scanned, their "triple-dash-delimted" yaml header is extracted and
|
||||||
|
parsed, and the list of tags is collected.
|
||||||
|
|
||||||
|
After that, a new temporal file is created (by default in `aux/tags.md`, but
|
||||||
|
this is customizable) which contains the generated tags page, in markdown
|
||||||
|
format. This file is not in the documents folder to avoid retriggering a
|
||||||
|
build, but it is added to the list of files to be converted to HTML by mkdocs.
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
The layout of the tags page is a markdown file with jinja2 embedded contents.
|
||||||
|
The package provides such a template by default, with the following content:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: Tags
|
||||||
|
---
|
||||||
|
# Contents grouped by tag
|
||||||
|
|
||||||
|
{% for tag, pages in tags %}
|
||||||
|
|
||||||
|
## <span class="tag">{{tag}}</span>
|
||||||
|
{% for page in pages %}
|
||||||
|
* [{{page.title}}]({{page.filename}})
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can style the `h2.tag` element via CSS, if you want.
|
||||||
|
|
||||||
|
You can also provide your own markdown template, in case that you want a
|
||||||
|
different layout or metadata. The `page` object contains all the metadata
|
||||||
|
in a mkdocs page, and in addition a `.filename` attribute, which contains
|
||||||
|
the file name of the source of the page (relative to the docs folder),
|
||||||
|
which can be used to link to that page.
|
||||||
|
|
||||||
|
The full customizable options for the plugin are:
|
||||||
|
|
||||||
|
* `tags_folder`: Folder in which the auxiliar tags markdown file will be written
|
||||||
|
(`aux` by default, relative to the folder in which `mkdocs` is invoked).
|
||||||
|
It can be set to an absolute path, such as `/tmp/mysite/aux`.
|
||||||
|
The required folders are created.
|
||||||
|
* `tags_template`: path to the file which contains the markdown-jinja template
|
||||||
|
for the tags page. It is `None` by default, which means that the
|
||||||
|
package-provided template is used. It can be an absolute path,
|
||||||
|
or relative to the folder in which `mkdocs` is run.
|
||||||
|
* `css_name`: this allows you to pick what name styles the tag that appears on
|
||||||
|
the top of the page that contains a tag. This way things won't be overloaded
|
||||||
|
|
||||||
|
For example, this can be put at `mkdocs.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
plugins:
|
||||||
|
- search
|
||||||
|
- tags:
|
||||||
|
tags_folder: /tmp/mysite/aux
|
||||||
|
tags_template: docs/theme/tags.md.template
|
||||||
|
```
|
1
custom-plugins/mkdocs-plugin-tags/requirements.txt
Normal file
1
custom-plugins/mkdocs-plugin-tags/requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
mkdocs==1.2.3
|
27
custom-plugins/mkdocs-plugin-tags/setup.cfg
Normal file
27
custom-plugins/mkdocs-plugin-tags/setup.cfg
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
[metadata]
|
||||||
|
name = mkdocs-plugin-tags
|
||||||
|
author = No Fuss Computing
|
||||||
|
author_email = helpdesk@nofusscomputing.com
|
||||||
|
url = https://gitlab.com/nofusscomputing/infrastructure/website
|
||||||
|
description = "Create tags in mkdocs"
|
||||||
|
long_description_content_type = text/markdown
|
||||||
|
long_description = file: README.md
|
||||||
|
license = MIT
|
||||||
|
keywords = "mkdocs python markdown tags"
|
||||||
|
classifiers =
|
||||||
|
Intended Audience :: Developers
|
||||||
|
License :: OSI Approved :: MIT License
|
||||||
|
Operating System :: OS Independent
|
||||||
|
Intended Audience :: Information Technology
|
||||||
|
Programming Language :: Python :: 3.6
|
||||||
|
Programming Language :: Python :: 3.7
|
||||||
|
Programming Language :: Python :: 3.8
|
||||||
|
Topic :: Security :: Cryptography
|
||||||
|
|
||||||
|
[versioneer]
|
||||||
|
VCS = git
|
||||||
|
style = pep440
|
||||||
|
versionfile_source = tags/_version.py
|
||||||
|
versionfile_build = tags/_version.py
|
||||||
|
tag_prefix =
|
||||||
|
parentdir_prefix = tags-
|
19
custom-plugins/mkdocs-plugin-tags/setup.py
Normal file
19
custom-plugins/mkdocs-plugin-tags/setup.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
"""
|
||||||
|
Setup the plugin
|
||||||
|
"""
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
setup(
|
||||||
|
version='0.0.1',
|
||||||
|
python_requires='>=3.6',
|
||||||
|
install_requires=[
|
||||||
|
'mkdocs==1.2.3',
|
||||||
|
],
|
||||||
|
packages=find_packages(exclude=['*.tests']),
|
||||||
|
package_data={'tags': ['templates/*.md.template']},
|
||||||
|
entry_points={
|
||||||
|
'mkdocs.plugins': [
|
||||||
|
'tags = tags.plugin:TagsPlugin'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
3
custom-plugins/mkdocs-plugin-tags/tags/__init__.py
Normal file
3
custom-plugins/mkdocs-plugin-tags/tags/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
from . import _version
|
||||||
|
__version__ = _version.get_versions()['version']
|
644
custom-plugins/mkdocs-plugin-tags/tags/_version.py
Normal file
644
custom-plugins/mkdocs-plugin-tags/tags/_version.py
Normal file
@ -0,0 +1,644 @@
|
|||||||
|
|
||||||
|
# This file helps to compute a version number in source trees obtained from
|
||||||
|
# git-archive tarball (such as those provided by githubs download-from-tag
|
||||||
|
# feature). Distribution tarballs (built by setup.py sdist) and build
|
||||||
|
# directories (produced by setup.py build) will contain a much shorter file
|
||||||
|
# that just contains the computed version number.
|
||||||
|
|
||||||
|
# This file is released into the public domain. Generated by
|
||||||
|
# versioneer-0.21 (https://github.com/python-versioneer/python-versioneer)
|
||||||
|
|
||||||
|
"""Git implementation of _version.py."""
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from typing import Callable, Dict
|
||||||
|
|
||||||
|
|
||||||
|
def get_keywords():
|
||||||
|
"""Get the keywords needed to look up the version information."""
|
||||||
|
# these strings will be replaced by git during git-archive.
|
||||||
|
# setup.py/versioneer.py will grep for the variable names, so they must
|
||||||
|
# each be defined on a line of their own. _version.py will just call
|
||||||
|
# get_keywords().
|
||||||
|
git_refnames = "$Format:%d$"
|
||||||
|
git_full = "$Format:%H$"
|
||||||
|
git_date = "$Format:%ci$"
|
||||||
|
keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
|
||||||
|
return keywords
|
||||||
|
|
||||||
|
|
||||||
|
class VersioneerConfig:
|
||||||
|
"""Container for Versioneer configuration parameters."""
|
||||||
|
|
||||||
|
|
||||||
|
def get_config():
|
||||||
|
"""Create, populate and return the VersioneerConfig() object."""
|
||||||
|
# these strings are filled in when 'setup.py versioneer' creates
|
||||||
|
# _version.py
|
||||||
|
cfg = VersioneerConfig()
|
||||||
|
cfg.VCS = "git"
|
||||||
|
cfg.style = "pep440"
|
||||||
|
cfg.tag_prefix = ""
|
||||||
|
cfg.parentdir_prefix = "tags-"
|
||||||
|
cfg.versionfile_source = "tags/_version.py"
|
||||||
|
cfg.verbose = False
|
||||||
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
|
class NotThisMethod(Exception):
|
||||||
|
"""Exception raised if a method is not valid for the current scenario."""
|
||||||
|
|
||||||
|
|
||||||
|
LONG_VERSION_PY: Dict[str, str] = {}
|
||||||
|
HANDLERS: Dict[str, Dict[str, Callable]] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def register_vcs_handler(vcs, method): # decorator
|
||||||
|
"""Create decorator to mark a method as the handler of a VCS."""
|
||||||
|
def decorate(f):
|
||||||
|
"""Store f in HANDLERS[vcs][method]."""
|
||||||
|
if vcs not in HANDLERS:
|
||||||
|
HANDLERS[vcs] = {}
|
||||||
|
HANDLERS[vcs][method] = f
|
||||||
|
return f
|
||||||
|
return decorate
|
||||||
|
|
||||||
|
|
||||||
|
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
|
||||||
|
env=None):
|
||||||
|
"""Call the given command(s)."""
|
||||||
|
assert isinstance(commands, list)
|
||||||
|
process = None
|
||||||
|
for command in commands:
|
||||||
|
try:
|
||||||
|
dispcmd = str([command] + args)
|
||||||
|
# remember shell=False, so use git.cmd on windows, not just git
|
||||||
|
process = subprocess.Popen([command] + args, cwd=cwd, env=env,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=(subprocess.PIPE if hide_stderr
|
||||||
|
else None))
|
||||||
|
break
|
||||||
|
except OSError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if e.errno == errno.ENOENT:
|
||||||
|
continue
|
||||||
|
if verbose:
|
||||||
|
print("unable to run %s" % dispcmd)
|
||||||
|
print(e)
|
||||||
|
return None, None
|
||||||
|
else:
|
||||||
|
if verbose:
|
||||||
|
print("unable to find command, tried %s" % (commands,))
|
||||||
|
return None, None
|
||||||
|
stdout = process.communicate()[0].strip().decode()
|
||||||
|
if process.returncode != 0:
|
||||||
|
if verbose:
|
||||||
|
print("unable to run %s (error)" % dispcmd)
|
||||||
|
print("stdout was %s" % stdout)
|
||||||
|
return None, process.returncode
|
||||||
|
return stdout, process.returncode
|
||||||
|
|
||||||
|
|
||||||
|
def versions_from_parentdir(parentdir_prefix, root, verbose):
|
||||||
|
"""Try to determine the version from the parent directory name.
|
||||||
|
|
||||||
|
Source tarballs conventionally unpack into a directory that includes both
|
||||||
|
the project name and a version string. We will also support searching up
|
||||||
|
two directory levels for an appropriately named parent directory
|
||||||
|
"""
|
||||||
|
rootdirs = []
|
||||||
|
|
||||||
|
for _ in range(3):
|
||||||
|
dirname = os.path.basename(root)
|
||||||
|
if dirname.startswith(parentdir_prefix):
|
||||||
|
return {"version": dirname[len(parentdir_prefix):],
|
||||||
|
"full-revisionid": None,
|
||||||
|
"dirty": False, "error": None, "date": None}
|
||||||
|
rootdirs.append(root)
|
||||||
|
root = os.path.dirname(root) # up a level
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print("Tried directories %s but none started with prefix %s" %
|
||||||
|
(str(rootdirs), parentdir_prefix))
|
||||||
|
raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
|
||||||
|
|
||||||
|
|
||||||
|
@register_vcs_handler("git", "get_keywords")
|
||||||
|
def git_get_keywords(versionfile_abs):
|
||||||
|
"""Extract version information from the given file."""
|
||||||
|
# the code embedded in _version.py can just fetch the value of these
|
||||||
|
# keywords. When used from setup.py, we don't want to import _version.py,
|
||||||
|
# so we do it with a regexp instead. This function is not used from
|
||||||
|
# _version.py.
|
||||||
|
keywords = {}
|
||||||
|
try:
|
||||||
|
with open(versionfile_abs, "r") as fobj:
|
||||||
|
for line in fobj:
|
||||||
|
if line.strip().startswith("git_refnames ="):
|
||||||
|
mo = re.search(r'=\s*"(.*)"', line)
|
||||||
|
if mo:
|
||||||
|
keywords["refnames"] = mo.group(1)
|
||||||
|
if line.strip().startswith("git_full ="):
|
||||||
|
mo = re.search(r'=\s*"(.*)"', line)
|
||||||
|
if mo:
|
||||||
|
keywords["full"] = mo.group(1)
|
||||||
|
if line.strip().startswith("git_date ="):
|
||||||
|
mo = re.search(r'=\s*"(.*)"', line)
|
||||||
|
if mo:
|
||||||
|
keywords["date"] = mo.group(1)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return keywords
|
||||||
|
|
||||||
|
|
||||||
|
@register_vcs_handler("git", "keywords")
|
||||||
|
def git_versions_from_keywords(keywords, tag_prefix, verbose):
|
||||||
|
"""Get version information from git keywords."""
|
||||||
|
if "refnames" not in keywords:
|
||||||
|
raise NotThisMethod("Short version file found")
|
||||||
|
date = keywords.get("date")
|
||||||
|
if date is not None:
|
||||||
|
# Use only the last line. Previous lines may contain GPG signature
|
||||||
|
# information.
|
||||||
|
date = date.splitlines()[-1]
|
||||||
|
|
||||||
|
# git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
|
||||||
|
# datestamp. However we prefer "%ci" (which expands to an "ISO-8601
|
||||||
|
# -like" string, which we must then edit to make compliant), because
|
||||||
|
# it's been around since git-1.5.3, and it's too difficult to
|
||||||
|
# discover which version we're using, or to work around using an
|
||||||
|
# older one.
|
||||||
|
date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
|
||||||
|
refnames = keywords["refnames"].strip()
|
||||||
|
if refnames.startswith("$Format"):
|
||||||
|
if verbose:
|
||||||
|
print("keywords are unexpanded, not using")
|
||||||
|
raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
|
||||||
|
refs = {r.strip() for r in refnames.strip("()").split(",")}
|
||||||
|
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
|
||||||
|
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
|
||||||
|
TAG = "tag: "
|
||||||
|
tags = {r[len(TAG):] for r in refs if r.startswith(TAG)}
|
||||||
|
if not tags:
|
||||||
|
# Either we're using git < 1.8.3, or there really are no tags. We use
|
||||||
|
# a heuristic: assume all version tags have a digit. The old git %d
|
||||||
|
# expansion behaves like git log --decorate=short and strips out the
|
||||||
|
# refs/heads/ and refs/tags/ prefixes that would let us distinguish
|
||||||
|
# between branches and tags. By ignoring refnames without digits, we
|
||||||
|
# filter out many common branch names like "release" and
|
||||||
|
# "stabilization", as well as "HEAD" and "master".
|
||||||
|
tags = {r for r in refs if re.search(r'\d', r)}
|
||||||
|
if verbose:
|
||||||
|
print("discarding '%s', no digits" % ",".join(refs - tags))
|
||||||
|
if verbose:
|
||||||
|
print("likely tags: %s" % ",".join(sorted(tags)))
|
||||||
|
for ref in sorted(tags):
|
||||||
|
# sorting will prefer e.g. "2.0" over "2.0rc1"
|
||||||
|
if ref.startswith(tag_prefix):
|
||||||
|
r = ref[len(tag_prefix):]
|
||||||
|
# Filter out refs that exactly match prefix or that don't start
|
||||||
|
# with a number once the prefix is stripped (mostly a concern
|
||||||
|
# when prefix is '')
|
||||||
|
if not re.match(r'\d', r):
|
||||||
|
continue
|
||||||
|
if verbose:
|
||||||
|
print("picking %s" % r)
|
||||||
|
return {"version": r,
|
||||||
|
"full-revisionid": keywords["full"].strip(),
|
||||||
|
"dirty": False, "error": None,
|
||||||
|
"date": date}
|
||||||
|
# no suitable tags, so version is "0+unknown", but full hex is still there
|
||||||
|
if verbose:
|
||||||
|
print("no suitable tags, using unknown + full revision id")
|
||||||
|
return {"version": "0+unknown",
|
||||||
|
"full-revisionid": keywords["full"].strip(),
|
||||||
|
"dirty": False, "error": "no suitable tags", "date": None}
|
||||||
|
|
||||||
|
|
||||||
|
@register_vcs_handler("git", "pieces_from_vcs")
|
||||||
|
def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
|
||||||
|
"""Get version from 'git describe' in the root of the source tree.
|
||||||
|
|
||||||
|
This only gets called if the git-archive 'subst' keywords were *not*
|
||||||
|
expanded, and _version.py hasn't already been rewritten with a short
|
||||||
|
version string, meaning we're inside a checked out source tree.
|
||||||
|
"""
|
||||||
|
GITS = ["git"]
|
||||||
|
TAG_PREFIX_REGEX = "*"
|
||||||
|
if sys.platform == "win32":
|
||||||
|
GITS = ["git.cmd", "git.exe"]
|
||||||
|
TAG_PREFIX_REGEX = r"\*"
|
||||||
|
|
||||||
|
_, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root,
|
||||||
|
hide_stderr=True)
|
||||||
|
if rc != 0:
|
||||||
|
if verbose:
|
||||||
|
print("Directory %s not under git control" % root)
|
||||||
|
raise NotThisMethod("'git rev-parse --git-dir' returned error")
|
||||||
|
|
||||||
|
# if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
|
||||||
|
# if there isn't one, this yields HEX[-dirty] (no NUM)
|
||||||
|
describe_out, rc = runner(GITS, ["describe", "--tags", "--dirty",
|
||||||
|
"--always", "--long",
|
||||||
|
"--match",
|
||||||
|
"%s%s" % (tag_prefix, TAG_PREFIX_REGEX)],
|
||||||
|
cwd=root)
|
||||||
|
# --long was added in git-1.5.5
|
||||||
|
if describe_out is None:
|
||||||
|
raise NotThisMethod("'git describe' failed")
|
||||||
|
describe_out = describe_out.strip()
|
||||||
|
full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root)
|
||||||
|
if full_out is None:
|
||||||
|
raise NotThisMethod("'git rev-parse' failed")
|
||||||
|
full_out = full_out.strip()
|
||||||
|
|
||||||
|
pieces = {}
|
||||||
|
pieces["long"] = full_out
|
||||||
|
pieces["short"] = full_out[:7] # maybe improved later
|
||||||
|
pieces["error"] = None
|
||||||
|
|
||||||
|
branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
|
||||||
|
cwd=root)
|
||||||
|
# --abbrev-ref was added in git-1.6.3
|
||||||
|
if rc != 0 or branch_name is None:
|
||||||
|
raise NotThisMethod("'git rev-parse --abbrev-ref' returned error")
|
||||||
|
branch_name = branch_name.strip()
|
||||||
|
|
||||||
|
if branch_name == "HEAD":
|
||||||
|
# If we aren't exactly on a branch, pick a branch which represents
|
||||||
|
# the current commit. If all else fails, we are on a branchless
|
||||||
|
# commit.
|
||||||
|
branches, rc = runner(GITS, ["branch", "--contains"], cwd=root)
|
||||||
|
# --contains was added in git-1.5.4
|
||||||
|
if rc != 0 or branches is None:
|
||||||
|
raise NotThisMethod("'git branch --contains' returned error")
|
||||||
|
branches = branches.split("\n")
|
||||||
|
|
||||||
|
# Remove the first line if we're running detached
|
||||||
|
if "(" in branches[0]:
|
||||||
|
branches.pop(0)
|
||||||
|
|
||||||
|
# Strip off the leading "* " from the list of branches.
|
||||||
|
branches = [branch[2:] for branch in branches]
|
||||||
|
if "master" in branches:
|
||||||
|
branch_name = "master"
|
||||||
|
elif not branches:
|
||||||
|
branch_name = None
|
||||||
|
else:
|
||||||
|
# Pick the first branch that is returned. Good or bad.
|
||||||
|
branch_name = branches[0]
|
||||||
|
|
||||||
|
pieces["branch"] = branch_name
|
||||||
|
|
||||||
|
# parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
|
||||||
|
# TAG might have hyphens.
|
||||||
|
git_describe = describe_out
|
||||||
|
|
||||||
|
# look for -dirty suffix
|
||||||
|
dirty = git_describe.endswith("-dirty")
|
||||||
|
pieces["dirty"] = dirty
|
||||||
|
if dirty:
|
||||||
|
git_describe = git_describe[:git_describe.rindex("-dirty")]
|
||||||
|
|
||||||
|
# now we have TAG-NUM-gHEX or HEX
|
||||||
|
|
||||||
|
if "-" in git_describe:
|
||||||
|
# TAG-NUM-gHEX
|
||||||
|
mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
|
||||||
|
if not mo:
|
||||||
|
# unparsable. Maybe git-describe is misbehaving?
|
||||||
|
pieces["error"] = ("unable to parse git-describe output: '%s'"
|
||||||
|
% describe_out)
|
||||||
|
return pieces
|
||||||
|
|
||||||
|
# tag
|
||||||
|
full_tag = mo.group(1)
|
||||||
|
if not full_tag.startswith(tag_prefix):
|
||||||
|
if verbose:
|
||||||
|
fmt = "tag '%s' doesn't start with prefix '%s'"
|
||||||
|
print(fmt % (full_tag, tag_prefix))
|
||||||
|
pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
|
||||||
|
% (full_tag, tag_prefix))
|
||||||
|
return pieces
|
||||||
|
pieces["closest-tag"] = full_tag[len(tag_prefix):]
|
||||||
|
|
||||||
|
# distance: number of commits since tag
|
||||||
|
pieces["distance"] = int(mo.group(2))
|
||||||
|
|
||||||
|
# commit: short hex revision ID
|
||||||
|
pieces["short"] = mo.group(3)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# HEX: no tags
|
||||||
|
pieces["closest-tag"] = None
|
||||||
|
count_out, rc = runner(GITS, ["rev-list", "HEAD", "--count"], cwd=root)
|
||||||
|
pieces["distance"] = int(count_out) # total number of commits
|
||||||
|
|
||||||
|
# commit date: see ISO-8601 comment in git_versions_from_keywords()
|
||||||
|
date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip()
|
||||||
|
# Use only the last line. Previous lines may contain GPG signature
|
||||||
|
# information.
|
||||||
|
date = date.splitlines()[-1]
|
||||||
|
pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
|
||||||
|
|
||||||
|
return pieces
|
||||||
|
|
||||||
|
|
||||||
|
def plus_or_dot(pieces):
|
||||||
|
"""Return a + if we don't already have one, else return a ."""
|
||||||
|
if "+" in pieces.get("closest-tag", ""):
|
||||||
|
return "."
|
||||||
|
return "+"
|
||||||
|
|
||||||
|
|
||||||
|
def render_pep440(pieces):
|
||||||
|
"""Build up version string, with post-release "local version identifier".
|
||||||
|
|
||||||
|
Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
|
||||||
|
get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
if pieces["distance"] or pieces["dirty"]:
|
||||||
|
rendered += plus_or_dot(pieces)
|
||||||
|
rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dirty"
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = "0+untagged.%d.g%s" % (pieces["distance"],
|
||||||
|
pieces["short"])
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dirty"
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def render_pep440_branch(pieces):
|
||||||
|
"""TAG[[.dev0]+DISTANCE.gHEX[.dirty]] .
|
||||||
|
|
||||||
|
The ".dev0" means not master branch. Note that .dev0 sorts backwards
|
||||||
|
(a feature branch will appear "older" than the master branch).
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty]
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
if pieces["distance"] or pieces["dirty"]:
|
||||||
|
if pieces["branch"] != "master":
|
||||||
|
rendered += ".dev0"
|
||||||
|
rendered += plus_or_dot(pieces)
|
||||||
|
rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dirty"
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = "0"
|
||||||
|
if pieces["branch"] != "master":
|
||||||
|
rendered += ".dev0"
|
||||||
|
rendered += "+untagged.%d.g%s" % (pieces["distance"],
|
||||||
|
pieces["short"])
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dirty"
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def pep440_split_post(ver):
|
||||||
|
"""Split pep440 version string at the post-release segment.
|
||||||
|
|
||||||
|
Returns the release segments before the post-release and the
|
||||||
|
post-release version number (or -1 if no post-release segment is present).
|
||||||
|
"""
|
||||||
|
vc = str.split(ver, ".post")
|
||||||
|
return vc[0], int(vc[1] or 0) if len(vc) == 2 else None
|
||||||
|
|
||||||
|
|
||||||
|
def render_pep440_pre(pieces):
|
||||||
|
"""TAG[.postN.devDISTANCE] -- No -dirty.
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. 0.post0.devDISTANCE
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
if pieces["distance"]:
|
||||||
|
# update the post release segment
|
||||||
|
tag_version, post_version = pep440_split_post(pieces["closest-tag"])
|
||||||
|
rendered = tag_version
|
||||||
|
if post_version is not None:
|
||||||
|
rendered += ".post%d.dev%d" % (post_version+1, pieces["distance"])
|
||||||
|
else:
|
||||||
|
rendered += ".post0.dev%d" % (pieces["distance"])
|
||||||
|
else:
|
||||||
|
# no commits, use the tag as the version
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = "0.post0.dev%d" % pieces["distance"]
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def render_pep440_post(pieces):
|
||||||
|
"""TAG[.postDISTANCE[.dev0]+gHEX] .
|
||||||
|
|
||||||
|
The ".dev0" means dirty. Note that .dev0 sorts backwards
|
||||||
|
(a dirty tree will appear "older" than the corresponding clean one),
|
||||||
|
but you shouldn't be releasing software with -dirty anyways.
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. 0.postDISTANCE[.dev0]
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
if pieces["distance"] or pieces["dirty"]:
|
||||||
|
rendered += ".post%d" % pieces["distance"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dev0"
|
||||||
|
rendered += plus_or_dot(pieces)
|
||||||
|
rendered += "g%s" % pieces["short"]
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = "0.post%d" % pieces["distance"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dev0"
|
||||||
|
rendered += "+g%s" % pieces["short"]
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def render_pep440_post_branch(pieces):
|
||||||
|
"""TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] .
|
||||||
|
|
||||||
|
The ".dev0" means not master branch.
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty]
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
if pieces["distance"] or pieces["dirty"]:
|
||||||
|
rendered += ".post%d" % pieces["distance"]
|
||||||
|
if pieces["branch"] != "master":
|
||||||
|
rendered += ".dev0"
|
||||||
|
rendered += plus_or_dot(pieces)
|
||||||
|
rendered += "g%s" % pieces["short"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dirty"
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = "0.post%d" % pieces["distance"]
|
||||||
|
if pieces["branch"] != "master":
|
||||||
|
rendered += ".dev0"
|
||||||
|
rendered += "+g%s" % pieces["short"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dirty"
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def render_pep440_old(pieces):
|
||||||
|
"""TAG[.postDISTANCE[.dev0]] .
|
||||||
|
|
||||||
|
The ".dev0" means dirty.
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. 0.postDISTANCE[.dev0]
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
if pieces["distance"] or pieces["dirty"]:
|
||||||
|
rendered += ".post%d" % pieces["distance"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dev0"
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = "0.post%d" % pieces["distance"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += ".dev0"
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def render_git_describe(pieces):
|
||||||
|
"""TAG[-DISTANCE-gHEX][-dirty].
|
||||||
|
|
||||||
|
Like 'git describe --tags --dirty --always'.
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. HEX[-dirty] (note: no 'g' prefix)
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
if pieces["distance"]:
|
||||||
|
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = pieces["short"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += "-dirty"
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def render_git_describe_long(pieces):
|
||||||
|
"""TAG-DISTANCE-gHEX[-dirty].
|
||||||
|
|
||||||
|
Like 'git describe --tags --dirty --always -long'.
|
||||||
|
The distance/hash is unconditional.
|
||||||
|
|
||||||
|
Exceptions:
|
||||||
|
1: no tags. HEX[-dirty] (note: no 'g' prefix)
|
||||||
|
"""
|
||||||
|
if pieces["closest-tag"]:
|
||||||
|
rendered = pieces["closest-tag"]
|
||||||
|
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
|
||||||
|
else:
|
||||||
|
# exception #1
|
||||||
|
rendered = pieces["short"]
|
||||||
|
if pieces["dirty"]:
|
||||||
|
rendered += "-dirty"
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def render(pieces, style):
|
||||||
|
"""Render the given version pieces into the requested style."""
|
||||||
|
if pieces["error"]:
|
||||||
|
return {"version": "unknown",
|
||||||
|
"full-revisionid": pieces.get("long"),
|
||||||
|
"dirty": None,
|
||||||
|
"error": pieces["error"],
|
||||||
|
"date": None}
|
||||||
|
|
||||||
|
if not style or style == "default":
|
||||||
|
style = "pep440" # the default
|
||||||
|
|
||||||
|
if style == "pep440":
|
||||||
|
rendered = render_pep440(pieces)
|
||||||
|
elif style == "pep440-branch":
|
||||||
|
rendered = render_pep440_branch(pieces)
|
||||||
|
elif style == "pep440-pre":
|
||||||
|
rendered = render_pep440_pre(pieces)
|
||||||
|
elif style == "pep440-post":
|
||||||
|
rendered = render_pep440_post(pieces)
|
||||||
|
elif style == "pep440-post-branch":
|
||||||
|
rendered = render_pep440_post_branch(pieces)
|
||||||
|
elif style == "pep440-old":
|
||||||
|
rendered = render_pep440_old(pieces)
|
||||||
|
elif style == "git-describe":
|
||||||
|
rendered = render_git_describe(pieces)
|
||||||
|
elif style == "git-describe-long":
|
||||||
|
rendered = render_git_describe_long(pieces)
|
||||||
|
else:
|
||||||
|
raise ValueError("unknown style '%s'" % style)
|
||||||
|
|
||||||
|
return {"version": rendered, "full-revisionid": pieces["long"],
|
||||||
|
"dirty": pieces["dirty"], "error": None,
|
||||||
|
"date": pieces.get("date")}
|
||||||
|
|
||||||
|
|
||||||
|
def get_versions():
|
||||||
|
"""Get version information or return default if unable to do so."""
|
||||||
|
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
|
||||||
|
# __file__, we can work backwards from there to the root. Some
|
||||||
|
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
|
||||||
|
# case we can only use expanded keywords.
|
||||||
|
|
||||||
|
cfg = get_config()
|
||||||
|
verbose = cfg.verbose
|
||||||
|
|
||||||
|
try:
|
||||||
|
return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
|
||||||
|
verbose)
|
||||||
|
except NotThisMethod:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
root = os.path.realpath(__file__)
|
||||||
|
# versionfile_source is the relative path from the top of the source
|
||||||
|
# tree (where the .git directory might live) to this file. Invert
|
||||||
|
# this to find the root from __file__.
|
||||||
|
for _ in cfg.versionfile_source.split('/'):
|
||||||
|
root = os.path.dirname(root)
|
||||||
|
except NameError:
|
||||||
|
return {"version": "0+unknown", "full-revisionid": None,
|
||||||
|
"dirty": None,
|
||||||
|
"error": "unable to find root of source tree",
|
||||||
|
"date": None}
|
||||||
|
|
||||||
|
try:
|
||||||
|
pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
|
||||||
|
return render(pieces, cfg.style)
|
||||||
|
except NotThisMethod:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
if cfg.parentdir_prefix:
|
||||||
|
return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
|
||||||
|
except NotThisMethod:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return {"version": "0+unknown", "full-revisionid": None,
|
||||||
|
"dirty": None,
|
||||||
|
"error": "unable to compute version", "date": None}
|
151
custom-plugins/mkdocs-plugin-tags/tags/plugin.py
Normal file
151
custom-plugins/mkdocs-plugin-tags/tags/plugin.py
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
This plugin generates tags file as well as inserts markdown
|
||||||
|
at the beginning of a file that has tags
|
||||||
|
|
||||||
|
@Adopted from
|
||||||
|
JL Diaz (c) 2019
|
||||||
|
MIT License
|
||||||
|
"""
|
||||||
|
from collections import defaultdict
|
||||||
|
from pathlib import Path
|
||||||
|
from re import search, DOTALL, MULTILINE
|
||||||
|
from yaml import load, FullLoader, YAMLError
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
from mkdocs.structure.files import File
|
||||||
|
from mkdocs.plugins import BasePlugin
|
||||||
|
from mkdocs.config.config_options import Type
|
||||||
|
from mkdocs.__main__ import log
|
||||||
|
|
||||||
|
class TagsPlugin(BasePlugin):
|
||||||
|
"""
|
||||||
|
Creates "tags.md" file containing a list of the pages grouped by tags
|
||||||
|
|
||||||
|
It uses the info in the YAML metadata of each page, for the pages which
|
||||||
|
provide a "tags" keyword (whose value is a list of strings)
|
||||||
|
"""
|
||||||
|
config_scheme = (
|
||||||
|
('filename', Type(str, default='tags.md')),
|
||||||
|
('folder', Type(str, default='aux')),
|
||||||
|
('template', Type(str)),
|
||||||
|
('css_name', Type(str, default='.button')),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.metadata = []
|
||||||
|
self.tag_dict = None
|
||||||
|
self.filename = "tags.md"
|
||||||
|
self.folder = "aux"
|
||||||
|
self.template = None
|
||||||
|
self.css_name = ".button"
|
||||||
|
self.templ = None
|
||||||
|
|
||||||
|
#pylint: disable=unused-argument
|
||||||
|
def on_page_markdown(self, markdown, page, config, files):
|
||||||
|
"""
|
||||||
|
takes markdown, page, config, and files
|
||||||
|
currently modifies the markdown to add a button to click to get related tag info
|
||||||
|
tag is customizeable by adding css that keys off the `self.css_name`
|
||||||
|
"""
|
||||||
|
|
||||||
|
page_url = page.url.split("/")
|
||||||
|
tags_link = ''
|
||||||
|
|
||||||
|
for i in range(len(page_url) - 1):
|
||||||
|
tags_link = tags_link + '../'
|
||||||
|
|
||||||
|
tags_link = tags_link + str(self.filename).strip('.md')
|
||||||
|
|
||||||
|
if tags_link[-1] != '/':
|
||||||
|
tags_link = tags_link + '/'
|
||||||
|
|
||||||
|
if 'tags' in page.meta:
|
||||||
|
swap_mark = [f"[{x}]({tags_link}#{x.lower()}){{{self.css_name}}}"
|
||||||
|
for x in page.meta['tags']]
|
||||||
|
swap_mark.append('\n')
|
||||||
|
return f'{" ".join(swap_mark)}{markdown}'
|
||||||
|
return markdown
|
||||||
|
|
||||||
|
def on_config(self, config):
|
||||||
|
"""Load config options"""
|
||||||
|
self.filename = Path(self.config.get("filename") or self.filename)
|
||||||
|
self.folder = Path(self.config.get("folder") or self.folder)
|
||||||
|
self.css_name = self.config.get("css_name")
|
||||||
|
# Make sure that the tags folder is absolute, and exists
|
||||||
|
if not self.folder.is_absolute():
|
||||||
|
self.folder = Path(config["docs_dir"]) / ".." / self.folder
|
||||||
|
if not self.folder.exists():
|
||||||
|
self.folder.mkdir(parents=True)
|
||||||
|
|
||||||
|
if self.config.get("template"):
|
||||||
|
self.template = Path(self.config.get("template"))
|
||||||
|
if self.template is None:
|
||||||
|
self.template = Path(__file__).parent.joinpath(
|
||||||
|
"templates"
|
||||||
|
).joinpath("tags.md.template")
|
||||||
|
environment = Environment(
|
||||||
|
loader=FileSystemLoader(searchpath=str(self.template.parent))
|
||||||
|
)
|
||||||
|
self.templ = environment.get_template(str(self.template.name))
|
||||||
|
|
||||||
|
def on_files(self, files, config):
|
||||||
|
"""Load files to check for tags"""
|
||||||
|
self.metadata = [
|
||||||
|
get_metadata(x.src_path, config['docs_dir'])
|
||||||
|
for x in files if x.src_path.endswith(".md")
|
||||||
|
]
|
||||||
|
# Create new file with tags
|
||||||
|
self.generate_tags_file()
|
||||||
|
# New file to add to the build
|
||||||
|
newfile = File(
|
||||||
|
path=str(self.filename),
|
||||||
|
src_dir=str(self.folder),
|
||||||
|
dest_dir=config["site_dir"],
|
||||||
|
use_directory_urls=False
|
||||||
|
)
|
||||||
|
files.append(newfile)
|
||||||
|
|
||||||
|
def generate_tags_page(self, data):
|
||||||
|
"""Generate the tags to be populated on the
|
||||||
|
mkdocs tag page"""
|
||||||
|
|
||||||
|
css_name = self.css_name
|
||||||
|
|
||||||
|
if css_name[0:1] == '.':
|
||||||
|
css_name = css_name[1:len(css_name)]
|
||||||
|
return self.templ.render(
|
||||||
|
tags=sorted(data.items(), key=lambda t: t[0].lower()),
|
||||||
|
css_name = css_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
def generate_tags_file(self):
|
||||||
|
"""Generate a file to be stored on the mkdocs page"""
|
||||||
|
sorted_meta = sorted(self.metadata, key=lambda e: e.get("year", 5000) if e else 0)
|
||||||
|
self.tag_dict = defaultdict(list)
|
||||||
|
for meta in sorted_meta:
|
||||||
|
if not meta:
|
||||||
|
continue
|
||||||
|
if "title" not in meta:
|
||||||
|
meta["title"] = meta['filename'].split("/")[-1].strip('.md')
|
||||||
|
tags = meta.get("tags", [])
|
||||||
|
for tag in tags:
|
||||||
|
self.tag_dict[tag].append(meta)
|
||||||
|
|
||||||
|
with open(str(self.folder / self.filename), "w", encoding='utf-8') as fname:
|
||||||
|
fname.write(self.generate_tags_page(self.tag_dict))
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
def get_metadata(name, path):
|
||||||
|
"""Get the metadata off of a file"""
|
||||||
|
filename = Path(path) / Path(name)
|
||||||
|
with filename.open() as fname:
|
||||||
|
match_string = search(r"\A\s*---\n.*?\n---", fname.read(), flags=DOTALL | MULTILINE)
|
||||||
|
if match_string:
|
||||||
|
try:
|
||||||
|
metadata = match_string.group(0).strip('---')
|
||||||
|
meta = load(metadata, Loader=FullLoader)
|
||||||
|
meta.update(filename=name)
|
||||||
|
return meta
|
||||||
|
except YAMLError as err:
|
||||||
|
log.error("Couldn't parse %s yaml due to %s", fname, err)
|
||||||
|
return None
|
@ -0,0 +1,6 @@
|
|||||||
|
# Contents grouped by tag
|
||||||
|
{% for tag, pages in tags %}
|
||||||
|
## <span class="{{css_name}}">{{tag}}</span>
|
||||||
|
{% for page in pages %}
|
||||||
|
* [{{page.title}}]({{page.filename}})
|
||||||
|
{% endfor %}{% endfor %}
|
Submodule gitlab-ci updated: 1ef6c41818...ce1cc017e2
159
mkdocs.yml
Normal file
159
mkdocs.yml
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
site_name: No Fuss Computing
|
||||||
|
site_description: A wiki with random bits of information you may find useful.
|
||||||
|
site_url: https://nofusscomputing.com
|
||||||
|
|
||||||
|
site_author: No Fuss Computing
|
||||||
|
copyright: Copyright © No Fuss Computing 2021
|
||||||
|
|
||||||
|
#site_favicon: favicon.ico
|
||||||
|
# site_dir: 'docs/static/mkdocs_build'
|
||||||
|
|
||||||
|
docs_dir: 'pages'
|
||||||
|
site_dir: build
|
||||||
|
|
||||||
|
repo_name: Website
|
||||||
|
#repo_url: https://gitlab.com/nofusscomputing/infrastructure/website
|
||||||
|
repo_url: https://gitlab.com/nofusscomputing/infrastructure/website
|
||||||
|
#edit_uri: '-/blob/pages'
|
||||||
|
#edit_uri: '-/blob/master/pages/'
|
||||||
|
edit_uri: ''
|
||||||
|
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
logo: assets/logo.png
|
||||||
|
custom_dir: theme-overrides
|
||||||
|
icon:
|
||||||
|
repo: fontawesome/brands/gitlab # (1)!
|
||||||
|
locale: en
|
||||||
|
font: false
|
||||||
|
features:
|
||||||
|
- navigation.tracking
|
||||||
|
- navigation.tabs
|
||||||
|
- navigation.tabs.sticky
|
||||||
|
- navigation.expand
|
||||||
|
- navigation.indexes
|
||||||
|
- toc.integrate
|
||||||
|
- navigation.top
|
||||||
|
- header.autohide
|
||||||
|
- navigation.sections
|
||||||
|
|
||||||
|
palette:
|
||||||
|
- scheme: default
|
||||||
|
primary: indigo
|
||||||
|
accent: indigo
|
||||||
|
toggle:
|
||||||
|
icon: material/lightbulb-outline
|
||||||
|
name: Switch to dark mode
|
||||||
|
- scheme: slate
|
||||||
|
primary: indigo
|
||||||
|
accent: indigo
|
||||||
|
toggle:
|
||||||
|
icon: material/lightbulb
|
||||||
|
name: Switch to light mode
|
||||||
|
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- tags:
|
||||||
|
filename: tags.md
|
||||||
|
folder: pages
|
||||||
|
css_name: ".tags"
|
||||||
|
- search:
|
||||||
|
lang: en
|
||||||
|
|
||||||
|
- git-revision-date-localized:
|
||||||
|
type: iso_date
|
||||||
|
enable_creation_date: true
|
||||||
|
exclude:
|
||||||
|
- index.md
|
||||||
|
- tags.md
|
||||||
|
# - minify:
|
||||||
|
# minify_html: true
|
||||||
|
|
||||||
|
extra:
|
||||||
|
homepage: https://nofusscomputing.com
|
||||||
|
version: 1.0
|
||||||
|
social:
|
||||||
|
- link: https://hub.docker.com/u/nofusscomputing
|
||||||
|
name: DockerHub
|
||||||
|
icon: fontawesome/brands/docker
|
||||||
|
|
||||||
|
- link: https://facebook.com/NoFussComputing
|
||||||
|
name: Facebook
|
||||||
|
icon: fontawesome/brands/facebook
|
||||||
|
|
||||||
|
- link: https://gitlab.com/nofusscomputing
|
||||||
|
name: Gitlab
|
||||||
|
icon: fontawesome/brands/gitlab
|
||||||
|
|
||||||
|
- link: https://github.com/NoFussComputing
|
||||||
|
name: Github
|
||||||
|
icon: fontawesome/brands/github
|
||||||
|
|
||||||
|
# - link: https://readthedocs.org/profiles/nofusscomputing/
|
||||||
|
# nane: ReadTheDocs
|
||||||
|
# icon: fontawesome/brands/readthedocs
|
||||||
|
# link: https://
|
||||||
|
blog:
|
||||||
|
dir: articles
|
||||||
|
author: jon_nfc
|
||||||
|
author_image: https://gitlab.com/uploads/-/system/user/avatar/4125177/avatar.png
|
||||||
|
words_read_per_minute: 300
|
||||||
|
list_length: 25
|
||||||
|
extended_preview: true
|
||||||
|
|
||||||
|
extra_css:
|
||||||
|
- stylesheets/extra.css
|
||||||
|
|
||||||
|
|
||||||
|
markdown_extensions:
|
||||||
|
- def_list
|
||||||
|
- pymdownx.tasklist:
|
||||||
|
custom_checkbox: true
|
||||||
|
- meta
|
||||||
|
- attr_list
|
||||||
|
- admonition
|
||||||
|
- pymdownx.details
|
||||||
|
- pymdownx.superfences
|
||||||
|
# - pymdownx.emoji:
|
||||||
|
# emoji_index: !!python/name:materialx.emoji.twemoji
|
||||||
|
# emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||||
|
# options:
|
||||||
|
# custom_icons:
|
||||||
|
# - .icons
|
||||||
|
nav:
|
||||||
|
- Home: index.md
|
||||||
|
|
||||||
|
- Articles:
|
||||||
|
|
||||||
|
- articles/index.md
|
||||||
|
|
||||||
|
- 2015:
|
||||||
|
|
||||||
|
- articles/2015/choose_internet_service.md
|
||||||
|
|
||||||
|
- Content Tags: tags.md
|
||||||
|
|
||||||
|
- Projects:
|
||||||
|
|
||||||
|
- projects/index.md
|
||||||
|
|
||||||
|
- Ansible Roles: projects/ansible-roles/README.md
|
||||||
|
|
||||||
|
- Gitlab CI Templates: projects/gitlab-ci/README.md
|
||||||
|
|
||||||
|
- Python Gitlab Management: projects/python-gitlab-management/README.md
|
||||||
|
|
||||||
|
- Operations:
|
||||||
|
|
||||||
|
- operations/index.md
|
||||||
|
|
||||||
|
- Development:
|
||||||
|
|
||||||
|
- operations/syntax.md
|
||||||
|
|
||||||
|
- Wiki:
|
||||||
|
|
||||||
|
- wiki/index.md
|
||||||
|
|
||||||
|
- Contact Us: contact.md
|
||||||
|
|
150
pages/articles/2015/choose_internet_service.md
Normal file
150
pages/articles/2015/choose_internet_service.md
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
template: blog_post.html
|
||||||
|
title: Choosing an Internet Service
|
||||||
|
description: The Internet has now become a mainstream item within the average Australian home. The Internet has become so ingrained within our daily lives that for those of us that were around when the Internet was born have actually forgotten what life was like without it. I remember when I was growing up that if we wanted to learn about something you would go to the local library or to a family/friends house to look through their Encyclopaedia Britannica which more often than not was at least five years out of date. Believe it or not that was only 15 to 20 years ago. Now if I haven't lost you already and hopefully by the end of this article I have been able to provide you with more insight on being able to choose an Internet service from an ISP with a little more of an understanding of the technology behind that Internet connection.
|
||||||
|
date: 2015-02-25
|
||||||
|
tags:
|
||||||
|
- ADSL
|
||||||
|
- Archive
|
||||||
|
- Article
|
||||||
|
- Broadband
|
||||||
|
- Internet
|
||||||
|
- NBN
|
||||||
|
- Australia
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
This article has been targeted towards the common mass who don’t understand the technical details and considerations for choosing an Internet package.
|
||||||
|
|
||||||
|
The Internet has now become a mainstream item within the average Australian home. The Internet has become so ingrained within our daily lives that for those of us that were around when the Internet was born have actually forgotten what life was like without it. I remember when I was growing up that if we wanted to learn about something you would go to the local library or to a family/friends house to look through their Encyclopaedia Britannica which more often than not was at least five years out of date. Believe it or not that was only 15 to 20 years ago. I would consider myself lucky in the regard we were introduced to the Internet in high school way back when Web Crawler was what Google is today and the only thing of any value was searching for random phrases like <s>porn</s> homework answers. It was a very new concept to have the Internet or even access, which was often met with confusion and a sheer lack of knowledge. Being part of that generation we grew with the Internet and became the first generation to learn about it, and to the behest of the generations before us who were either left in the dark or were very slow on the uptake.
|
||||||
|
|
||||||
|
Now if I haven't lost you already and hopefully by the end of this article I have been able to provide you with more insight on being able to choose an Internet service from an ISP with a little more of an understanding of the technology behind that Internet connection.
|
||||||
|
|
||||||
|
Below I will cover a little of the technical details and hopefully bringing into perspective, so you can better understand what is being explained to you. To do this I will use the flow of water methodology.
|
||||||
|
|
||||||
|
<p hidden>#more</p>
|
||||||
|
|
||||||
|
## Bandwidth
|
||||||
|
|
||||||
|
Bandwidth is the actual speed of your Internet connection and its unit of measure is bits per second. So basically if you think water pipe, only so much water will flow through a water pipe but if you increase it’s pressure you will receive more water. For the actual Internet connection different technology is used to essentially achieve the same
|
||||||
|
thing.
|
||||||
|
|
||||||
|
## Quota
|
||||||
|
|
||||||
|
This is how much you can download and/or upload from the Internet. Its unit of measure is bytes. Think of a water tank, larger the tank the more quota you have available. This will be set by your ISP and 9 times out of 10 will be limited. Every Time you connect to the Internet you are using this available quota.
|
||||||
|
|
||||||
|
## Theory
|
||||||
|
|
||||||
|
Now to fully understand the quota and bandwidth I will have to cover a little bit of computer theory. Computers compute information by doing mathematical equations. The only numbers a computer recognizes are Base 2. Base 2 numbering means it uses the first 2 numbers, being zero and one. In common computer terms this is called binary which is always in the computer world as a minimum 8 bits wide i.e. 01010101. Each digit of the number is a bit, four bits to a nibble and 2 nibbles to a byte. Unlike the English language; Binary is read from right to left and each one or zero, within a binary number is actually counting from 1 through to 255, which takes 8 bits of information. Binary is a notational reference system, so starting from right to left each digit represents another number, the first number being one, each number after that is double the number before it so the next number would be two, then four, eight, 16, 32, 64 finishing with the leftmost digit as 128. Confusing? Not really, when the bit is zero you don't add each notated number, you only add if the bit is one. So 0001 would be one, 0010 would be two, 0011 is three and so on.
|
||||||
|
|
||||||
|
Communication between different components or computers (network or The Internet) is measured in bits per second or bps (lowercase). Computers store data in bytes or B (uppercase). Each unit of measure has multipliers like normal numbers, computers use the following multipliers, Kilo (K) for thousands, Mega (M) for millions, Giga (G) for billions, Tera (T) for trillions and Peta (P) for quintillion's. The conversion from bits to bytes is a division of 8.
|
||||||
|
|
||||||
|
So why use different units of measure for the same data? simply put, computers are electronic devices which communicate with an electronic signal with 1 being on and zero being off; basically the signal is either on or off. So the transmission of data is serial or singular and storage is in parallel or stored in octets which is a group of bits. Hence bits and bytes. generally you will find lowercase letters are used to represent bits and uppercase letters are used for bytes.
|
||||||
|
|
||||||
|
### Connection types
|
||||||
|
|
||||||
|
The common Internet connection types in Australia are ADSL or via the Mobile network. Very rarely used but still available if you look hard enough dial-up. and the newest and greatest is the National Broadband Network or NBN. With the exception of the NBN all of the above connection types will have a max speed. This max speed is a theoretical maximum speed and there are many factors which generally slow down your connection. All connection methods have a technological peak, which basically means there is no known way to improve that technology any further.
|
||||||
|
|
||||||
|
### Dial-Up
|
||||||
|
|
||||||
|
Dial-UpInternet was the first mainstream way to connect to the Internet. For this to happen you needed an active phone line, a computer with a MODEM (short for modulator/demodulator) and you would plug a phone cable into your computer, which would dial a number to connect to the Internet. At its technological peak the max theoretical download speed was 56kb and approx 33kb up. Dial-up modems are generally part of the computer. The downside to Dial-up is that it relies on good quality phone cables, basically if you have a bad phone line you will have unstable and slower Internet. Dial-up also suffers from signal attenuation which means the further away from the telephone exchange the lower the speed your Internet is going to be. The biggest downside to having Dial-up Internet is that you can either be connected to the Internet or on the phone, not both.
|
||||||
|
|
||||||
|
### ADSL
|
||||||
|
|
||||||
|
Asynchronous Digital Subscriber Line or ADSL is the most common Internet in Australia. This is also commonly referred to as broadband Internet, the biggest difference between ADSL and Dial-up is that it is always on. When ADSL first arrived it had a speed of 1.5mb, which was a massive increase over Dial-up. As ADSL evolved its speed increased, when this occurred its name slightly changed to suit the technological level, ADSL1, ADSL2 and finishing with ADSL2+ which has a maximum theoretical download speed of 24Mb and 2Mb Up. An ADSL connection like dial-up Internet requires a modem and suffers with the same line issues. Where ADSL is an improvement over Dial-up is that you can still make telephone calls when you are have an active Internet connection for this you will need a line filter. To utilise an ADSL connection you require an ADSL modem.
|
||||||
|
|
||||||
|
### Mobile Network
|
||||||
|
|
||||||
|
Again this method of connecting to the Internet has been around for a while and with the invention of the smartphone has become quite a common way to “surf the Web”. 4th generation or 4G being the current technology has a max theoretical speed of 50Mb. The connection speed is shared amongst all users utilizing that mobile tower to connect to the Internet, and if you don’t have good mobile reception you will not have a stable Internet connection.
|
||||||
|
|
||||||
|
### NBN
|
||||||
|
|
||||||
|
The National broadband network or NBN as it is known is the new way to connect to the Internet. The NBN unlike Dial-up or ADSL does not use a phone line to connect to the Internet. The NBN uses fiber optic cable, which uses light not electricity to communicate. Fiber optic cable can be thinner than a human hair. Fiber Optic cable, or fiber networks have one purpose; transmit data, not voice or electronic signals like a copper cable Since fiber is designed for networking you require a router to connect to it. A router looks very similar to an ADSL modem. Unlike the other Internet connection methods above, communication in either direction is the same. Within Australia this is not the case, and for whatever reason you will find most NBN capable ISPs will still have packages with different upload and download speeds. Fiber networks are very mature and their speed is actual, not theoretical maximums and are capable of transmitting data at 10gbps. Using that speed for connecting to the Internet is overkill and you will find that most ISPs offer no connection speed above 100mbps at the moment.
|
||||||
|
|
||||||
|
## Choosing a suitable Internet service
|
||||||
|
|
||||||
|
Now hopefully by now I have given you a little better understanding of the connection types and terminology in relation to choosing an Internet service; believe me it is still a cumbersome task. Yes there are a lot of things to consider. From a technical standpoint the following should be taken into account:
|
||||||
|
|
||||||
|
- availability in your area
|
||||||
|
|
||||||
|
- what you will be using the Internet for
|
||||||
|
|
||||||
|
- bang for buck
|
||||||
|
|
||||||
|
### Availability in Your Area
|
||||||
|
|
||||||
|
For a majority of Australians, ADSL is the best Internet service you will have available. The most annoying thing when trying to connect an ADSL service is the wait time. This wait time is due to the requirement for a technician to have to go to your local telephone exchange to actually connect you, that is if there are spare ports available in the exchange. If though, you can get the NBN, go for it. Seriously you are being foolish if you don't. Why? the NBN is an actual data network and the speed you pay for is what you get, overall the NBN is more reliable.
|
||||||
|
|
||||||
|
### What You Will be Using the Internet For?
|
||||||
|
|
||||||
|
Most website designers will aim for a page load time of within one-two seconds; Even now how website technology is becoming more media focused, I would not recommend any speed lower that ADSL2+(24mbps) or 12mbps for the NBN. Why the different speeds? Remember that ADSL is a theoretical maximum, on average. Most ADSL users will have an actual connection speed of between 8mbps-22mbps and the NBN is actual speed. Anything faster than this for just “surfing the web” is overkill, and a waste of money. Where would you require a faster connection speed? if you start to use services like netflix and/or Foxtel IPTV to stream videos. Having more than ~5 users, may also be a consideration for a speed increase. How much quota do you need? if you have had the Internet before, go look at your previous bills, most of the time you will see what you used for the billing period, use this figure as a basis to guesstimate how much quota you are going to need. If you have never had an Internet package before then as a guide I would recommend nothing less than 10GB quota per month for the average light Internet user. I can't emphasize this enough, please do your research before you take this as gospel. Most people do know someone who <s>“knows boats”</s> would be able to assist in assessing how much quota you may require.
|
||||||
|
|
||||||
|
### Bang for Buck
|
||||||
|
|
||||||
|
Read the fine print………. READ THE FINE PRINT……… oh, did I mention fine print? Every Internet package has fine print. This fine print will cover things like:
|
||||||
|
|
||||||
|
- what is unmetered((this is a category of sites that you can use without it being counted towards your quota.))
|
||||||
|
|
||||||
|
- how much quota you have, read carefully some ISPs will charge by the megabyte if you go over
|
||||||
|
|
||||||
|
- what happens when you reach your quota limit (good ISPs will shape your speed ((slow your Internet connection speed)))
|
||||||
|
|
||||||
|
- what you should not do with your Internet package (some ISPs won’t allow you to host your own website.)
|
||||||
|
|
||||||
|
- contract period
|
||||||
|
|
||||||
|
- exit fees associated with leaving your contract early
|
||||||
|
|
||||||
|
- fees associated with moving house
|
||||||
|
|
||||||
|
- support
|
||||||
|
|
||||||
|
- your responsibilities
|
||||||
|
|
||||||
|
### Further Considerations
|
||||||
|
|
||||||
|
- "**Unlimited Packages"** Some ISPs do offer "unlimited packages". Please read the fine print so you can get the definition of unlimited as sometimes unlimited does not exactly mean unlimited. Some ISPs have been know to use peak and off-peak times, during peak you will have a quota and off peak is “unlimited”. A big consideration for unlimited or large packages with lower download speeds is calculating what you could actually download in that billing period. This is a simple task and would use the following formula.
|
||||||
|
|
||||||
|
> (Billing Period Days x seconds in day) × max download speed in bits ÷ 8 = max bytes for period
|
||||||
|
>Example:
|
||||||
|
>
|
||||||
|
>- Billing Period days = 30
|
||||||
|
>- Second in one day = 86,400
|
||||||
|
>- Max download speed = 22,000,000
|
||||||
|
>- ( 30 x 86,400 ) × 22,000,000 ÷ 8 = 7,128,000,000,000Bytes or 7.128TB
|
||||||
|
>So with the example above a package with a quota above 7.128TB with a download speed of 22mb would be a waste of money.
|
||||||
|
|
||||||
|
- **Bundled Items** We have all seen and heard of them.
|
||||||
|
|
||||||
|
- "Select our Internet Package for $120 a month and we will give you a telephone with free calls, 200gb of download and if you sign up for a 24month contract we will throw in a free iPad"
|
||||||
|
|
||||||
|
- With the exception of a modem-if you don't have one; be very careful of falling into this trap. These “Bundled Packages” are plain and simply designed to get your business. Believe me when I say you can get all of this for a hell of a lot cheaper. Again <u>READ THE FINE PRINT</u> and calculate the cost of the whole contract period including any hidden fees and you will find that these are quite expensive packages. A simple way to test these packages is how much is thrown in, the more free stuff that is included outside of the Internet package, then the more desperate they are for your business. Listen to your gut and the age old saying "If it's too good to be true, than it probably is". Once in my life time I have seen one of these packages and it was too good to be true, but turned out to actually be worth while in the long run, again this was more than likely a “once in a lifetime good package”
|
||||||
|
|
||||||
|
- **Naked ADSL** works exactly the same as normal ADSL Internet but you don’t have to pay for the phone line as it is included in the “Naked ADSL package” if you don’t use the telephone much or you are utilizing VOIP choosing one of these packages can save you some money. Like ADSL this is only available in certain areas, Please confirm with your ISP for availability.
|
||||||
|
|
||||||
|
- **Support** It's common practice for ISPs to outsource the first stage of customer support. This problem is a plague that needs to be truncated from the IT((Information Technology)) industry. Why? 9 times out of 10 the person on the other end of the phone either does not have a good grasp on our native language or has an accent that is so thick you can not understand them, which makes it very difficult for the hearing impaired. When this occurs the assistance you called for doesn't happen, and is escalated to someone else in the chain who may or may not be able to help you. In the end you are stuck with no internet and built up frustration from a 1:30h phone call.
|
||||||
|
|
||||||
|
There are however some ISPs who are old school. they will give you a callback after being on hold for a few minutes and if your assistance call needs to be escalated will either call you back or give a detailed handover to the next person you need to speak to. bottom line if you are not technically minded than ask around to find a good ISP who can assist you and be wary of outsourced tech support.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Lets face it, The Internet has made our lives easier. You can now sit in your lounge room and read this long, very mind numbing article on how to choose a better Internet Service, do your Banking, Pay Bills, Buy Goods, <s>look at porn</s> and best of all place video calls to family and friends. What will the future hold? Who knows but given how far technology has evolved in the last 50 years, I think the next 50 will yield even more from this simple little invention courtesy of DARPA.
|
||||||
|
|
||||||
|
<s>Like this article? Please consider buying me a coffee. Donations can be accepted via PayPal via our store at No Fuss Computing</s>
|
||||||
|
|
||||||
|
Some ISPs in Australia:
|
||||||
|
|
||||||
|
- Internode
|
||||||
|
|
||||||
|
- IINet
|
||||||
|
|
||||||
|
- WestNet
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
The information contained within this article based on the opinion of the author and is provided for informational purposes only. Before utilizing any information or advice from this article you are encouraged to do your own research
|
||||||
|
|
||||||
|
|
||||||
|
!!! attention
|
||||||
|
This post is considered an archived post.
|
||||||
|
|
||||||
|
This article was originally posted on 25 Feb 2015. It has been migrated from its original source _http://nofusscomputing.com/wiki/public/article/150225_choose_internet_service_ to here.
|
8
pages/articles/index.md
Normal file
8
pages/articles/index.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
template: blog_list.html
|
||||||
|
title: No Fuss Computing Articles
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Please see below for our articles.
|
BIN
pages/assets/logo.png
Normal file
BIN
pages/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
23
pages/contact.md
Normal file
23
pages/contact.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Contact Us
|
||||||
|
|
||||||
|
We can be found in the following places on the internet:
|
||||||
|
|
||||||
|
- [:fontawesome-brands-docker:{ .docker } Docker Hub](https://hub.docker.com/u/nofusscomputing)
|
||||||
|
|
||||||
|
- [:fontawesome-brands-facebook:{ .facebook } Facebook](https://www.facebook.com/NoFussComputing)
|
||||||
|
|
||||||
|
- [:fontawesome-brands-github:{ .github } Github](https://github.com/NoFussComputing)
|
||||||
|
|
||||||
|
- [:fontawesome-brands-gitlab:{ .gitlab } Gitlab](https://gitlab.com/nofusscomputing)
|
||||||
|
|
||||||
|
- [:books: Read the Docs](https://readthedocs.org/profiles/nofusscomputing/)
|
||||||
|
|
||||||
|
## Found an issue with a page on this website?
|
||||||
|
|
||||||
|
On every page of this website that you are able to edit, you will find this icon :material-pencil:. Located in the top right hand corner of the content. After clicking on this icon, you will be taken to the git repository that contains the page in question for you to edit. An understanding of Git and Gitlab is required for the use of this method.
|
||||||
|
|
||||||
|
For the non-developers out there, you can still contribute by submitting an issue about the related page. To do this find this icon :fontawesome-brands-gitlab: on the subject page. Copy the page url to your clipboard, then click :fontawesome-brands-gitlab: icon. You will be taken to Gitlab.com and the repository in question. There will be a menu on the left hand side of the screen, where you will click issues. On the issues page loading, click new issue and use a relevant template for your report. _**Don't forget to include the url of the subject page and to ensure there is enough details for us to rectify the issue.**_
|
||||||
|
|
||||||
|
??? info "Where is the owner located??"
|
||||||
|
|
||||||
|
Jon can be found on [:fontawesome-brands-github:{ .github } Github](https://github.com/jon-nfc) and [:fontawesome-brands-gitlab:{ .gitlab } Gitlab](https://gitlab.com/jon_nfc)
|
8
pages/index.md
Normal file
8
pages/index.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
hide:
|
||||||
|
- navigation
|
||||||
|
- toc
|
||||||
|
---
|
||||||
|
# No Fuss Computing
|
||||||
|
|
||||||
|
Home Page
|
5
pages/operations/index.md
Normal file
5
pages/operations/index.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# No Fuss Computing Operations
|
||||||
|
|
||||||
|
| :red_circle: This page is a placeholder for the operations repo's docs. |
|
||||||
|
|:---|
|
||||||
|
| _If you can see this page there has been an error, please report the issue on gitlab_ |
|
15
pages/operations/syntax.md
Normal file
15
pages/operations/syntax.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: Supported Markdown Syntax
|
||||||
|
tags:
|
||||||
|
- Development
|
||||||
|
- Markdown
|
||||||
|
- Website
|
||||||
|
- mkdocs
|
||||||
|
---
|
||||||
|
|
||||||
|
# Supported Markdown Syntax
|
||||||
|
|
||||||
|
!!! Notice
|
||||||
|
This page is still being constructed
|
||||||
|
|
||||||
|
_This website uses markdown documents to create the pages, please see the [reference guide](https://squidfunk.github.io/mkdocs-material/reference/) for further items that can be used._
|
5
pages/projects/ansible-roles/README.md
Normal file
5
pages/projects/ansible-roles/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Ansible Roles
|
||||||
|
|
||||||
|
| :red_circle: This page is a placeholder for the ansible-roles repo's docs. |
|
||||||
|
|:---|
|
||||||
|
| _If you can see this page there has been an error, please report the issue on gitlab_ |
|
5
pages/projects/gitlab-ci/README.md
Normal file
5
pages/projects/gitlab-ci/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Gitlab Continuous Integration Templates
|
||||||
|
|
||||||
|
| :red_circle: This page is a placeholder for the gitlab-ci repo's docs. |
|
||||||
|
|:---|
|
||||||
|
| _If you can see this page there has been an error, please report the issue on gitlab_ |
|
8
pages/projects/index.md
Normal file
8
pages/projects/index.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Development
|
||||||
|
- brand new
|
||||||
|
---
|
||||||
|
# No Fuss Computing Projects
|
||||||
|
|
||||||
|
## Our Projects
|
5
pages/projects/python-gitlab-management/README.md
Normal file
5
pages/projects/python-gitlab-management/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Python Gitlab Management
|
||||||
|
|
||||||
|
| :red_circle: This page is a placeholder for the python-gitlab-management repo's docs. |
|
||||||
|
|:---|
|
||||||
|
| _If you can see this page there has been an error, please report the issue on gitlab_ |
|
13
pages/robots.txt
Normal file
13
pages/robots.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
User-agent: *
|
||||||
|
|
||||||
|
# example: Redirect 301 /oldpage.html /newpage.html
|
||||||
|
|
||||||
|
Redirect 301 /wiki/public/article/150225_choose_internet_service /articles/2015/choose_internet_service
|
||||||
|
|
||||||
|
Redirect 301 /wiki/syntax /operations/syntax
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Redirect 301 /wiki/public/help/mdt/* /wiki/info/*
|
||||||
|
|
||||||
|
Redirect 301 /wiki/public/help/mantis/* /wiki/info/*
|
72
pages/stylesheets/extra.css
Normal file
72
pages/stylesheets/extra.css
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
html .md-social a[title="DockerHub"] {
|
||||||
|
color: #0DB7ED;
|
||||||
|
}
|
||||||
|
|
||||||
|
html .md-social a[title="Facebook"] {
|
||||||
|
color: #3B5998;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
html .md-social a[title="Github"] {
|
||||||
|
color: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
html .md-social a[title="Gitlab"] {
|
||||||
|
color: #fc6d26;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docker {
|
||||||
|
color: #0DB7ED;
|
||||||
|
}
|
||||||
|
|
||||||
|
.facebook {
|
||||||
|
color: #3B5998;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gitlab {
|
||||||
|
color: #fc6d26;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
background-color: #4051B5;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: white;
|
||||||
|
padding: 3px 6px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
a.tags:hover {
|
||||||
|
color: #FFFF00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags:link {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags:visited {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Blog Styles */
|
||||||
|
.mdx-author {
|
||||||
|
display: flex;
|
||||||
|
font-size: 13.6px;
|
||||||
|
}
|
||||||
|
.mdx-author img {
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
.mdx-author p:first-child {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
.mdx-author p > span {
|
||||||
|
display: block;
|
||||||
|
}
|
3
pages/tags.md
Normal file
3
pages/tags.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# tags
|
||||||
|
|
||||||
|
Do not edit this file as it is auto generated.
|
@ -1,3 +1,3 @@
|
|||||||
# Welcome to the Wiki
|
# Welcome to the Wiki
|
||||||
|
|
||||||
|
## Wiki Sections
|
5
pytest.ini
Normal file
5
pytest.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[pytest]
|
||||||
|
#junit_suite_name=Unit Test
|
||||||
|
junit_log_passing_tests=true
|
||||||
|
#enable_assertion_pass_hook=true
|
||||||
|
junit_logging=all
|
7
requirements.txt
Normal file
7
requirements.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
mkdocs-minify-plugin==0.5.0
|
||||||
|
mkdocs-material-extensions==1.0.3
|
||||||
|
wheel
|
||||||
|
mkdocs-material==8.1.7
|
||||||
|
./custom-plugins/mkdocs-plugin-tags
|
||||||
|
mkdocs-git-revision-date-localized-plugin==0.11.1
|
||||||
|
pymdown-extensions==9.1
|
4
test/requirements.txt
Normal file
4
test/requirements.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
selenium==3.141.0
|
||||||
|
|
||||||
|
pytest==6.2.5
|
||||||
|
requests==2.27.1
|
160
test/unit/conftest.py
Normal file
160
test/unit/conftest.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from selenium import webdriver
|
||||||
|
from selenium.webdriver.chrome.options import Options
|
||||||
|
|
||||||
|
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
|
||||||
|
def process_browser_log_entry(self, entry):
|
||||||
|
response = json.loads(entry['message'])['message']
|
||||||
|
return response
|
||||||
|
|
||||||
|
def parse_url(self, url):
|
||||||
|
|
||||||
|
request_protocol = re.match("^[http|file]+s?", url).group(0)
|
||||||
|
|
||||||
|
url_id = hashlib.md5(bytes(url, 'utf-8')).hexdigest()
|
||||||
|
|
||||||
|
if re.match("^http.*", url) is not None:
|
||||||
|
|
||||||
|
domain = re.match(r'^([a-z]+[\.|a-z|]+)',url.replace(request_protocol + '://', '')).group(0)
|
||||||
|
|
||||||
|
request_path = url.replace(request_protocol + '://','').replace(domain, '')[1:]
|
||||||
|
|
||||||
|
elif re.match("^file.*", url) is not None:
|
||||||
|
|
||||||
|
domain = 'file'
|
||||||
|
|
||||||
|
request_path = url.replace(request_protocol + '://','')[1:]
|
||||||
|
|
||||||
|
request_path = request_path.replace(self.suffux_path[1:], '')
|
||||||
|
|
||||||
|
return {
|
||||||
|
'url_id': url_id,
|
||||||
|
'url': url,
|
||||||
|
'request_protocol': request_protocol,
|
||||||
|
'domain': domain,
|
||||||
|
'request_path': request_path
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
caps = DesiredCapabilities.CHROME
|
||||||
|
caps['goog:loggingPrefs'] = {'performance': 'ALL'}
|
||||||
|
|
||||||
|
|
||||||
|
chrome_options = Options()
|
||||||
|
chrome_options.add_argument("no-sandbox")
|
||||||
|
chrome_options.add_argument("headless")
|
||||||
|
chrome_options.add_argument("start-maximized")
|
||||||
|
chrome_options.add_argument("window-size=1900,1080");
|
||||||
|
|
||||||
|
self.driver = webdriver.Chrome(desired_capabilities=caps, options=chrome_options)
|
||||||
|
|
||||||
|
self.urls = []
|
||||||
|
self.suffux_path = os.path.realpath('./build')
|
||||||
|
self.urls += [os.path.join(dp, f) for dp, dn, fn in os.walk(os.path.expanduser('./build')) for f in fn if f.endswith('.html')]
|
||||||
|
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'page_load_resource_links': {},
|
||||||
|
'source_files': [],
|
||||||
|
'hyperlinks': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for check_file in self.urls:
|
||||||
|
|
||||||
|
check_url = 'file://' + self.suffux_path + check_file.replace('./build','')
|
||||||
|
source_file = check_file.replace('./build','')[1:]
|
||||||
|
|
||||||
|
if source_file not in data['source_files']:
|
||||||
|
data['source_files'].append(source_file)
|
||||||
|
|
||||||
|
self.driver.get(check_url)
|
||||||
|
|
||||||
|
links = self.driver.find_elements_by_css_selector("a")
|
||||||
|
|
||||||
|
for link in links:
|
||||||
|
|
||||||
|
link_location = link.location
|
||||||
|
|
||||||
|
url = link.get_attribute('href')
|
||||||
|
|
||||||
|
link = self.parse_url(url)
|
||||||
|
|
||||||
|
hyperlink_source_file = {'name': source_file, 'location': link_location}
|
||||||
|
|
||||||
|
if link['url_id'] in data['hyperlinks']:
|
||||||
|
|
||||||
|
data['hyperlinks'][link['url_id']]['source_files'].append(hyperlink_source_file)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
link['source_files'] = [ hyperlink_source_file ]
|
||||||
|
data['hyperlinks'][link['url_id']] = link
|
||||||
|
|
||||||
|
|
||||||
|
events = [self.process_browser_log_entry(entry) for entry in self.driver.get_log('performance')]
|
||||||
|
|
||||||
|
for entry in events:
|
||||||
|
|
||||||
|
if entry['method'] == 'Network.requestWillBeSent':
|
||||||
|
|
||||||
|
http_status = str([response['params']['response']['status'] for response in events if response['method'] == 'Network.responseReceived' and response['params']['requestId'] == entry['params']['requestId']]).replace('[', '').replace(']', '')
|
||||||
|
|
||||||
|
url = str(entry['params']['request']['url'])
|
||||||
|
|
||||||
|
|
||||||
|
url_id = hashlib.md5(bytes(url, 'utf-8')).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
if re.match("^http|file.*", url) is not None:
|
||||||
|
|
||||||
|
source_file_line_number = ''
|
||||||
|
|
||||||
|
if 'lineNumber' in entry['params']['initiator']:
|
||||||
|
|
||||||
|
source_file_line_number = str(entry['params']['initiator']['lineNumber'])
|
||||||
|
|
||||||
|
request_protocol = re.match("^[http|file]+s?", url).group(0)
|
||||||
|
|
||||||
|
if re.match("^http.*", url) is not None:
|
||||||
|
|
||||||
|
domain = re.match(r'^([a-z]+[\.|a-z|]+)',url.replace(request_protocol + '://', '')).group(0)
|
||||||
|
|
||||||
|
request_path = url.replace(request_protocol + '://','').replace(domain, '')[1:]
|
||||||
|
|
||||||
|
|
||||||
|
elif re.match("^file.*", url) is not None:
|
||||||
|
|
||||||
|
domain = 'file'
|
||||||
|
|
||||||
|
request_path = url.replace(request_protocol + '://','')[1:]
|
||||||
|
|
||||||
|
if url_id in data['page_load_resource_links']:
|
||||||
|
|
||||||
|
data['page_load_resource_links'][url_id]['source_files'].append({'name': source_file, 'line_number': source_file_line_number, 'http_status': http_status})
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
data['page_load_resource_links'][url_id] = {'url': url, 'request_protocol': request_protocol, 'domain': domain, 'request_path': request_path, 'source_files': [ {'name': source_file, 'line_number': source_file_line_number, 'http_status': http_status} ]}
|
||||||
|
|
||||||
|
self.driver.quit()
|
||||||
|
self.test_data = data
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.driver.quit()
|
||||||
|
|
||||||
|
print("\n"+'Creating test data')
|
||||||
|
print("\n\ntest data:\n" + json.dumps(Data().test_data, indent=2, default=str))
|
||||||
|
|
105
test/unit/main_test.py
Normal file
105
test/unit/main_test.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import pytest
|
||||||
|
import os
|
||||||
|
|
||||||
|
from conftest import Data
|
||||||
|
|
||||||
|
class Test:
|
||||||
|
|
||||||
|
data = Data()
|
||||||
|
|
||||||
|
def setup_class(self):
|
||||||
|
#copy data so it can be used
|
||||||
|
self.source_files = self.data.test_data['source_files']
|
||||||
|
|
||||||
|
|
||||||
|
def setup_method(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
argnames='data',
|
||||||
|
argvalues=[link for url_id, link in data.test_data['hyperlinks'].items() if link['request_protocol'][0:4] =='http'],
|
||||||
|
ids=[url_id for url_id, link in data.test_data['hyperlinks'].items() if link['request_protocol'][0:4] =='http']
|
||||||
|
)
|
||||||
|
def test_hyperlink_external_alive_check(self, data):
|
||||||
|
"""Test hyperlinks that are found within each page of the site.
|
||||||
|
|
||||||
|
SSL verification has been disabled as this test only checks if the link is alive and valid.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (dict): A dictionary of hyperlinks constructed within conftest.py
|
||||||
|
"""
|
||||||
|
from requests import get
|
||||||
|
from requests import packages
|
||||||
|
from urllib3.exceptions import InsecureRequestWarning
|
||||||
|
|
||||||
|
packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
||||||
|
|
||||||
|
request = get(data['url'], verify=False)
|
||||||
|
|
||||||
|
print(str(data) + str(request.status_code))
|
||||||
|
|
||||||
|
assert request.status_code == 200, (
|
||||||
|
f"Hyperlink [{data['url_id']}] to location [{data['url']}] failed,"
|
||||||
|
f"with status [{request.status_code}].")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
argnames='data',
|
||||||
|
argvalues=[link for url_id, link in data.test_data['hyperlinks'].items() if link['request_protocol'][0:4] =='file' and link['request_path'] != ''],
|
||||||
|
ids=[url_id for url_id, link in data.test_data['hyperlinks'].items() if link['request_protocol'][0:4] =='file' and link['request_path'] != '']
|
||||||
|
)
|
||||||
|
def test_hyperlink_internal_alive_check(self, data):
|
||||||
|
""" Test all internal hyperlinks are valid and the page exists.
|
||||||
|
|
||||||
|
This test constructs the actual file path from a found internal (contains file as the protocol) link. After the link is found it is checked against the pages that exist.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (list): list of dictionaries containing the urls to test
|
||||||
|
"""
|
||||||
|
|
||||||
|
path_suffix = os.path.realpath('./build')
|
||||||
|
|
||||||
|
print('URL Data:' + str(data))
|
||||||
|
|
||||||
|
request_path = str(data['request_path'])
|
||||||
|
|
||||||
|
if request_path[0:1] == '/':
|
||||||
|
if request_path[0:1] == request_path:
|
||||||
|
request_path = 'index.html'
|
||||||
|
else:
|
||||||
|
request_path = request_path[1:]
|
||||||
|
|
||||||
|
if '#' in request_path:
|
||||||
|
request_path_split = request_path.split('#')
|
||||||
|
request_path = str(request_path_split[0])
|
||||||
|
print('Debug # in path ' + request_path_split[0])
|
||||||
|
|
||||||
|
# Reconstruct a valid url. append 'index.html' for paths ending in '/'
|
||||||
|
if (request_path[len(request_path)-1:] == '/'
|
||||||
|
and request_path[len(request_path)-5:] != '.html'
|
||||||
|
):
|
||||||
|
|
||||||
|
request_path = str(request_path) + 'index.html'
|
||||||
|
|
||||||
|
elif (request_path[len(request_path)-1:] != '/'
|
||||||
|
and request_path[len(request_path)-5:] == '.html'
|
||||||
|
):
|
||||||
|
|
||||||
|
request_path = request_path
|
||||||
|
|
||||||
|
print('DEBUG consructed path:' + request_path)
|
||||||
|
|
||||||
|
assert request_path in self.source_files, (
|
||||||
|
f"hyperlink [{str(data['request_path'])}] that was reconstructed to[{request_path}] "
|
||||||
|
"does not exist. This link was found "
|
||||||
|
f"within the following pages [{str(data['source_files'])}]"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_method(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def teardown_class(self):
|
||||||
|
del self.data
|
||||||
|
|
65
test/unit/privacy_test.py
Normal file
65
test/unit/privacy_test.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from conftest import Data
|
||||||
|
|
||||||
|
class Test:
|
||||||
|
|
||||||
|
data = Data()
|
||||||
|
|
||||||
|
def setup_method(self):
|
||||||
|
|
||||||
|
self.approved_external_requests = {
|
||||||
|
'gitlab.com': [
|
||||||
|
'api/v4/projects/nofusscomputing%2Finfrastructure%2Fwebsite',
|
||||||
|
'uploads/-/system/user/avatar/4125177/avatar.png'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
argnames='data',
|
||||||
|
argvalues=[link for url_id, link in data.test_data['page_load_resource_links'].items() if link['request_protocol'][0:4] =='http'],
|
||||||
|
ids=[url_id for url_id, link in data.test_data['page_load_resource_links'].items() if link['request_protocol'][0:4] =='http']
|
||||||
|
)
|
||||||
|
def test_page_load_external_requests(self, data):
|
||||||
|
|
||||||
|
check_url = data['url']
|
||||||
|
|
||||||
|
print(str(data))
|
||||||
|
|
||||||
|
assert data['request_protocol'] == 'https', f"Insecure Request to domain [{data['request_path']}] in source files [{data['source_files']}]"
|
||||||
|
|
||||||
|
assert data['domain'] in self.approved_external_requests, f"A request is being made to a non-approved domain [{data['domain']}] path [{data['request_path']}] in source files [{data['source_files']}]"
|
||||||
|
|
||||||
|
assert data['request_path'] in self.approved_external_requests[data['domain']], f"A request is being made to a non-approved path [{data['request_path']}] on domain [{data['domain']}] in source files [{data['source_files']}]"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
argnames='data',
|
||||||
|
argvalues=[link
|
||||||
|
for url_id, link in data.test_data['hyperlinks'].items()
|
||||||
|
if link['request_protocol'][0:4] =='http'],
|
||||||
|
ids=[url_id for url_id, link in data.test_data['hyperlinks'].items() if link['request_protocol'][0:4] =='http']
|
||||||
|
)
|
||||||
|
def test_ssl_hyperlinks_only(self, data):
|
||||||
|
"""Ensure all hyperlinks from our site are to https ONLY
|
||||||
|
|
||||||
|
Tests to ensure that all hyperlinks from our site are to 'https' links only. Any link that is not secure will fail this test.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (dict): A dictionary of hyperlinks constructed within conftest.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(str(data))
|
||||||
|
|
||||||
|
assert data['request_protocol'] == 'https', (
|
||||||
|
f"Hyperlink [{data['url_id']}] to location [{data['url']}] is insecure"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_method(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def teardown_class(self):
|
||||||
|
del self.data
|
||||||
|
|
1
theme-overrides/.icons/brand/docker.svg
Normal file
1
theme-overrides/.icons/brand/docker.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M349.9 236.3h-66.1v-59.4h66.1v59.4zm0-204.3h-66.1v60.7h66.1V32zm78.2 144.8H362v59.4h66.1v-59.4zm-156.3-72.1h-66.1v60.1h66.1v-60.1zm78.1 0h-66.1v60.1h66.1v-60.1zm276.8 100c-14.4-9.7-47.6-13.2-73.1-8.4-3.3-24-16.7-44.9-41.1-63.7l-14-9.3-9.3 14c-18.4 27.8-23.4 73.6-3.7 103.8-8.7 4.7-25.8 11.1-48.4 10.7H2.4c-8.7 50.8 5.8 116.8 44 162.1 37.1 43.9 92.7 66.2 165.4 66.2 157.4 0 273.9-72.5 328.4-204.2 21.4.4 67.6.1 91.3-45.2 1.5-2.5 6.6-13.2 8.5-17.1l-13.3-8.9zm-511.1-27.9h-66v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm-78.1-72.1h-66.1v60.1h66.1v-60.1z"/></svg>
|
After Width: | Height: | Size: 663 B |
31
theme-overrides/blog_list.html
Normal file
31
theme-overrides/blog_list.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{{ page.content }}
|
||||||
|
{% set blog_posts = [] %}
|
||||||
|
{% for page in nav.pages %}
|
||||||
|
{% if page.url.startswith(config.extra.blog.dir) and page.meta.date is defined %}
|
||||||
|
<!-- or "" suppresses "None" output-->
|
||||||
|
{{ blog_posts.append( page ) or "" }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for page in (blog_posts|sort(attribute="meta.date", reverse=True))[:config.extra.blog.list_length] %}
|
||||||
|
<h2><a href="{{ page.url|url }}">{{ page.title }}</a></h2>
|
||||||
|
<hr>
|
||||||
|
{% include "partials/blog_metadata.html" %}
|
||||||
|
<p>
|
||||||
|
{{ page.meta.description }}
|
||||||
|
</p>
|
||||||
|
<!-- Use a hidden p tag to provide a preview -->
|
||||||
|
{% if config.extra.blog.extended_preview %}
|
||||||
|
<a href="{{ page.url|url }}#more">
|
||||||
|
<span class="twemoji">
|
||||||
|
{% include ".icons/octicons/arrow-right-24.svg" %}
|
||||||
|
</span>
|
||||||
|
Continue reading
|
||||||
|
<hr>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
8
theme-overrides/blog_post.html
Normal file
8
theme-overrides/blog_post.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{{ page.title }}</h1>
|
||||||
|
{% include "partials/blog_metadata.html" %}
|
||||||
|
<hr>
|
||||||
|
{{ page.content }}
|
||||||
|
{% endblock %}
|
7
theme-overrides/partials/blog_extended_preview.html
Normal file
7
theme-overrides/partials/blog_extended_preview.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<a href="{{ page.url|url }}">
|
||||||
|
<span class="twemoji">
|
||||||
|
{% include ".icons/octicons/arrow-right-24.svg" %}
|
||||||
|
</span>
|
||||||
|
Continue reading
|
||||||
|
<hr>
|
||||||
|
</a>
|
32
theme-overrides/partials/blog_metadata.html
Normal file
32
theme-overrides/partials/blog_metadata.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<aside class="mdx-author">
|
||||||
|
{% if config.extra.blog.author_image is defined %}
|
||||||
|
<p>
|
||||||
|
<img alt={{ config.extra.blog.author }} src={{ config.extra.blog.author_image }}>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<p>
|
||||||
|
<span>
|
||||||
|
{% if config.extra.blog.author %}
|
||||||
|
<strong>{{ config.extra.blog.author }}</strong>
|
||||||
|
·
|
||||||
|
{% endif %}
|
||||||
|
{% include "partials/blog_social.html" %}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<span class="twemoji">
|
||||||
|
{% include ".icons/octicons/calendar-24.svg" %}
|
||||||
|
</span>
|
||||||
|
{{ page.meta.date.strftime("%Y-%m-%d") }} ·
|
||||||
|
{% if page.meta.git_revision_date_localized %}Updated {{ page.meta.git_revision_date_localized.replace("\n", "").replace("\r", "") }} <br>{% endif %}
|
||||||
|
<span class="twemoji">
|
||||||
|
{% include ".icons/octicons/clock-24.svg" %}
|
||||||
|
</span>
|
||||||
|
<!--Min reading time is 1 minute-->
|
||||||
|
{% set read_time = page.content | wordcount // config.extra.blog.words_read_per_minute|default(300, true) %}
|
||||||
|
{% if read_time == 0 %}
|
||||||
|
{% set read_time = 1 %}
|
||||||
|
{% endif %}
|
||||||
|
{{ read_time }} min read
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</aside>
|
17
theme-overrides/partials/blog_social.html
Normal file
17
theme-overrides/partials/blog_social.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{% if config.extra.social %}
|
||||||
|
{% set ns = namespace() %}
|
||||||
|
{% for social in config.extra.social %}
|
||||||
|
{% set title = social.name %}
|
||||||
|
{% if not title and "//" in social.link %}
|
||||||
|
{% set _,url = social.link.split("//") %}
|
||||||
|
{% set title = url.split("/")[0] %}
|
||||||
|
{% endif %}
|
||||||
|
{% if ns.line_break is defined %}
|
||||||
|
{{ ns.line_break }}
|
||||||
|
{% endif %}
|
||||||
|
<a href="{{ social.link }}" target="_blank" rel="noopener" title="{{ title | e }}" class="twemoji">
|
||||||
|
{% include ".icons/" ~ social.icon ~ ".svg" %}
|
||||||
|
</a>
|
||||||
|
{% set ns.line_break = " · " %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
14
theme-overrides/partials/footer.html
Normal file
14
theme-overrides/partials/footer.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{#-
|
||||||
|
This file was automatically generated - do not edit
|
||||||
|
-#}
|
||||||
|
<footer class="md-footer">
|
||||||
|
|
||||||
|
<div class="md-footer-meta md-typeset">
|
||||||
|
<div class="md-footer-meta__inner md-grid">
|
||||||
|
{% include "partials/copyright.html" %}
|
||||||
|
{% if config.extra.social %}
|
||||||
|
{% include "partials/social.html" %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
12
theme-overrides/sitemap.xml
Normal file
12
theme-overrides/sitemap.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
{%- for file in pages -%}
|
||||||
|
{% if not file.page.is_link %}
|
||||||
|
<url>
|
||||||
|
<loc>{% if file.page.canonical_url %}{{ file.page.canonical_url|e }}{% else %}{{ file.page.abs_url|e }}{% endif %}</loc>
|
||||||
|
{% if file.page.meta.git_revision_date_localized %}<lastmod>{{ file.page.meta.git_revision_date_localized.replace("\n", "").replace("\r", "").replace('<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-iso_date">', '').replace('</span>','') }}</lastmod>{% endif %}
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
</url>
|
||||||
|
{%- endif -%}
|
||||||
|
{% endfor %}
|
||||||
|
</urlset>
|
@ -1,109 +0,0 @@
|
|||||||
====== Choosing an Internet Service ======
|
|
||||||
|
|
||||||
<wrap center info 90%>This article has been targeted towards the common mass who don’t understand the technical details and considerations for choosing an Internet package.</wrap>
|
|
||||||
|
|
||||||
The Internet has now become a mainstream item within the average Australian home. The Internet has become so ingrained within our daily lives that for those of us that were around when the Internet was born have actually forgotten what life was like without it. I remember when I was growing up that if we wanted to learn about something you would go to the local library or to a family/friends house to look through their Encyclopaedia Britannica which more often than not was at least five years out of date. Believe it or not that was only 15 to 20 years ago.
|
|
||||||
I would consider myself lucky in the regard we were introduced to the Internet in high school way back when [[http://webcrawler.com|Web Crawler]] was what Google is today and the only thing of any value was searching for random phrases like <del>porn</del> homework answers. It was a very new concept to have the Internet or even access, which was often met with confusion and a sheer lack of knowledge. Being part of that generation we grew with the Internet and became the first generation to learn about it, and to the behest of the generations before us who were either left in the dark or were very slow on the uptake.
|
|
||||||
|
|
||||||
Now if I haven't lost you already and hopefully by the end of this article I have been able to provide you with more insight on being able to choose an Internet service from an ISP with a little more of an understanding of the technology behind that Internet connection.
|
|
||||||
|
|
||||||
Below I will cover a little of the technical details and hopefully bringing into perspective, so you can better understand what is being explained to you. To do this I will use the flow of water methodology.
|
|
||||||
|
|
||||||
===== Bandwidth =====
|
|
||||||
Bandwidth is the actual speed of your Internet connection and its unit of measure is bits per second. So basically if you think water pipe, only so much water will flow through a water pipe but if you increase it’s pressure you will receive more water. For the actual Internet connection different technology is used to essentially achieve the same thing.
|
|
||||||
|
|
||||||
===== Quota =====
|
|
||||||
This is how much you can download and/or upload from the Internet. Its unit of measure is bytes. Think of a water tank, larger the tank the more quota you have available. This will be set by your ISP and 9 times out of 10 will be limited. Every Time you connect to the Internet you are using this available quota.
|
|
||||||
|
|
||||||
===== Theory =====
|
|
||||||
Now to fully understand the quota and bandwidth I will have to cover a little bit of computer theory. Computers compute information by doing mathematical equations. The only numbers a computer recognizes are [[wp>Binary_number|Base 2]]. Base 2 numbering means it uses the first 2 numbers, being zero and one. In common computer terms this is called binary which is always in the computer world as a minimum 8 bits wide i.e. 01010101. Each digit of the number is a bit, four bits to a nibble and 2 nibbles to a byte. Unlike the English language; Binary is read from right to left and each one or zero, within a binary number is actually counting from 1 through to 255, which takes 8 bits of information. Binary is a [[wp>Notation|notational reference system]], so starting from right to left each digit represents another number, the first number being one, each number after that is double the number before it so the next number would be two, then four, eight, 16, 32, 64 finishing with the leftmost digit as 128.
|
|
||||||
Confusing? Not really, when the bit is zero you don't add each notated number, you only add if the bit is one. So 0001 would be one, 0010 would be two, 0011 is three and so on.
|
|
||||||
|
|
||||||
Communication between different components or computers (network or The Internet) is measured in bits per second or bps (lowercase). Computers store data in bytes or B (uppercase). Each unit of measure has multipliers like normal numbers, computers use the following multipliers, Kilo (K) for thousands, Mega (M) for millions, Giga (G) for billions, Tera (T) for trillions and Peta (P) for quintillion's. The conversion from bits to bytes is a division of 8.
|
|
||||||
|
|
||||||
So why use different units of measure for the same data? simply put, computers are electronic devices which communicate with an electronic signal with 1 being on and zero being off; basically the signal is either on or off. So the transmission of data is serial or singular and storage is in parallel or stored in octets which is a group of bits. Hence bits and bytes. generally you will find lowercase letters are used to represent bits and uppercase letters are used for bytes.
|
|
||||||
|
|
||||||
|
|
||||||
===== Connection types =====
|
|
||||||
The common Internet connection types in Australia are ADSL or via the Mobile network. Very rarely used but still available if you look hard enough dial-up. and the newest and greatest is the National Broadband Network or NBN. With the exception of the NBN all of the above connection types will have a max speed. This max speed is a theoretical maximum speed and there are many factors which generally slow down your connection. All connection methods have a technological peak, which basically means there is no known way to improve that technology any further.
|
|
||||||
|
|
||||||
==== Dial-Up ====
|
|
||||||
[[wp>56_kbit/s_modem|Dial-Up]] Internet was the first mainstream way to connect to the Internet. For this to happen you needed an active phone line, a computer with a MODEM (short for modulator/demodulator) and you would plug a phone cable into your computer, which would dial a number to connect to the Internet. At its technological peak the max theoretical download speed was 56kb and approx 33kb up. Dial-up modems are generally part of the computer. The downside to Dial-up is that it relies on good quality phone cables, basically if you have a bad phone line you will have unstable and slower Internet. Dial-up also suffers from signal attenuation which means the further away from the telephone exchange the lower the speed your Internet is going to be. The biggest downside to having Dial-up Internet is that you can either be connected to the Internet or on the phone, not both.
|
|
||||||
|
|
||||||
==== ADSL ====
|
|
||||||
[[wp>Asymmetric_digital_subscriber_line|Asynchronous Digital Subscriber Line]] or ADSL is the most common Internet in Australia. This is also commonly referred to as broadband Internet, the biggest difference between ADSL and Dial-up is that it is always on. When ADSL first arrived it had a speed of 1.5mb, which was a massive increase over Dial-up. As ADSL evolved its speed increased, when this occurred its name slightly changed to suit the technological level, ADSL1, ADSL2 and finishing with ADSL2+ which has a maximum theoretical download speed of 24Mb and 2Mb Up. An ADSL connection like dial-up Internet requires a modem and suffers with the same line issues. Where ADSL is an improvement over Dial-up is that you can still make telephone calls when you are have an active Internet connection for this you will need a line filter. To utilise an ADSL connection you require an ADSL modem.
|
|
||||||
|
|
||||||
==== Mobile Network ====
|
|
||||||
Again this method of connecting to the Internet has been around for a while and with the invention of the smartphone has become quite a common way to “surf the Web”. 4th generation or 4G being the current technology has a max theoretical speed of 50Mb. The connection speed is shared amongst all users utilizing that mobile tower to connect to the Internet, and if you don’t have good mobile reception you will not have a stable Internet connection.
|
|
||||||
|
|
||||||
==== NBN ====
|
|
||||||
The National broadband network or NBN as it is known is the new way to connect to the Internet. The NBN unlike Dial-up or ADSL does not use a phone line to connect to the Internet. The NBN uses [[wp>Optical_fiber_cable|fiber optic cable]], which uses light not electricity to communicate. Fiber optic cable can be thinner than a human hair. Fiber Optic cable, or fiber networks have one purpose; transmit data, not voice or electronic signals like a [[wp>Copper_wire_and_cable|copper cable]]. Since fiber is designed for networking you require a router to connect to it. A router looks very similar to an ADSL modem. Unlike the other Internet connection methods above, communication in either direction is the same. Within Australia this is not the case, and for whatever reason you will find most NBN capable ISPs will still have packages with different upload and download speeds. Fiber networks are very mature and their speed is actual, not theoretical maximums and are capable of transmitting data at 10gbps. Using that speed for connecting to the Internet is overkill and you will find that most ISPs offer no connection speed above 100mbps at the moment.
|
|
||||||
|
|
||||||
|
|
||||||
===== Choosing a suitable Internet service =====
|
|
||||||
Now hopefully by now I have given you a little better understanding of the connection types and terminology in relation to choosing an Internet service; believe me it is still a cumbersome task. Yes there are a lot of things to consider. From a technical standpoint the following should be taken into account:
|
|
||||||
* availability in your area
|
|
||||||
* what you will be using the Internet for
|
|
||||||
* bang for buck
|
|
||||||
|
|
||||||
|
|
||||||
==== Availability in Your Area ====
|
|
||||||
For a majority of Australians, ADSL is the best Internet service you will have available. The most annoying thing when trying to connect an ADSL service is the wait time. This wait time is due to the requirement for a technician to have to go to your local [[wp>Telephone_exchange|telephone exchange]] to actually connect you, that is if there are spare ports available in the exchange. If though, you can get the NBN, go for it. Seriously you are being foolish if you don't. Why? the NBN is an actual data network and the speed you pay for is what you get, overall the NBN is more reliable.
|
|
||||||
|
|
||||||
==== What You Will be Using the Internet For? ====
|
|
||||||
Most website designers will aim for a page load time of within one-two seconds; Even now how website technology is becoming more media focused, I would not recommend any speed lower that ADSL2+(24mbps) or 12mbps for the NBN. Why the different speeds? Remember that ADSL is a theoretical maximum, on average. Most ADSL users will have an actual connection speed of between 8mbps-22mbps and the NBN is actual speed. Anything faster than this for just “surfing the web” is overkill, and a waste of money. Where would you require a faster connection speed? if you start to use services like netflix and/or Foxtel[[wp>IPTV| IPTV]] to stream videos. Having more than ~5 users, may also be a consideration for a speed increase.
|
|
||||||
How much quota do you need? if you have had the Internet before, go look at your previous bills, most of the time you will see what you used for the billing period, use this figure as a basis to guesstimate how much quota you are going to need. If you have never had an Internet package before then as a guide I would recommend nothing less than 10GB quota per month for the average light Internet user. I can't emphasize this enough, please do your research before you take this as gospel. Most people do know someone who <del>“knows boats”</del> would be able to assist in assessing how much quota you may require.
|
|
||||||
|
|
||||||
==== Bang for Buck ====
|
|
||||||
Read the fine print………. READ THE FINE PRINT……… oh, did I mention fine print? Every Internet package has fine print. This fine print will cover things like:
|
|
||||||
* what is unmetered((this is a category of sites that you can use without it being counted towards your quota.))
|
|
||||||
* how much quota you have, read carefully some ISPs will charge by the megabyte if you go over
|
|
||||||
* what happens when you reach your quota limit (good ISPs will shape your speed ((slow your Internet connection speed)))
|
|
||||||
* what you should not do with your Internet package (some ISPs won’t allow you to host your own website.)
|
|
||||||
* contract period
|
|
||||||
* exit fees associated with leaving your contract early
|
|
||||||
* fees associated with moving house
|
|
||||||
* support
|
|
||||||
* your responsibilities
|
|
||||||
|
|
||||||
|
|
||||||
==== Further Considerations ====
|
|
||||||
**“Unlimited Packages”** Some ISPs do offer “unlimited packages”. Please read the fine print so you can get the definition of unlimited as sometimes unlimited does not exactly mean unlimited. Some ISPs have been know to use peak and off-peak times, during peak you will have a quota and off peak is “unlimited”.
|
|
||||||
A big consideration for unlimited or large packages with lower download speeds is calculating what you could actually download in that billing period. This is a simple task and would use the following formula.
|
|
||||||
|
|
||||||
(Billing Period Days x seconds in day) × max download speed in bits ÷ 8 = max bytes for period
|
|
||||||
|
|
||||||
Example:\\
|
|
||||||
Billing Period days = 30\\
|
|
||||||
Second in one day = 86,400\\
|
|
||||||
Max download speed = 22,000,000\\
|
|
||||||
\\
|
|
||||||
( 30 x 86,400 ) × 22,000,000 ÷ 8 = 7,128,000,000,000Bytes or 7.128TB
|
|
||||||
|
|
||||||
So with the example above a package with a quota above 7.128TB with a download speed of 22mb would be a waste of money.
|
|
||||||
|
|
||||||
|
|
||||||
**Bundled Items** We have all seen and heard of them.
|
|
||||||
//"Select our Internet Package for $120 a month and we will give you a telephone with free calls, 200gb of download and if you sign up for a 24month contract we will throw in a free iPad"//
|
|
||||||
|
|
||||||
With the exception of a modem-if you don't have one; be very careful of falling into this trap. These "Bundled Packages" are plain and simply designed to get your business. Believe me when I say you can get all of this for a hell of a lot cheaper. Again __READ THE FINE PRINT__ and calculate the cost of the whole contract period including any hidden fees and you will find that these are quite expensive packages. A simple way to test these packages is how much is thrown in, the more free stuff that is included outside of the Internet package, then the more desperate they are for your business. Listen to your gut and the age old saying //"If it's too good to be true, than it probably is"//. Once in my life time I have seen one of these packages and it was too good to be true, but turned out to actually be worth while in the long run, again this was more than likely a "once in a lifetime good package"
|
|
||||||
|
|
||||||
**Naked ADSL** works exactly the same as normal ADSL Internet but you don’t have to pay for the phone line as it is included in the “Naked ADSL package” if you don’t use the telephone much or you are utilizing VOIP choosing one of these packages can save you some money. Like ADSL this is only available in certain areas, Please confirm with your ISP for availability.
|
|
||||||
|
|
||||||
**Support** It's common practice for ISPs to outsource the first stage of customer support. This problem is a plague that needs to be truncated from the IT((Information Technology)) industry. Why? 9 times out of 10 the person on the other end of the phone either does not have a good grasp on our native language or has an accent that is so thick you can not understand them, which makes it very difficult for the hearing impaired. When this occurs the assistance you called for doesn't happen, and is escalated to someone else in the chain who may or may not be able to help you. In the end you are stuck with no internet and built up frustration from a 1:30h phone call.\\
|
|
||||||
There are however some ISPs who are old school. they will give you a callback after being on hold for a few minutes and if your assistance call needs to be escalated will either call you back or give a detailed handover to the next person you need to speak to. bottom line if you are not technically minded than ask around to find a good ISP who can assist you and be wary of outsourced tech support.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
===== Conclusion =====
|
|
||||||
Lets face it, The Internet has made our lives easier. You can now sit in your lounge room and read this long, very mind numbing article on how to choose a better Internet Service, do your Banking, Pay Bills, Buy Goods, <del>look at porn</del> and best of all place video calls to family and friends. What will the future hold? Who knows but given how far technology has evolved in the last 50 years, I think the next 50 will yield even more from this simple little invention courtesy of [[wp>darpa|DARPA]].
|
|
||||||
|
|
||||||
Like this article? Please consider buying me a coffee. Donations can be accepted via PayPal via our store at [[NFC>product-category/donation/|No Fuss Computing]]
|
|
||||||
|
|
||||||
Some ISPs in Australia:
|
|
||||||
- [[http://internode.on.net|Internode]]
|
|
||||||
- [[http://iinet.net.au|IINet]]
|
|
||||||
- [[http://westnet.com.au|WestNet]]
|
|
||||||
|
|
||||||
<wrap center important 90%>The information contained within this article based on the opinion of the author and is provided for informational purposes only. Before utilizing any information or advice from this article you are encouraged to do your own research</wrap>
|
|
||||||
|
|
Reference in New Issue
Block a user