...
 
Commits (23)
clone:
git:
image: plugins/git
tags: true
pipeline:
sass:
image: codycraven/sassc
pull: true
commands:
- sassc -p 0 -t compressed sass/main.scss sass/main.css
- sassc -p 0 -t compressed sass/chart.scss sass/chart.css
- sassc -p 0 -t compressed sass/status.scss sass/status.css
build:
image: golang
pull: true
environment:
- CGO_ENABLED=0
commands:
- go generate --run "fileb0x"
- go build -ldflags "-X main.VERSION=$(git describe --tags) -X main.BUILD_DATE=$(date --iso-8601=seconds) -X main.GIN_MODE=release" -o bin/hashworksNET *.go
- go test --covermode=atomic --coverprofile=coverage.out ./server
- ./bin/hashworksNET --version
codecov:
image: plugins/codecov
pull: true
files:
- coverage.out
secrets: [ codecov_token ]
when:
event: [ push, pull_request ]
status: [ success ]
deploy:
image: rics3n/drone-ansible:2
inventory: staging
inventory_path: deployment/inventories
playbook: deployment/deploy.yml
secrets: [ ssh_key ]
when:
branch: master
event: [push, tag, deployment]
selenium:
image: golang
pull: true
commands:
- cd acception
- if ! go test . --hub="selenium-chrome:4444" --url="https://hashworks.net/" --htmlPath acceptionTest.html --screenshotPath acceptionTest.png; then
- if [ -f acceptionTest.html ]; then echo "HTML:" "$FILEBIN_BASE"/"$(curl -s "$FILEBIN_BASE"/api/v2.1.1/file/upload -F apikey="$FILEBIN_APIKEY" -F "file=@acceptionTest.html" | cut -d \" -f 10)"; fi
- if [ -f acceptionTest.png ]; then echo "Screenshot:" "$FILEBIN_BASE"/"$(curl -s "$FILEBIN_BASE"/api/v2.1.1/file/upload -F apikey="$FILEBIN_APIKEY" -F "file=@acceptionTest.png" | cut -d \" -f 10)"; fi
- return 1
- fi
secrets: [ filebin_base, filebin_apikey ]
when:
branch: master
event: [push, tag, deployment]
restore:
image: rics3n/drone-ansible:2
inventory: staging
inventory_path: deployment/inventories
playbook: deployment/restore.yml
secrets: [ ssh_key ]
when:
branch: master
event: [push, tag, deployment]
status: [ failure ]
telegram:
image: appleboy/drone-telegram
pull: true
format: markdown
secrets: [telegram_to, telegram_token]
when:
event: [push, tag, deployment]
status: [ changed, failure ]
message: >
*Build of {{repo.name}}/{{commit.branch}} {{#success build.status}}*[succeeded]({{build.link}}) 💪{{else}}*[failed]({{build.link}}) 👎{{/success}}
{{build.event}} from {{commit.author}}: [{{commit.message}}]({{commit.link}})
services:
selenium-chrome:
image: selenium/standalone-chrome
pull: true
environment:
- HUB_HOST=selenium-chrome
when:
branch: master
event: [push, tag, deployment]
#variables:
# CODEGOV_TOKEN (project)
# ANSIBLE_SSH_KEY (project) base64 encoded
stages:
- generate
- build
- deploy
- acceptance
- restore
sass:
stage: generate
image:
name: codycraven/sassc:latest
entrypoint: [""]
script:
- sassc -p 0 -t compressed sass/main.scss sass/main.css
- sassc -p 0 -t compressed sass/chart.scss sass/chart.css
- sassc -p 0 -t compressed sass/status.scss sass/status.css
artifacts:
paths:
- sass/*.css
buildAndTest:
stage: build
image: golang:latest
variables:
CGO_ENABLED: 0
script:
- test -f sass/main.css
- test -f sass/chart.css
- test -f sass/status.css
- export GOPATH="$PWD/.go"
- go generate --run "fileb0x"
- go build -ldflags "-X main.VERSION=$(git describe --tags) -X main.BUILD_DATE=$(date --iso-8601=seconds) -X main.GIN_MODE=release" -o bin/hashworksNET *.go
- go test --covermode=atomic --coverprofile=coverage.out ./server
- test -f coverage.out
- curl -sL https://codecov.io/bash > codecov
- bash codecov -f coverage.out -t "$CODEGOV_TOKEN"
- ./bin/hashworksNET --version
artifacts:
paths:
- coverage.out
- bin/hashworksNET
cache:
key: go
paths:
- .go
.ansible: # Template
image:
name: mullnerz/ansible-playbook:latest
entrypoint: [""]
variables:
ANSIBLE_HOST_KEY_CHECKING: 'false'
before_script:
- echo "${ANSIBLE_SSH_KEY}" | base64 -d > ansible.key
- chmod 0600 ansible.key
only:
- master
- tags
deploy:
dependencies:
- buildAndTest
stage: deploy
extends: .ansible
script:
- ansible-playbook --private-key=ansible.key -i deployment/inventories/staging deployment/deploy.yml
- echo "true" > .deployed
artifacts:
paths:
- .deployed
selenium:
dependencies: []
stage: acceptance
image: golang
variables:
HUB_HOST: "selenium"
services:
- name: selenium/standalone-chrome:3.141.59-oxygen
alias: selenium
script:
- cd acception
- go test . --hub="${HUB_HOST}:4444" --url="https://hashworks.net/" --htmlPath acceptionTest.html --screenshotPath acceptionTest.png
when: delayed
start_in: 10 seconds
only:
- master
- tags
artifacts:
paths:
- acception/acceptionTest.html
- acception/acceptionTest.png
when: on_failure
restore:
dependencies:
- deploy
stage: restore
extends: .ansible
script:
- test -f .deployed || exit 0
- ansible-playbook --private-key=ansible.key -i deployment/inventories/staging deployment/restore.yml
when: on_failure
# hashworks.net source
[![droneio](https://drone.github.hashworks.net/api/badges/hashworks/hashworksNET/status.svg?branch=master)](https://drone.github.hashworks.net/hashworks/hashworksNET) [![codecov](https://codecov.io/gh/hashworks/hashworksNET/branch/dev/graph/badge.svg)](https://codecov.io/gh/hashworks/hashworksNET)
[![pipeline status](https://git.hashworks.net/hashworks/hashworksNET/badges/master/pipeline.svg)](https://git.hashworks.net/hashworks/hashworksNET/commits/master) [![codecov](https://codecov.io/gh/hashworks/hashworksNET/branch/dev/graph/badge.svg)](https://codecov.io/gh/hashworks/hashworksNET)
Repository of [hashworks.net](https://hashworks.net).
......@@ -18,6 +18,6 @@ Using the [httptest](https://golang.org/pkg/net/http/httptest/) package we can u
Additionally, acception tests are done by the CD system.
## Continuous Delivery
[Drone](https://drone.io/) in combination with [Ansible](https://www.ansible.com/) is used as the CD system. Any commit or pull request is built, tested and provided with a coverage report. Merges on the protected master branch will be deployed after successfull unit tests. Since the server is a single binary, including all static files thanks to [fileb0x](https://github.com/UnnoTed/fileb0x/) this process becomes trivial. Using systemd the service is sandboxed.
GitlabCI in combination with [Ansible](https://www.ansible.com/) is used as the CD system. Any commit or pull request is built, tested and provided with a coverage report. Merges on the protected master branch will be deployed after successfull unit tests. Since the server is a single binary, including all static files thanks to [fileb0x](https://github.com/UnnoTed/fileb0x/) this process becomes trivial. Using systemd the service is sandboxed.
After a successfull deployment acception tests using [agouti](https://github.com/sclevine/agouti) are run. On failure a backup is restored.
\ No newline at end of file
After a successfull deployment acception tests using [agouti](https://github.com/sclevine/agouti) are run. On failure a backup is restored.
......@@ -115,8 +115,8 @@ func TestAcception(t *testing.T) {
// Header should contain some links
header := page.FindByXPath("//header")
for _, link := range []string{"/", "/status", "https://github.com/hashworks", "https://steamcommunity.com/id/hashworks", "https://www.reddit.com/user/hashworks/posts/"} {
linkElement := header.FindByXPath(fmt.Sprintf("//a[@href='%s']", link))
for _, link := range []string{"/", "/status", "https://git.hashworks.net", "https://github.com/hashworks", "https://steamcommunity.com/id/hashworks", "https://www.reddit.com/user/hashworks/posts/"} {
linkElement := header.FindByXPath(fmt.Sprintf("//nav//a[@href='%s']", link))
if count, err := linkElement.Count(); assert.NoError(t, err) {
assert.Equal(t, count, 1)
}
......
......@@ -6,3 +6,5 @@ require (
github.com/sclevine/agouti v3.0.0+incompatible
github.com/stretchr/testify v1.2.2
)
go 1.13
......@@ -3,40 +3,33 @@
tasks:
- name: Create backup of systemd unit file with fixed name
copy:
src: /etc/systemd/system/hashworksNET.service
dest: /etc/systemd/system/hashworksNET.service.bak
src: ~/.config/systemd/user/hashworksNET.service
dest: ~/.config/systemd/user/hashworksNET.service.bak
remote_src: yes
owner: root
group: root
mode: 0600
- name: Copy systemd unit file
copy:
src: ../systemd/hashworksNET.service
dest: /etc/systemd/system/hashworksNET.service
owner: root
group: root
dest: ~/.config/systemd/user/hashworksNET.service
mode: 0600
- name: Create backup of binary file with fixed name
copy:
src: /usr/local/bin/hashworksNET
dest: /usr/local/bin/hashworksNET.bak
src: ~/bin/hashworksNET
dest: ~/bin/hashworksNET.bak
remote_src: yes
owner: root
group: root
mode: 0775
mode: 0770
- name: Copy binary
copy:
src: ../bin/hashworksNET
dest: /usr/local/bin/hashworksNET
owner: root
group: root
mode: 0775
dest: ~/bin/hashworksNET
mode: 0770
- name: Restart systemd service
systemd:
name: hashworksNET
scope: user
daemon_reload: true
state: restarted
......@@ -2,4 +2,4 @@
hive.hashworks.net
[hive:vars]
ansible_ssh_user=root
ansible_ssh_user=ansible_hashworksnet
......@@ -13,25 +13,24 @@ require (
github.com/gin-gonic/gin v1.3.0
github.com/go-errors/errors v1.0.1
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.2.0 // indirect
github.com/gomodule/redigo v2.0.0+incompatible // indirect
github.com/hashworks/go-chart v2.0.2-0.20181012215714-9fd7836f84d7+incompatible
github.com/influxdata/influxdb v1.6.3
github.com/json-iterator/go v1.1.5 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/memcachier/mc v2.0.1+incompatible // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 // indirect
github.com/stretchr/testify v1.2.2
github.com/securego/gosec v0.0.0-20190912120752-140048b2a218 // indirect
github.com/stretchr/testify v1.4.0
github.com/ugorji/go/codec v0.0.0-20180831062425-e253f1f20942 // indirect
github.com/unrolled/secure v0.0.0-20180914162101-439d7b25425f
github.com/urfave/cli v1.20.0
github.com/wcharczuk/go-chart v2.0.1+incompatible
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81 // indirect
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
golang.org/x/net v0.0.0-20190909003024-a7b16738d86b
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
)
go 1.13
This diff is collapsed.
[Unit]
Description=hashworks.net Server
ConditionFileIsExecutable=/usr/local/bin/hashworksNET
ConditionFileIsExecutable=%h/bin/hashworksNET
[Service]
EnvironmentFile=/etc/hashworksNET/server.conf
ExecStart=/usr/local/bin/hashworksNET
EnvironmentFile=%h/server.conf
ExecStart=%h/bin/hashworksNET
DynamicUser=true
# implies:
# ProtectSystem=strict
# ProtectHome=read-only
# RemoveIPC=
# PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=read-only
PrivateTmp=yes
NoNewPrivileges=yes
ProtectControlGroups=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
\ No newline at end of file
WantedBy=default.target
......@@ -34,26 +34,32 @@
</nav>
<nav class="icons">
<a href="https://git.hashworks.net" rel="nofollow" target="_blank" class="icon">
<svg viewBox="0 0 24 24" height="22px" width="24px">
<desc>GitLab icon</desc>
<path d="M23.955 13.587l-1.342-4.135-2.664-8.189c-.135-.423-.73-.423-.867 0L16.418 9.45H7.582L4.919 1.263C4.783.84 4.185.84 4.05 1.26L1.386 9.449.044 13.587c-.121.375.014.789.331 1.023L12 23.054l11.625-8.443c.318-.235.453-.647.33-1.024"/>
</svg>
</a>
<a href="https://github.com/hashworks" rel="nofollow" target="_blank" class="icon">
<svg height="23px" width="24px">
<desc>GitHub Icon</desc>
<path d="M7.2 6.6h-.1c-.5 1.4-.2 2.3-.1 2.6-.6.7-1 1.6-1 2.6 0 3.8 2.4 4.6 4.6 4.9-.2 0-.6.2-.8.8-.4.2-1.8.7-2.6-.7 0 0-.5-.8-1.3-.9 0 0-.8 0-.1.5 0 0 .6.3.9 1.3 0 0 .5 1.7 3 1.1v3.1h5v-3.5c0-1-.4-1.5-.8-1.8 2.2-.2 4.6-1 4.6-4.8 0-1.1-.4-2-1-2.6.1-.3.4-1.2-.1-2.6 0 0-.8-.3-2.7 1-.8-.2-1.6-.3-2.5-.3-.8 0-1.7.1-2.5.3-1.4-1-2.2-1-2.6-1zm12.8 15.4h-16c-1.1 0-2-.9-2-2v-16c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2v16c0 1.1-.9 2-2 2z"></path>
<path d="M7.2 6.6h-.1c-.5 1.4-.2 2.3-.1 2.6-.6.7-1 1.6-1 2.6 0 3.8 2.4 4.6 4.6 4.9-.2 0-.6.2-.8.8-.4.2-1.8.7-2.6-.7 0 0-.5-.8-1.3-.9 0 0-.8 0-.1.5 0 0 .6.3.9 1.3 0 0 .5 1.7 3 1.1v3.1h5v-3.5c0-1-.4-1.5-.8-1.8 2.2-.2 4.6-1 4.6-4.8 0-1.1-.4-2-1-2.6.1-.3.4-1.2-.1-2.6 0 0-.8-.3-2.7 1-.8-.2-1.6-.3-2.5-.3-.8 0-1.7.1-2.5.3-1.4-1-2.2-1-2.6-1zm12.8 15.4h-16c-1.1 0-2-.9-2-2v-16c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2v16c0 1.1-.9 2-2 2z"/>
</svg>
</a>
<a href="https://steamcommunity.com/id/hashworks" rel="nofollow" target="_blank" class="icon">
<svg viewBox="0 0 512 512" height="21px" width="21px">
<desc>Steam Icon</desc>
<path d="M 151.961,418.005 C 165.533,418.005 178.854,411.437 186.947,399.297 C 199.814,379.996 194.598,353.92 175.298,341.053 L 142.261,319.029 C 147.915,317.489 153.858,316.651 160.00,316.651 C 197.196,316.651 227.348,346.803 227.348,384.00 C 227.348,421.197 197.195,451.349 159.999,451.349 C 123.797,451.349 94.277,422.783 92.725,386.962 L 128.702,410.946 C 135.863,415.72 143.955,418.005 151.961,418.005 ZM 426.67,0.00 C 473.608,0.00 512.00,38.406 512.00,85.344 L 512.00,426.658 C 512.00,473.626 473.608,512.00 426.67,512.00 L 85.344,512.00 C 38.406,512.00 0.00,473.625 0.00,426.659 L 0.00,325.145 L 60.667,365.589 C 54.841,397.176 64.136,431.004 88.566,455.434 C 128.018,494.886 191.981,494.886 231.434,455.434 C 255.668,431.201 265.009,397.719 259.472,366.351 L 384.001,254.858 L 384.00,254.857 C 407.124,251.538 429.408,240.985 447.197,223.196 C 490.935,179.458 490.935,108.543 447.197,64.804 C 403.457,21.065 332.543,21.065 288.804,64.804 C 271.015,82.593 260.462,104.877 257.143,128.00 L 257.143,128.00 L 154.796,283.115 C 138.872,283.931 123.107,288.497 108.933,296.811 L 0.00,224.189 L 0.00,85.344 C 0.00,38.406 38.405,0.00 85.343,0.00 L 426.67,0.00 ZM 448.00,144.00c0.00-44.183-35.817-80.00-80.00-80.00s-80.00,35.817-80.00,80.00s 35.817,80.00, 80.00,80.00S 448.00,188.183, 448.00,144.00z M 320.00,144.00 c0.00-26.51, 21.49-48.00, 48.00-48.00s 48.00,21.49, 48.00,48.00s-21.49,48.00-48.00,48.00S 320.00,170.51, 320.00,144.00z"></path>
<path d="M 151.961,418.005 C 165.533,418.005 178.854,411.437 186.947,399.297 C 199.814,379.996 194.598,353.92 175.298,341.053 L 142.261,319.029 C 147.915,317.489 153.858,316.651 160.00,316.651 C 197.196,316.651 227.348,346.803 227.348,384.00 C 227.348,421.197 197.195,451.349 159.999,451.349 C 123.797,451.349 94.277,422.783 92.725,386.962 L 128.702,410.946 C 135.863,415.72 143.955,418.005 151.961,418.005 ZM 426.67,0.00 C 473.608,0.00 512.00,38.406 512.00,85.344 L 512.00,426.658 C 512.00,473.626 473.608,512.00 426.67,512.00 L 85.344,512.00 C 38.406,512.00 0.00,473.625 0.00,426.659 L 0.00,325.145 L 60.667,365.589 C 54.841,397.176 64.136,431.004 88.566,455.434 C 128.018,494.886 191.981,494.886 231.434,455.434 C 255.668,431.201 265.009,397.719 259.472,366.351 L 384.001,254.858 L 384.00,254.857 C 407.124,251.538 429.408,240.985 447.197,223.196 C 490.935,179.458 490.935,108.543 447.197,64.804 C 403.457,21.065 332.543,21.065 288.804,64.804 C 271.015,82.593 260.462,104.877 257.143,128.00 L 257.143,128.00 L 154.796,283.115 C 138.872,283.931 123.107,288.497 108.933,296.811 L 0.00,224.189 L 0.00,85.344 C 0.00,38.406 38.405,0.00 85.343,0.00 L 426.67,0.00 ZM 448.00,144.00c0.00-44.183-35.817-80.00-80.00-80.00s-80.00,35.817-80.00,80.00s 35.817,80.00, 80.00,80.00S 448.00,188.183, 448.00,144.00z M 320.00,144.00 c0.00-26.51, 21.49-48.00, 48.00-48.00s 48.00,21.49, 48.00,48.00s-21.49,48.00-48.00,48.00S 320.00,170.51, 320.00,144.00z"/>
</svg>
</a>
<a href="https://www.reddit.com/user/hashworks/posts/" rel="nofollow" target="_blank" class="icon">
<svg viewBox="0 0 512 512" height="24px" width="24px">
<desc>Reddit Icon</desc>
<path d="M480.5,251c0-27.7-22.2-50.2-49.5-50.2c-13,0-24.7,5-33.6,13.3c-32.4-22.8-76.1-37.8-124.9-40.6l21.9-73.2l67.1,13.5 c2.3,22.7,21.2,40.4,44.3,40.4c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0,0.2,0c24.6,0,44.5-20.2,44.5-45.1S430.7,64,406.1,64 c-0.1,0-0.1,0-0.2,0c0,0-0.1,0-0.1,0c-17.2,0-32,9.8-39.5,24.3l-89.7-18l-30.8,103l-2.5,0.1c-50.3,2.2-95.5,17.4-128.7,40.7 c-8.8-8.3-20.6-13.3-33.6-13.3c-27.3,0-49.5,22.5-49.5,50.2c0,19.6,11,36.5,27.1,44.8c-0.8,4.9-1.2,9.8-1.2,14.8 C57.5,386.4,146.4,448,256,448s198.5-61.6,198.5-137.5c0-5-0.4-9.9-1.1-14.8C469.5,287.4,480.5,270.5,480.5,251z M65.8,271.1 c-6.6-4.5-10.9-12.1-10.9-20.8c0-13.8,11.1-25.1,24.7-25.1c5.6,0,10.8,1.9,15,5.1C81.1,242.2,71.1,256,65.8,271.1z M389.3,109.1 c0-9.2,7.4-16.8,16.5-16.8s16.5,7.5,16.5,16.8c0,9.2-7.4,16.8-16.5,16.8S389.3,118.4,389.3,109.1z M158.5,288.4 c0-17.6,14.2-31.8,31.8-31.8s31.8,14.2,31.8,31.8c0,17.6-14.2,31.8-31.8,31.8S158.5,306,158.5,288.4z M256,400 c-47.6-0.2-76-28.5-77.2-29.7l12.6-12.4c0.2,0.2,23.7,24.2,64.6,24.4c40.3-0.2,64.2-24.2,64.5-24.4l12.6,12.4 C331.9,371.5,303.6,399.8,256,400z M322.3,320.2c-17.6,0-31.8-14.2-31.8-31.8c0-17.6,14.2-31.8,31.8-31.8s31.8,14.2,31.8,31.8 C354.1,306,339.8,320.2,322.3,320.2z M446.4,271.5c-5.4-15.3-15.6-29.4-29.3-41.4c4.2-3.3,9.5-5.2,15.2-5.2 c13.9,0,25.1,11.4,25.1,25.5C457.5,259.2,453.1,266.9,446.4,271.5z"></path>
<path d="M480.5,251c0-27.7-22.2-50.2-49.5-50.2c-13,0-24.7,5-33.6,13.3c-32.4-22.8-76.1-37.8-124.9-40.6l21.9-73.2l67.1,13.5 c2.3,22.7,21.2,40.4,44.3,40.4c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0,0.2,0c24.6,0,44.5-20.2,44.5-45.1S430.7,64,406.1,64 c-0.1,0-0.1,0-0.2,0c0,0-0.1,0-0.1,0c-17.2,0-32,9.8-39.5,24.3l-89.7-18l-30.8,103l-2.5,0.1c-50.3,2.2-95.5,17.4-128.7,40.7 c-8.8-8.3-20.6-13.3-33.6-13.3c-27.3,0-49.5,22.5-49.5,50.2c0,19.6,11,36.5,27.1,44.8c-0.8,4.9-1.2,9.8-1.2,14.8 C57.5,386.4,146.4,448,256,448s198.5-61.6,198.5-137.5c0-5-0.4-9.9-1.1-14.8C469.5,287.4,480.5,270.5,480.5,251z M65.8,271.1 c-6.6-4.5-10.9-12.1-10.9-20.8c0-13.8,11.1-25.1,24.7-25.1c5.6,0,10.8,1.9,15,5.1C81.1,242.2,71.1,256,65.8,271.1z M389.3,109.1 c0-9.2,7.4-16.8,16.5-16.8s16.5,7.5,16.5,16.8c0,9.2-7.4,16.8-16.5,16.8S389.3,118.4,389.3,109.1z M158.5,288.4 c0-17.6,14.2-31.8,31.8-31.8s31.8,14.2,31.8,31.8c0,17.6-14.2,31.8-31.8,31.8S158.5,306,158.5,288.4z M256,400 c-47.6-0.2-76-28.5-77.2-29.7l12.6-12.4c0.2,0.2,23.7,24.2,64.6,24.4c40.3-0.2,64.2-24.2,64.5-24.4l12.6,12.4 C331.9,371.5,303.6,399.8,256,400z M322.3,320.2c-17.6,0-31.8-14.2-31.8-31.8c0-17.6,14.2-31.8,31.8-31.8s31.8,14.2,31.8,31.8 C354.1,306,339.8,320.2,322.3,320.2z M446.4,271.5c-5.4-15.3-15.6-29.4-29.3-41.4c4.2-3.3,9.5-5.2,15.2-5.2 c13.9,0,25.1,11.4,25.1,25.5C457.5,259.2,453.1,266.9,446.4,271.5z"/>
</svg>
</a>
</nav>
</header>
<div class="content">
{{end}}
\ No newline at end of file
{{end}}