Compare commits

...

54 Commits

Author SHA1 Message Date
Mathis 501c92444b Update content/blog/cuda_net.md
Build website container / Build image (push) Successful in 3m7s Details
2024-04-22 14:32:25 +00:00
Mathis b8a160bac8 Update content/blog/coding_style
Build website container / Build image (push) Successful in 1m41s Details
2024-04-06 12:31:43 +00:00
Mathis dc96335c5d Update content/blog/cuda_net.md
Build website container / Build image (push) Successful in 15s Details
2024-04-03 20:34:03 +00:00
Mathis 3c71b6464d Add content/blog/coding_style
Build website container / Build image (push) Successful in 1m28s Details
2024-04-03 20:32:11 +00:00
Mathis 5c8e4c91e3 CUDAnet post draft
Build website container / Build image (push) Successful in 40s Details
2024-03-06 10:24:00 +00:00
LordMathis b8a62de72d Update Dockerfile
Build website container / Build image (push) Successful in 25s Details
2024-02-15 21:59:46 +01:00
LordMathis 14d3a06479 Update theme dependency 2024-02-15 21:59:32 +01:00
LordMathis cc7925c5e2 Update about me
Build website container / Build image (push) Successful in 10m49s Details
2024-02-13 18:02:58 +01:00
Mathis 9886416649 Change actions container
Build website container / Build image (push) Failing after 12m16s Details
2024-02-13 10:46:17 +00:00
Mathis 6e175e0a60 Add tags
Build website container / Build image (push) Successful in 10m45s Details
2024-01-05 20:31:31 +01:00
Mathis 2ed43b4c83 Enable access logs 2024-01-05 20:29:25 +01:00
Mathis 3c71ebe5e2 Write gitea actions post
Build website container / Build image (push) Successful in 11m12s Details
2023-12-28 15:56:47 +01:00
LordMathis 4de8e60977 Update theme dependency
Build website container / Build image (push) Successful in 8m55s Details
2023-12-06 18:19:04 +01:00
Mathis c8a60f51ab Remove extra braces from build command
Build website container / Build image (push) Successful in 9m7s Details
2023-12-03 17:30:38 +00:00
LordMathis e751ce1576 Extend gitea actions draft
Build website container / Build image (push) Successful in 6s Details
2023-12-03 00:29:21 +01:00
LordMathis b342a8e020 Remove resume from container 2023-12-03 00:12:11 +01:00
LordMathis 5dbe7c6f86 Change docker tag to current data
Build website container / Build image (push) Successful in 6s Details
2023-11-25 20:46:37 +01:00
LordMathis b80cd1e8bf Add actions draft 2023-11-25 20:46:19 +01:00
LordMathis ec1792c2f6 Rename container passthrough file 2023-11-25 20:46:08 +01:00
LordMathis cf4fc0b442 Fix docker push command in workflow
Build website container / Build image (push) Successful in 16s Details
2023-11-25 18:50:32 +01:00
LordMathis 2bea6dd459 Use docker add instead of wget
Build website container / Build image (push) Failing after 11s Details
2023-11-25 18:49:01 +01:00
LordMathis 92e47a8038 Fix image tag typo
Build website container / Build image (push) Failing after 10m51s Details
2023-11-25 16:57:02 +01:00
LordMathis 5d3e4305ce Use repo owner variable instead of gitea.actor
Build website container / Build image (push) Failing after 6s Details
2023-11-25 16:55:34 +01:00
LordMathis 1ac1c32e07 Fix typo in image name
Build website container / Build image (push) Failing after 6s Details
2023-11-25 16:49:29 +01:00
LordMathis 05d70945d3 Run docker commands directly
Build website container / Build image (push) Failing after 6s Details
2023-11-25 16:46:09 +01:00
LordMathis 9ef3e44252 Remove docker installation step
Build website container / Build image (push) Failing after 1m58s Details
2023-11-23 21:30:19 +01:00
LordMathis 859366880b Add install docker step
Build website container / Build image (push) Failing after 5m13s Details
2023-11-23 20:54:20 +01:00
LordMathis f5af83357a Switch to docker action
Build website container / Build image (push) Failing after 35s Details
2023-11-23 20:31:38 +01:00
LordMathis 58e3d0ab22 Update package list
Build website container / Build image (push) Failing after 3m8s Details
2023-11-23 19:29:10 +01:00
LordMathis d07ee060e9 Specify action container
Build website container / Build image (push) Failing after 1m22s Details
2023-11-23 19:26:01 +01:00
LordMathis ba49ca249d Add install buildah package step
Build website container / Build image (push) Failing after 8s Details
2023-11-23 19:23:46 +01:00
LordMathis dcf3ec12fa Create initial release workflow
Build website container / Build image (push) Failing after 1m10s Details
2023-11-23 19:13:55 +01:00
LordMathis 91eee78ec7 Update hugo and theme 2023-11-22 22:00:23 +01:00
LordMathis b76681ab23 Update gitea ssh passthrough post 2023-11-22 22:00:02 +01:00
LordMathis bdf6335c83 Merge commit 'eca50e8e00ce7e66a406cfdd09632f90063f183d' 2023-11-22 20:58:05 +01:00
LordMathis 8c66901bda Remove everything 2023-11-22 20:56:57 +01:00
LordMathis eca50e8e00 Finish gh resume article 2023-10-02 22:45:29 +02:00
LordMathis 79d0e98b13 Create resume gh action blog post 2023-09-28 21:48:32 +02:00
Matúš Námešný f3d80f5e98 Update resujme 2023-08-18 19:46:52 +00:00
Matúš Námešný b3342d575a Update content/about.md 2023-08-18 13:40:55 +00:00
LordMathis fcfcf6b388 Add resume 2023-08-13 17:39:49 +02:00
LordMathis a6f9c744bc Add back to hugo post 2023-08-13 17:20:57 +02:00
LordMathis 78fa6b708f Update theme dependency 2023-08-13 14:06:58 +02:00
LordMathis d788ddfcb2 Run go mod tidy 2023-07-27 22:29:30 +02:00
LordMathis 81a93304ca Update about.md 2023-07-27 22:29:16 +02:00
LordMathis 3f97bde5e3 Add mastodon link 2023-07-27 22:29:05 +02:00
LordMathis b4ca1d0b6a Update about me 2023-02-13 22:11:40 +01:00
LordMathis fd32c6e935 Add testing section to gitea 2023-02-13 22:11:23 +01:00
LordMathis ec42485c6f Add Dockerfile 2023-02-13 20:05:21 +01:00
LordMathis b77d343666 Update theme version 2023-02-12 22:11:45 +01:00
LordMathis e0c56dc6c0 Add gitea blog post 2023-02-12 21:29:19 +01:00
LordMathis 6ae7e75913 Add gitignore 2023-02-12 21:29:03 +01:00
LordMathis 24545acb1a Add favicon 2023-02-12 21:28:53 +01:00
LordMathis 3fa409f68b Initial commit 2023-02-12 19:02:38 +01:00
59 changed files with 520 additions and 12697 deletions

View File

@ -1,6 +0,0 @@
node_modules/
npm-debug.log
yarn-error.log
public/
.git/
.cache/

View File

@ -1,34 +0,0 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
charset = utf-8
# 4 space indentation
[*.py]
indent_style = space
indent_size = 4
# Tab indentation (no size specified)
[Makefile]
indent_style = tab
# Indentation override for all JS under lib directory
[lib/**.js]
indent_style = space
indent_size = 2
# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2

View File

@ -1,23 +0,0 @@
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": [
"standard",
"plugin:react/recommended"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "babel-eslint",
"plugins": [
"babel",
"react"
],
"rules": {
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
}
}

View File

@ -0,0 +1,31 @@
name: Build website container
on:
push:
branches:
- main
jobs:
build:
name: Build image
runs-on: ubuntu-latest
container: git.namesny.com/cluster/act-runner:v1
env:
IMAGE_NAME: namesny-com
REGISTRY: git.namesny.com
REPO_OWNER: mathis
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: git.namesny.com
username: ${{ gitea.actor }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Build and push
run: |
TODAY=$(date +'%Y-%m-%d')
docker build -t ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:${TODAY} -t ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:latest .
docker push ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:${TODAY}
docker push ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:latest

View File

@ -1,67 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '16 19 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

81
.gitignore vendored
View File

@ -1,72 +1,13 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Generated files by hugo
/public/
/resources/_gen/
/assets/jsconfig.json
hugo_stats.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Executable may be added to repository
hugo.exe
hugo.darwin
hugo.linux
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# dotenv environment variable files
.env*
# gatsby files
.cache/
public
# Mac files
.DS_Store
# Yarn
yarn-error.log
.pnp/
.pnp.js
# Yarn Integrity file
.yarn-integrity
# Custom
/content
# Temporary lock file while building
/.hugo_build.lock

View File

@ -1,4 +0,0 @@
.cache
package.json
package-lock.json
public

View File

@ -1,4 +0,0 @@
{
"arrowParens": "avoid",
"semi": false
}

27
Dockerfile Normal file
View File

@ -0,0 +1,27 @@
FROM golang:1.21-bookworm as build
ARG DART_SASS_VERSION=1.70.0
ARG HUGO_VERSION=0.122.0
WORKDIR /app
# Install Dart Sass
RUN curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
cp -r dart-sass/* /usr/local/bin && \
rm -rf dart-sass*
# Install Hugo
RUN curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb && \
apt install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb && \
rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb
COPY . /app
RUN hugo mod get -u && \
hugo --gc --minify
FROM nginx:stable-alpine
COPY --from=build /app/public /usr/share/nginx/html/
COPY ./nginx.conf /etc/nginx/conf.d/default.conf

14
LICENSE
View File

@ -1,14 +0,0 @@
The BSD Zero Clause License (0BSD)
Copyright (c) 2020 Gatsby Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@ -1,8 +0,0 @@
# Personal Website
This is a source code for my personal website. It's implemented using Gatsby.js
## TODO
* Light theme
* Remove Google Fonts CDN

6
archetypes/default.md Normal file
View File

@ -0,0 +1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

50
config.toml Normal file
View File

@ -0,0 +1,50 @@
baseURL = 'https://namesny.com/'
languageCode = 'en-us'
[module]
[[module.imports]]
path = "github.com/LordMathis/hugo-theme-nightfall"
[menu]
[[menu.header]]
name = "blog"
weight = 0
url = "blog"
[[menu.header]]
name = "about"
weight = 1
url = "about"
[params]
user = "hello"
hostname = "namesny.com"
[params.author]
name = "Matúš Námešný"
[[params.social]]
key = 0
name = "github"
url = "https://github.com/LordMathis"
[[params.social]]
key = 1
name = "gitea"
url = "https://git.namesny.com/Mathis"
[[params.social]]
key = 2
name = "linkedin"
url = "https://www.linkedin.com/in/matus-namesny/"
[[params.social]]
key = 3
name = "mastodon"
url = "https://toot.io/@mathis"
rel = "me"
[[params.social]]
key = 4
name = "email"
url = "mailto:matus@namesny.com"

24
content/about.md Normal file
View File

@ -0,0 +1,24 @@
---
title: 'About Me'
showMetadata: false
---
Hello there.
I am Matúš [ˈmatuːʃ]. I am a Machine Learning Engineer based in Darmstadt, Germany. I focus on MLOps bridging the gap between Data Science, DevOps and Software Engineering. I am interested in broad range of topics including Machine Learning, Cloud, DevOps, Linux and open source.
After graduating in Artificial Intelligence and Natural Language Processing I joined Konica Minolta in Brno, Czechia, where I worked as an R&D Engineer developing a Python application that provides a unified approach for production ML model deployment. I was also deploying ML applications and MLOps tools to the cloud with Docker and Kubernetes which sparked my interest in DevOps and Cloud.
Currently, I work at Telespazio Germany as a Software Engineer. I participated in the development of a Kubeflow based Machine Learning Platform for Spacecraft Operational datasets. Nowadays I am working on a question-answering Chatbot the helps users explain complex documentation.
Here are some interesting projects that I'm working on in my free time:
* [k3s-configs](https://git.namesny.com/Cluster/k3s-configs) - Kustomize manifests for my self-hosted cluster.
* [neural-nets](https://github.com/LordMathis/neural-nets) - Small neural network library written in C from scratch.
* [GitEcho](https://github.com/LordMathis/GitEcho) - Backup tool for git repositories.
* [CUDANet](https://github.com/LordMathis/CUDANet) - Convolutional neural network library with CUDA support.
I also maintain two themes for [Hugo](https://gohugo.io), a static site generator:
* [Nix](https://github.com/LordMathis/hugo-theme-nix)
* [Nightfall](https://github.com/LordMathis/hugo-theme-nightfall)

3
content/blog/_index.md Normal file
View File

@ -0,0 +1,3 @@
---
title: "Blog"
---

View File

@ -0,0 +1,47 @@
---
title: "Back to Hugo"
date: "2023-08-13"
tags:
- gatsby
- hugo
---
Over the years, this website was running on WordPress, Hugo, a custom React SPA, server-side rendered React, Gatsby, and now I'm back to Hugo.
<!--more-->
## First Hugo Website
I created my first Hugo website in 2016 while still in University studying Computer Science. I started looking for internships and thought that having a personal website would enhance my appeal. I created the [Nix theme](https://github.com/LordMathis/hugo-theme-nix), a minimalistic theme inspired by Unix and the terminal. Looking back at the code, it's actually not that bad considering I had zero experience with web development. But I think it speaks more about the simplicity of Hugo and Bootstrap rather than my skills.
If I were to rewrite this theme from scratch, I would implement many things differently. However, many people use the theme, so I continue to maintain it.
## Here Comes React
Hugo was working perfectly fine for my needs, but for some reason, I wanted something more. Since I was already learning React and Node.js, I decided to build my website using React. Initially, I started building the website as a standard React app. I created all the components that I thought I might need, and the website quickly grew.
Then I learned about universal (isomorphic) rendering and decided to give it a try. This part of development took me the longest. My challenge with implementing universal rendering was a distinct lack of up-to-date tutorials. They all used outdated versions of Webpack or React Router, or didn't utilize React Router at all. Another issue was that some tutorials were using babel-node in production, which is not recommended.
After finally implementing universal rendering, the next issue to solve was how to deliver content. A simpler approach would be to create a new React component for each blog post and "hard code" the content. However, that's not very React-like. Instead, I implemented a simple API in Express.
There are many more aspects that I didn't mention, things I spent hours working on, only to change my mind after implementation. An honorable mention goes to the CSS and the overall style of the website, which underwent several changes. I also reinvented the wheel multiple times, opting to build features from scratch rather than using existing modules.
So now, I had a new website that was much more complex but had fewer features than my initial Hugo website.
## The Great Gatsby
My React-based website wasn't fully server-side rendered. The only server-rendered element was the page layout, while the content was served via an API and rendered on the client side. Thus, I found myself running a Node.js app at all times for a relatively simple website with minimal visitors and content. Instead of embarking on creating my own server-side renderer, I got sidetracked by a captivating newcomer: Gatsby.
Migrating to Gatsby wasn't overly challenging since I already had all my styles and components ready. I just needed to grasp how to write GraphQL queries to fetch content and assemble a set of Gatsby plugins for website building. The initial implementation of the Gatsby website was enjoyable, but ongoing maintenance proved to be a hassle.
## Move Fast and Break Things
The JavaScript landscape evolves at breakneck speed. Libraries that emerged yesterday risk deprecation tomorrow. Not to mention the ceaseless discovery of vulnerabilities every day. To mitigate this, I established dependabot security alerts for my website's GitHub repository. At one point, dependabot became the primary contributor.
While the detected vulnerabilities didn't directly threaten my server, as the website generated static HTML files and was served by nginx, a chain of vulnerabilities encompassing Gatsby, nginx, and Docker would be necessary for a genuine threat. Nevertheless, uncertainty lingered.
In the end, I opted to return to Hugo. You can still explore the archived React/Gatsby source code [here](https://git.namesny.com/Mathis/namesny-com-gatsby-archive).
## Full Circle
Instead of revisiting my old Nix theme, I chose to create a new theme: [Nightfall](https://github.com/LordMathis/hugo-theme-nightfall), based on the layout of my Gatsby website. Migrating to Hugo was relatively straightforward, thanks to React components. I only needed to replace JSX tags with appropriate HTML tags and integrate Hugo partials. I welcome all contributions to both the Nix and Nightfall themes.

24
content/blog/coding_style Normal file
View File

@ -0,0 +1,24 @@
---
title: "Coding style"
draft: true
---
I had a few interviews where I was asked about my coding style. I wasn't sure how to respond. I'm not following dogmatically any one coding principle such as Clean Code or TDD. Coding standards are hard, thats why there are so many books about it. I pick and choose the ideas and try to follow those in my code.
I would be surprised if I follow the same ideas in 5 years. The style is evolving and my opinions change.
Here are ideas that I currently follow:
- never nesting
- early return
- fight abstractions
- grugg brained dev
- don't repeat yourself thrice
Sources:
- https://www.youtube.com/watch?v=tD5NrevFtbU
- https://www.youtube.com/watch?v=CFRhGnuXG-4
- https://grugbrain.dev/
- https://testing.googleblog.com/2023/09/else-nuances.html
- https://www.youtube.com/watch?v=bJQj1uKtnus

29
content/blog/cuda_net.md Normal file
View File

@ -0,0 +1,29 @@
---
title: Writing a Convolutional Neural Network library with CUDA Support
draft: true
---
Straightforward project, learned a lot more than I expected.
"Just use cuBLAS, it'll be easier. You don't have to implement custom CUDA kernels.", they said. Actually, noone said that. I just thought that because I didn't do enough research.
Why not combine multiple challenging things into 1 (C++, cmake, CUDA, CNN)
Quickly discovering that without writing custom kernels, you can't really progress
- cuBLAS column major layout, macro
- cmake woes (findCUDA)
- google test
- padding kernel
- column major / row major headache
- removing cuBLAS -> just row major representation
- naive conv2d
- learning 3D memory representation
- optimizing conv2d
- softmax sum reduce
- softmax numerical stability - max reduce
- custom binary weights file - (safetensors - json parser vs csv) values overwritten by header
- tests passing -> implement AlexNet
- AlexNet cmake, opencv
- AlexNet crashing -> add cuda error checking to tests -> test crashing
- compute-sanitizer memecheck

View File

@ -0,0 +1,88 @@
---
title: "Building a Docker Container with Gitea Actions on K3s"
date: "2023-12-28"
tags:
- gitea
- k3s
- cicd
---
Building a Docker image and pushing it to the registry with GitHub Actions is incredibily easy. Since Gitea Actions are designed to be compatible with GitHub Actions, this should be easy, right?
<!--more-->
## Gitea Actions
Gitea Actions is a CI/CD solution tightly coupled with Gitea. They have been available since Gitea 1.19 and are designed to be mostly compatible with GitHub Actions. They are based on the [act](https://github.com/nektos/act), which allows you to run GitHub workflows locally. Gitea has soft forked it to create [act_runner](https://gitea.com/gitea/act_runner).
To use Gitea Actions on you instance, you need to first allow them in `app.ini`. Then create a token and deploy the runner. Once the runner is deployed and registered, you will also need to enable Actions for each repository separately. The Actions runner is a self-contained system - a docker container that, for each job, launches a new container inside which the action steps are run. For a full guide on setting up Actions, check the official [Gitea docs](https://docs.gitea.com/usage/actions/quickstart).
## Building and Pushing Docker Image with GitHub Actions
With GitHub Actions, you can make use of thousands of actions available in [GitHub Marketplace](https://github.com/marketplace?type=actions). If you want to build a Docker image on GitHub, you can just use the official Docker [build-and-push](https://github.com/marketplace/actions/build-and-push-docker-images) action. Just copy one of the examples and you are good to go.
## Building with Gitea
In order to enable Gitea Actions, you nedd to first deploy the Actions runner. I followed the Kubernetes example from [gitea/act_runner](https://gitea.com/gitea/act_runner/src/commit/f17cad1bbe0d4a84308a37fb4a5e64211ada7e8a/examples/kubernetes/rootless-docker.yaml) repository. The deployment is simple. The runner will register itself with your Gitea instance, and after you enable Actions globally and for each repository, you'll be able to try Actions.
The first thing I tried was the same workflow that I used on Github. That didn't work. The first step to fail was docker login action. It complained that it couldn't find the `docker` command. It turns out that the default container image in which the Actions runner runs the commands did not contain docker. I tried manually installing it, but a simpler solution was to just specify a different container by [catthehacker](https://github.com/catthehacker/docker_images), which already has docker preinstalled. After switch to the new container, the logging in worked fine.
The next problem was with setting up the docker buildx action. It couldn't connect to Docker daemon at `unix:///var/run/docker.sock`. After much debugging, trying different things, and searching the internet, I found out that because the docker-in-docker runner container is rootless, the Docker socket is at `unix:///var/run/user/1000/docker.sock` instead. I just needed to change the `DOCKER_HOST` environment variables. I also removed `DOCKER_TLS_VERIFY` and `DOCKER_CERT_PATH` environment variables since they weren't necessary.
Okay, so now, everything should work fine, right? Not so fast. Apparently the Docker buildx action makea some assumtions about the system, which work well in a well-defined environment of GitHub Actions but don't necessarily hold true for self-hosted K3s deployments. It complained that it couldn't mount `sysfs` to `rootfs` at `/sys` due to operation not permitted. The solution was to run docker commands directly instead of using `buildx` action.
The last hurdle was to pass the login secrets to the action. Gitea does not yet support an equivalent to `GITHUB_TOKEN`, so instead, I needed to manually create a token and add it to action secrets as `REGISTRY_TOKEN`.
This is a very condensed summary of many hours spent debugging, searching, and trying to make Gitea Actions build a Docker image on K3s. I've skiped a few different attempts that lead to nowhere, such as using RedHat's Buildah instead of Docker. In the end the actual solution was much simpler than any of my attempts.
## TL;DR
To build a Docker image using Gitea Actions on K3s deploy the dind-rootless Actions runner with these environment variables:
{{< highlight yaml >}}
env:
- name: DOCKER_HOST
value: unix:///var/run/user/1000/docker.sock
- name: GITEA_INSTANCE_URL
value: http://gitea-http.gitea.svc.cluster.local:3000
- name: GITEA_RUNNER_REGISTRATION_TOKEN
valueFrom:
secretKeyRef:
name: runner-secret
key: token
{{< / highlight >}}
Create `release.yaml` file in `.gitea/workflows` folder. For building and pushing the image, use `docker` commands directly. For example:
{{< highlight yaml >}}
name: Build docker container
on:
push:
branches:
- main
jobs:
build:
name: Build image
runs-on: ubuntu-latest
container: ghcr.io/catthehacker/ubuntu:act-latest
env:
IMAGE_NAME: example-image
REGISTRY: example.com
REPO_OWNER: test
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: example.com
username: ${{ gitea.actor }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Build and push
run: |
TODAY=$(date +'%Y-%m-%d')
docker build -t ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:${TODAY} -t ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:latest .
docker push ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:${TODAY}
docker push ${REGISTRY}/${REPO_OWNER}/${IMAGE_NAME}:latest
{{< / highlight >}}

View File

@ -0,0 +1,84 @@
---
title: "Replicating Gitea Docker SSH Passthrough on K3s"
date: "2023-02-12"
tags:
- gitea
- k3s
---
If you are selfhosting Gitea on a single node Kubernetes cluster and want to enable git through SSH while keeping SSH connection to the cluster, this guide is for you.
<!--more-->
**Update**
As of Gitea Helm Chart v9.0.0, Gitea is not a StatefulSet but a Deployment instead. In order to make this work you have to replace pod pod name `gitea-0` with:
{{< highlight bash >}}
$(kubectl get po -n gitea -l app=gitea -o name --no-headers=true)
{{< / highlight >}}
Command substitution does not work in `AuthorizedKeysCommand` so I suggest creating a separate script along the lines of `/usr/local/bin/gitea-shell`
## Background
I am currently in the process of migrating my selfhosted applications from docker-compose to Kubernetes. One of my most used selfhosted app is Gitea. I use it to host my projects, dotfiles and config files where I don't expect any contributions or I simply want to keep it more private. In my docker-compose setup I used SSH Container Passthrough from [Gitea docs](https://docs.gitea.io/en-us/install-with-docker/#SSH-container-passthrough) but when I moved Gitea to k3s I couldn't find any guides on how to achieve the same thing.
I installed Gitea using the official [Helm Chart](https://gitea.com/gitea/helm-chart/). The documentation says this about enabling SSH:
> If you're using ingress and want to use SSH, keep in mind, that ingress is not able to forward SSH Ports. You will need a LoadBalancer like metallb and a setting in your SSH service annotations.
However using this method will route all incoming SSH connections to the Gitea container, essentialy disabling SSH connection to the host. Therefore we need a way to pass SSH connections to user `git` to our Gite container running on Kubernetes and at the same time allow SSH connections to host for some other user(s)
## Kubernetes Setup
Create user git on your host and deploy Gitea to Kubernetes (e.g. using Helm). You don't need to expose port 22 using a service.
First we are going to create a new login shell for user git. Create file `/usr/local/bin/gitea-shell` with content:
{{< highlight bash >}}
#!/bin/sh
/usr/local/bin/kubectl exec -i -n gitea gitea-0 -c gitea -- env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" /bin/sh "$@"
{{< / highlight >}}
Your namespace might be different.
Then run as root (or sudo):
{{< highlight bash >}}
chmod +x /usr/local/bin/gitea-shell
usermod -s /usr/local/bin/gitea-shell git
{{< / highlight >}}
Now everytime the user git logs in (i.e. using git via SSH) `/usr/local/bin/gitea-shell` gets executed which means our original SSH command will be executed in the gitea container.
Finally we need to make sure that the SSH keys we add through Gitea interface allow us to 'login' as git user.
Edit `/etc/SSH/SSHd_config` and add the following:
{{< highlight yaml>}}
Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/local/bin/kubectl exec -i -n gitea gitea-0 -c gitea -- /usr/local/bin/gitea keys -e git -u %u -t %t -k %k
{{< / highlight >}}
If you are using `AllowUsers` directive don't forget to add user git
## Testing
Open Gitea in web browser and add you SSH key. Then try to SSH into the Gitea container.
{{< highlight bash >}}
ssh git@<your gitea url>
{{< / highlight >}}
You should get a message like this:
> PTY allocation request failed on channel 0
> Hi there, test! You've successfully authenticated with the key named <your ssh key>, but Gitea does not provide shell access.
> If this is unexpected, please log in with password and setup Gitea under another user.
> Connection to <your gitea url> closed.
Now you can create a repo and you should be able to clone and push via SSH.

View File

@ -0,0 +1,64 @@
---
title: "Building My Resume with GitHub Actions"
date: "2023-10-02"
tags:
- cicd
---
Even if you are not actively looking for a new job, it is a good idea to have an up to date resume. I'm using Overleaf's GitHub integration and GitHub Actions to build PDF from my LaTeX resume and release it on GitHub
<!--more-->
## LaTeX
LaTeX is a typesetting system and document preparation tool known for its professional-quality typography and precise formatting capabilities. Widely used in academia, it's popular for creating resumes and academic documents due to its superior handling of complex formatting, mathematical equations, and citations. One of the benefits of using LaTeX is that it separates the content and formatting of a document, which makes it easier to focus on the content without worrying about the layout.
TeXLive is a comprehensive distribution of the LaTeX typesetting system, providing a wide range of packages, fonts, and utilities for users. It includes everything needed to create LaTeX documents, making it a go-to choice for many LaTeX users.
## Compiling PDF on Overleaf
I have been using [Overleaf](https://www.overleaf.com/) to edit, update and build my resume. Overleaf is a cloud-based LaTeX editor with countless templates for resumes, theses, presentations, cover letters, scientific papers and more. Overleaf uses TeXLive distribution, enabling their compile servers to provide a real-time preview of the typeset PDFs. This makes editing LaTeX on Overleaf very convenient since it is not necessary to understand the intricacies of document processing. Overleaf handles the complexities of LaTeX compilation, allowing you to concentrate on creating a standout resume. However, replicating the same results outside of Overleaf's environment requires deeper knowledge of the compilation process.
Overleaf uses [latexmk](https://ctan.org/pkg/latexmk?lang=en) package to automate the compilation. The package uses a system-wide configuration, which can be customized by a user-level configuration on a document-by-document basis. This customization might include adjusting the sequence of commands, specifying which files to include or exclude, defining custom dependencies, or setting up personalized error-handling procedures. You can access the `latexmk` configuration file used by Overleaf to typeset your document by compiling [this project](https://www.overleaf.com/learn/how-to/How_does_Overleaf_compile_my_project%3F#How_to_access_a_copy_of_Overleaf%E2%80%99s_LatexMk_file).
Because the template of my resume is quite simple it was not necessary to get the exact `latexmk` config file or to customize it in any way.
## Compiling and Releasing with GitHub Actions
Leveraging the power of GitHub Actions has streamlined my document compilation and release process significantly. Within the GitHub Actions Marketplace, there's a wealth of workflows tailored for various tasks, including LaTeX compilation. I've opted for [xu-cheng/latex-action](https://github.com/xu-cheng/latex-action) which utilizes the TeXLive environment and `latexmk` compiler, mirroring the setup used on Overleaf. And indeed without any configuration changes, my resume compiled to PDF correctly.
But automation doesn't stop there. To simplify the release procedure, I've incorporated [softprops/action-gh-release](https://github.com/softprops/action-gh-release). This action automates the creation of new tags, and releases, and even handles file attachments seamlessly. I've configured it to generate new releases marked with the current date, effortlessly adding the compiled `resume.pdf`. This automated process not only saves valuable time but also streamlines the release workflow, eliminating the need for manual login to Overleaf, recompilation, and downloading. It ensures that each new version of my resume is promptly available to the public.
You can check the full repository [here](https://github.com/LordMathis/resume). Alternatively here's just the workflow file:
```yaml
name: Release Compiled PDF
on:
push:
branches:
- master
jobs:
build_latex:
runs-on: ubuntu-latest
steps:
- name: Get current date
id: date
run: echo "NOW=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Set up Git repository
uses: actions/checkout@v3
- name: Compile
uses: xu-cheng/latex-action@v2
with:
root_file: resume.tex
- name: Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.NOW }}
files: ./resume.pdf
```

View File

@ -1,12 +0,0 @@
FROM node:16-alpine as front
WORKDIR /app
COPY ./ /app/
RUN yarn install
RUN yarn run build
FROM nginx:1.17.8-alpine
RUN rm -rf /usr/share/nginx/html
COPY --from=front /app/public/ /usr/share/nginx/html
COPY ./docker/default.conf /etc/nginx/conf.d/default.conf

View File

@ -1,21 +0,0 @@
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
autoindex off;
charset urtf-8;
error_page 404 /404.html;
access_log /var/log/nginx/access.log;
location ~* \.(html)$ {
add_header Cache-Control "no-store";
expires off;
}
rewrite ^([^.\?]*[^/])$ $1/ permanent;
try_files $uri $uri/ $uri/index.html =404;
}

View File

@ -1,7 +0,0 @@
/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/browser-apis/
*/
// You can delete this file if you're not using it

View File

@ -1,72 +0,0 @@
module.exports = {
siteMetadata: {
author: `Matúš Námešný`,
user: "hello",
hostname: "namesny.com",
email: "matus@namesny.com",
social: [
{
name: "github",
link: "https://github.com/LordMathis",
},
{
name: "linkedin",
link: "https://www.linkedin.com/in/mat%C3%BA%C5%A1-n%C3%A1me%C5%A1n%C3%BD-3903b6128/",
}
],
},
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `pages`,
path: `${__dirname}/content/pages`,
},
},
{
resolve: `gatsby-transformer-remark`,
options: {
filter: node => node.sourceInstanceName === `pages`,
type: `MarkdownPage`
}
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `posts`,
path: `${__dirname}/content/posts/`,
},
},
{
resolve: `gatsby-transformer-remark`,
options: {
filter: node => node.sourceInstanceName === `posts`,
excerpt_separator: `<!-- end -->`,
type: `BlogPost`
}
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/favicon-32x32.png`, // This path is relative to the root of the site.
},
},
`gatsby-plugin-sass`,
],
}

View File

@ -1,93 +0,0 @@
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
const parent = getNode(node.parent)
createNodeField({
node,
name: `slug`,
value: slug,
})
createNodeField({
node,
name: 'collection',
value: parent.sourceInstanceName,
})
}
}
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
// Posts query
const posts = await graphql(
`
{
allMarkdownRemark(filter:{frontmatter: {draft: {ne: true}}, fields: {collection: {eq: "posts"}}}) {
edges {
node {
fields {
slug
}
}
}
}
}
`
)
// Handle errors
if (posts.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
// Create pages for each markdown file.
const blogPostTemplate = path.resolve(`src/templates/blog-post.js`)
posts.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: `/posts${node.fields.slug}`,
component: blogPostTemplate,
context: {
slug: node.fields.slug,
},
})
})
const pages = await graphql(
`
{
allMarkdownRemark(filter: {fields: {collection: {eq: "pages"}}}) {
edges {
node {
fields {
slug
}
}
}
}
}
`
)
// Handle errors
if (pages.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
// Create pages for each markdown file.
const pageTemplate = path.resolve(`src/templates/page.js`)
pages.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: pageTemplate,
context: {
slug: node.fields.slug,
},
})
})
}

View File

@ -1,7 +0,0 @@
/**
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/ssr-apis/
*/
// You can delete this file if you're not using it

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module git.namesny.com/Mathis/namesny.com
go 1.20
require github.com/LordMathis/hugo-theme-nightfall v0.7.0 // indirect

10
go.sum Normal file
View File

@ -0,0 +1,10 @@
github.com/LordMathis/hugo-theme-nightfall v0.0.0-20230212210243-f116fbf0bdbb h1:31cDOpojmeNh9kpnwdPSe+Umzc1UaMc9vFM5N/7e5Yc=
github.com/LordMathis/hugo-theme-nightfall v0.0.0-20230212210243-f116fbf0bdbb/go.mod h1:0tCPxAeg5+tWhv17517Q8Lti/TPh0KNyON/uferEU30=
github.com/LordMathis/hugo-theme-nightfall v0.5.1 h1:xeycc74MTnikZ7tv+V8Lhuu9zrqRpVkaNjqw9eQYVNc=
github.com/LordMathis/hugo-theme-nightfall v0.5.1/go.mod h1:0tCPxAeg5+tWhv17517Q8Lti/TPh0KNyON/uferEU30=
github.com/LordMathis/hugo-theme-nightfall v0.6.0 h1:AmJFH2tQ66ZboBJ44RVwtt37Nhi6Qv29k6I/ouPxxRc=
github.com/LordMathis/hugo-theme-nightfall v0.6.0/go.mod h1:0tCPxAeg5+tWhv17517Q8Lti/TPh0KNyON/uferEU30=
github.com/LordMathis/hugo-theme-nightfall v0.6.1 h1:O9MXJpRv8A6Gxn2xUQHZJ2PVq4ryORlht6d4miUXrvI=
github.com/LordMathis/hugo-theme-nightfall v0.6.1/go.mod h1:0tCPxAeg5+tWhv17517Q8Lti/TPh0KNyON/uferEU30=
github.com/LordMathis/hugo-theme-nightfall v0.7.0 h1:aKN7W6wx1l2alvesLwA4rsoi7w/9wR0A+pKBWysiDCI=
github.com/LordMathis/hugo-theme-nightfall v0.7.0/go.mod h1:0tCPxAeg5+tWhv17517Q8Lti/TPh0KNyON/uferEU30=

17
nginx.conf Normal file
View File

@ -0,0 +1,17 @@
server {
listen 80;
listen [::]:80;
server_name localhost;
access_log /var/log/nginx/access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@ -1,51 +0,0 @@
{
"name": "namesny.com",
"private": true,
"description": "Personal website",
"version": "2.0.0",
"author": "Matus Namesny <matus@namesny.com>",
"dependencies": {
"@fontsource/fira-mono": "^4.5.0",
"@fontsource/open-sans": "^4.5.2",
"gatsby": "^4.5.4",
"gatsby-image": "^3.11.0",
"gatsby-plugin-manifest": "^4.5.2",
"gatsby-plugin-offline": "^5.5.2",
"gatsby-plugin-react-helmet": "^5.5.0",
"gatsby-plugin-sass": "^5.5.0",
"gatsby-plugin-sharp": "^4.5.2",
"gatsby-source-filesystem": "^4.5.2",
"gatsby-transformer-remark": "^5.25.1",
"gatsby-transformer-sharp": "^4.5.0",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet": "^6.1.0",
"sass": "^1.49.0"
},
"devDependencies": {
"prettier": "^2.5.1"
},
"keywords": [
"gatsby",
"blog",
"portfolio"
],
"license": "0BSD",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}

View File

@ -1,21 +0,0 @@
import React from "react"
import PostLink from "./post-link"
import {header} from "../styles/blog.module.scss"
const Blog = ({ edges }) => {
const Posts = edges
.map(edge => <PostLink key={edge.node.id} post={edge.node} />)
return (
<div>
<div className={header}>
<h1>Blog</h1>
</div>
<div>
{Posts}
</div>
</div>
)
}
export default Blog

View File

@ -1,12 +0,0 @@
import React from "react"
import { footer, link } from '../styles/footer.module.scss'
const Footer = ({authorName}) => (
<footer className={footer}>
© {new Date().getFullYear()} {authorName}, Built with
{` `}
<a href="https://www.gatsbyjs.org" className={link}>Gatsby</a>
</footer>
)
export default Footer

View File

@ -1,35 +0,0 @@
import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"
import { header, headerWrapper, terminal, links } from "../styles/header.module.scss"
const Header = ({ user, hostname }) => (
<header className={headerWrapper}>
<div className={header}>
<div>
<Link to="/" className={terminal}>{user}@{hostname} ~ $</Link>
</div>
<nav className={links}>
<ul>
<li key="about">
<a href='/about'>
<span>~/about</span>
</a>
</li>
<li key="blog">
<a href='/blog'>
<span>~/blog</span>
</a>
</li>
</ul>
</nav>
</div>
</header>
)
Header.propTypes = {
user: PropTypes.string.isRequired,
hostname: PropTypes.string.isRequired,
}
export default Header

View File

@ -1,32 +0,0 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
/*
* This component is built using `gatsby-image` to automatically serve optimized
* images with lazy loading and reduced file sizes. The image is loaded using a
* `useStaticQuery`, which allows us to load the image from directly within this
* component, rather than having to pass the image data down from pages.
*
* For more information, see the docs:
* - `gatsby-image`: https://gatsby.dev/gatsby-image
* - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
*/
const Image = () => {
const data = useStaticQuery(graphql`
query {
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
`)
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
}
export default Image

View File

@ -1,19 +0,0 @@
import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"
import { indexWrapper, header } from "../styles/index.module.scss"
import Social from "./social"
const Index = ({ author, social, email }) => (
<div className={indexWrapper}>
<div>
<h1 className={header}>{ author }</h1>
</div>
<Social social={social} email={email}/>
</div>
)
Index.propTypes = {
}
export default Index

View File

@ -1,49 +0,0 @@
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import Footer from "./footer"
import { Helmet } from "react-helmet"
import '../styles/global.scss';
import { main, content, vertical, flexWrapper } from "../styles/layout.module.scss"
const Layout = ({ children, title, verticalLayout}) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
author
user
hostname
}
}
}`)
const classes = verticalLayout ? `${content} ${vertical}` : content
return (
<div className={flexWrapper}>
<Helmet
titleTemplate={`%s | ${data.site.siteMetadata.author}`}>
<html lang="en" amp />
<title>{title}</title>
</Helmet>
<Header
user={data.site.siteMetadata.user}
hostname={data.site.siteMetadata.hostname} />
<div className={classes}>
<main className={main}>{children}</main>
</div>
<Footer authorName={data.site.siteMetadata.author}/>
</div>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
vertical: PropTypes.bool
}
export default Layout

View File

@ -1,28 +0,0 @@
import React from "react"
import { Link } from "gatsby"
import { postTitle, postDate, postHeader, postListItem, postExcerpt } from '../styles/post-link.module.scss'
const PostLink = ({ post }) => {
const date = new Date(post.frontmatter.date)
const options = { year: 'numeric', month: 'long', day: 'numeric' };
const postDateString = date.toLocaleDateString('en', options);
const postUrl = "/posts" + post.fields.slug
return (
<Link to={postUrl}>
<div className={postListItem} role="listitem">
<div className={postHeader} >
<span className={postTitle}>{post.frontmatter.title}</span>
<span className={postDate}>{postDateString}</span>
</div>
<div className={postExcerpt}>
<p>{post.excerpt}</p>
</div>
</div>
</Link>
)
}
export default PostLink

View File

@ -1,43 +0,0 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { socialNavbar } from '../styles/social.module.scss'
export default class Social extends Component {
static propTypes = {
social: PropTypes.arrayOf(PropTypes.object),
email: PropTypes.string
}
render () {
let key = 0
const socialLinks = this.props.social.map((val) => {
const link = (
<li key={key}>
<a href={val.link} role="link">
{val.name}
</a>
</li>
)
key += 1
return link
})
socialLinks.push(
<li key={key}>
<a href={`mailto:${this.props.email}`} role="link">
e-mail
</a>
</li>
)
return (
<div className={socialNavbar} role="list">
<ul>
{socialLinks}
</ul>
</div>
)
}
}

View File

@ -1,10 +0,0 @@
import React from "react"
const NotFoundPage = () => (
<Layout title="404: Not found" >
<h1>NOT FOUND</h1>
<p>You just hit a route that doesn&#39;t exist... the sadness.</p>
</Layout>
)
export default NotFoundPage

View File

@ -1,39 +0,0 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Layout from "../components/layout"
import Blog from "../components/blog"
const IndexPage = () => {
const data = useStaticQuery(graphql`
query {
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
filter: {frontmatter: {draft: {ne: true}}, fields: {collection: {eq: "posts"}}}
) {
edges {
node {
id
excerpt
frontmatter {
date
title
}
fields {
slug
}
}
}
}
}
`)
return (
<Layout title="Blog">
<Blog edges={data.allMarkdownRemark.edges}/>
</Layout>
)
}
export default IndexPage

View File

@ -1,31 +0,0 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Layout from "../components/layout"
import Index from "../components"
const IndexPage = () => {
const data = useStaticQuery(graphql`
query SiteDataQuery {
site {
siteMetadata {
author
email
social {
name
link
}
}
}
}
`)
return (
<Layout title="Home" vertical={true} >
<Index author={data.site.siteMetadata.author} social={data.site.siteMetadata.social} email={data.site.siteMetadata.email}/>
</Layout>
)
}
export default IndexPage

View File

@ -1,5 +0,0 @@
@import "./variables.scss";
.blogPostWrapper {
text-align: left;
}

View File

@ -1,5 +0,0 @@
@import "./variables.scss";
.header {
text-align: left;
}

View File

@ -1,11 +0,0 @@
@import "./variables.scss";
.footer {
padding: 15px;
text-align: center;
background-color: $backgroundDarker;
}
.link {
color: $white;
}

View File

@ -1,25 +0,0 @@
@import "./variables.scss";
body, html {
height: 100%;
}
body {
font-family: $fontParagraph;
color: $white;
background-color: $backgroundDark;
margin: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
@for $i from 1 through 6 {
h#{$i} {
font-family: $fontHeader;
}
}
@-ms-viewport{
width: device-width;
}

View File

@ -1,42 +0,0 @@
@import "./variables.scss";
.header {
font-family: $fontHeader;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
@media only screen and (min-width: $breakLarge) {
width: $width;
}
}
.headerWrapper {
overflow: auto;
box-sizing: border-box;
background-color: $backgroundDarker;
display: flex;
justify-content: center;
}
.links {
ul {
list-style: none;
padding: 0;
margin: 0;
li {
display: inline;
margin: 5px;
a {
color: $white;
text-decoration: none;
}
}
}
}
.terminal {
color: $white;
text-decoration: none;
}

View File

@ -1,9 +0,0 @@
.indexWrapper {
display: flex;
flex-direction: column;
justify-content: center;
}
.header {
font-size: 3em;
}

View File

@ -1,31 +0,0 @@
@import "./variables.scss";
.content {
text-align: center;
margin: 0 auto;
flex: 1 auto;
padding: 20px;
@media only screen and (min-width: $breakLarge) {
display: flex;
width: $width;
}
}
.vertical {
display: flex;
flex-direction: column;
justify-content: center;
}
.flexWrapper {
display: flex;
flex-direction: column;
justify-content: center;
min-height: 100vh;
}
.main {
width: 100%;
height: 100%;
}

View File

@ -1,5 +0,0 @@
@import "./variables.scss";
.pageWrapper {
text-align: left;
}

View File

@ -1,52 +0,0 @@
@import "./variables.scss";
.postDate {
float: right;
color: $white;
}
.postTitle {
color: $blue;
text-decoration: none;
text-transform: capitalize;
font-family: $fontHeader;
font-size: 1.2em;
float: left;
}
.postHeader {
overflow: hidden;
}
.postsList {
margin-top: 20px;
}
.postListItem {
padding: 20px;
background-color: $black;
margin-bottom: 20px;
}
.postExcerpt {
text-align: initial;
text-decoration: none;
color: $white;
}
.headerContainer {
display: flex;
justify-content: space-between;
}
.noDecoration {
text-decoration: none;
}
a,
a:link,
a:visited,
a:hover,
a:active{
text-decoration: none;
}

View File

@ -1,19 +0,0 @@
@import "./variables.scss";
.socialNavbar {
ul {
list-style: none;
padding: 0;
li {
display: inline;
}
}
a {
color: $white;
text-shadow: $black 0px 0px 2px;
-webkit-font-smoothing: antialiased;
display: inline-block;
margin: 10px;
}
}

View File

@ -1,18 +0,0 @@
// Colors
$darkGrey: #323232;
$white: #f8f8ff;
$black: #2f2f2f;
$blue: #0f52bf;
$backgroundDarker: #252627;
$backgroundDark: #292a2d;
//Fonts
@import "~@fontsource/fira-mono/500.css";
@import "~@fontsource/open-sans/index.css"; // Weight 400.
$fontHeader: 'Fira Mono', monospace;
$fontParagraph: 'Open Sans', sans-serif;
// Content
$breakLarge: 992px;
$width: 760px;

View File

@ -1,27 +0,0 @@
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import { blogPostWrapper } from "../styles/blog-post.module.scss"
export default function BlogPost({ data }) {
const post = data.markdownRemark
return (
<Layout>
<div className={blogPostWrapper}>
<h1>{post.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
}
}
}
`

View File

@ -1,27 +0,0 @@
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import {pageWrapper} from "../styles/page.module.scss"
export default function Page({ data }) {
const page = data.markdownRemark
return (
<Layout>
<div className={pageWrapper}>
<h1>{page.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: page.html }} />
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
}
}
}
`

View File

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 433 B

View File

Before

Width:  |  Height:  |  Size: 887 B

After

Width:  |  Height:  |  Size: 887 B

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

11609
yarn.lock

File diff suppressed because it is too large Load Diff