Skip to main content


GitHub Signatures in Gitea


A small lifehack for the Gitea owners. As you may know, GitHub signs commits done with its web interface with its GPG key. These commits may end up on your Gitea server. It looks rather unconvincing:
Image/PhotoCommit listImage/PhotoCommit page
Luckily it is fixable by a simple lifehack:
  • Register user ‘github’
  • Login with it and optionally set up a profile
  • Add the web flow GPG key: https://github.com/web-flow.gpg
  • Add noreply@github.com to the account emails
  • Mind the security and disable sign-in for this account
The signatures will look much better:
Image/PhotoCommit listImage/PhotoCommit page
https://sandfox.me/misc/gitea-github.html


RPM5 lost all distros


With OpenMandriva Lx 4 now in beta it seems that RPM5 lost all its main users.CAOS, Ark and Unity are discontinued, Wind River and OpenMandriva switched to RPMv4

Interestingly, it’s also the end of urpmi with both Mageia and OpenMandriva switching to dnf.

It seems rpm world entered a semi-unified state with dnf and zypper, both libsolv based and partly interoperable
https://sandfox.me/linux/rpm5.html


Dark Theme for the Blog


Just finalized the dark theme for the blog. The idea is simple, use prefers-color-scheme media query and wrap dark style elements with it:

@media (prefers-color-scheme: dark) {
a {
color: #4be
}
}

The browser then will respect the OS dark mode or have its own night mode and show your website in dark:

Image/PhotoLight mode Image/PhotoDark mode
That’s simple and cool!

One of the problems currently is testing. It is possible but rarely comfortable. None of the browsers has mode setting in their dev tools.
  • Firefox only reads theme status from the operating system. There are some switcher extensions but they don’t work properly.
  • Chrome can be run with --force-dark-mode CLI param.
  • Opera here is the best. Choosing light/dark themes in browser will also change the prefers-color-scheme rendering in the fly.

https://sandfox.me/misc/dark-theme.html
#4be


On Common Misuse of the File Formats


A small rant about text file format holy wars. I believe that most of the file formats that participate in these holy wars are rather good and the most of the frustration comes from their misuse.
  • XML is a DOCUMENT language
  • JSON is a SERIALIZATION language
  • TOML and YAML are CONFIGURATION languages. TOML vs YAML holy war is out of scope of this post
XML is an awesome format for extensible documents. Like, you cannot do (X)HTML or SVG with JSON, also it’s namespacing features allow you to embed one type of document into another. However it’s a terrible serialization format, that’s why XMPP seems so weird and uses partially invalid XML. Just think of <stream:stream> in the beginning that’s never closed. Terrible. It also has no place in RPC-like protocols.SOAP for example is another terrible application for XML.

JSON is an awesome human-inspectable serialization language. It’s good for network intercommunication and maybe for data exporting. It’s strict and standartized and readable at least in its “pretty” form. However, it’s a terrible configuration language due to its extremely strict syntax and lack of comments.composer.json and package.json are terrible applications for JSON, but, interestingly, composer.lock and package-lock.json are not.Pipenv can be an example of the correct usage. It uses TOML for the config and JSON for the lock file.

I want to return to the comparison of TOML and YAML in another post, so let’s go directly to the bad parts. Just try to serialize a random dictionary with TOML and look at the result. It will be a mess. Also many new features introduced in TOML 0.5, like dotted keys, make sense only when the config is written by a human.TOML is not too popular yet to have any known bad applications so let’s get to YAML.YAML is extremely insecure to be used as a data exchange format for untrusted data. It also wastes a lot of space for indentation spaces. Ironically, Rails collected both misuses for YAML by using it both as a parsable language for the POST body (in past) and a default serialization language for complex fields in the database. Also, YAML’s short json-like syntax is also made solely for a human decision making.

Of course all these applications are not isolated and often there are options depending on the point of view, like RSS/Atom and JSON Feed both making sense depending on whether you see it as an alternative representation of a website as a document or a stream in a serialized form or some sort of REST response.

Well, there are no solutions, only trade-offs. Choose your languages wisely.
https://sandfox.me/misc/file-formats-misuse.html


Fix AsciiDoc Display in Gitea


After installing my own Gitea I looked for the support for the markups I use.Gitea has support for external markup renderers and the official doc lists configs for both reStructuredText and AsciiDoc:

[markup.asciidoc]
ENABLED = true
FILE_EXTENSIONS = .adoc,.asciidoc
RENDER_COMMAND = "asciidoctor --out-file=- -"
; Input is not a standard input but a file
IS_INPUT_FILE = false

[markup.restructuredtext]
ENABLED = true
FILE_EXTENSIONS = .rst
RENDER_COMMAND = rst2html.py
IS_INPUT_FILE = false

RST works perfectly but AsciiDoc has two visible problems:
Image/PhotoGlitch on the topImage/PhotoUseless timestamp on the bottom
Unfortunately it seems that the Asciidoctor CLI cannot produce html code that will be correctly rendered by Gitea so we need to use the Ruby interface.

require 'asciidoctor'

# Load the document in the embeddable mode
document = Asciidoctor.load STDIN.read

# Embeddable doesn't display the main header so render it manually
puts "<h1>#{document.doctitle}&lt;/h1>"

# Render HTML
puts document.convert

Now replace the asciidoctor call with our new script:

[markup.asciidoc]
ENABLED = true
FILE_EXTENSIONS = .adoc,.asciidoc
RENDER_COMMAND = "ruby /path/to/gitea-asciidoc.rb"
; Input is not a standard input but a file
IS_INPUT_FILE = false

and enjoy a non glitchy AsciiDoc render.
https://sandfox.me/ruby/gitea-asciidoc.html


PHP 7.4: Splat Inconsistency


PHP 7.4 has this great new feature: splat operator now works in array expressions.

<?php
var_export([1,2,3, ...[4,5,6]]); // [1,2,3,4,5,6]

including when it is in the middle

<?php
var_export([1,2,3, ...[4,5,6], 7,8,9]); // [1,2,3,4,5,6,7,8,9]

Let’s have some variadic function

<?php

function sum(...$values)
{
return array_sum($values);
}

but

<?php
// PHP 5.6 - 7.4
echo sum(1,2,3, ...[4,5,6], 7,8,9); // PHP Fatal error: Cannot use positional argument after argument unpacking

of course there is a well-known workaround

<?php
echo sum(1,2,3, ...[4,5,6], ...[7,8,9]); // 45

and now also this

<?php
// PHP 7.4+
echo sum(...[1,2,3, ...[4,5,6], 7,8,9]); // 45

but why wasn’t the original behavior fixed as well?
https://sandfox.me/php/splat-inconsistency.html



Composer Yaml


My new library to allow composer to read config from YAML file. There is some demand in comments for composer config but the developers are not interestedand most 3rd party attempts to solve it are limited to yaml2json converters.

I tried a slightly different approach. There is a command in the composer itself that changes the way the config is read: composer global. During its execution it changes current working directory, resets composer state, and forces the composer to read config from another directory.

What I tried to do: I put yaml2json converter in place of global‘s directory changing code, and it seems it worked. Of course, some things got broken like any command that tries to change composer.json will no longer have any effect, however many people don’t use them and it may be an acceptable tradeoff for using yml-based config.

You can find the project on my new dev website: https://sandfox.dev/php/composer-yaml.html
https://sandfox.me/php/composer-yaml.html


Bitbucket to Remove Mercurial Support


So Mercurial lost its biggest hosting platform. Sad to see it because I always thought that it has much more usable CLIand much better branching system for corporate development than git.
After much consideration, we’ve decided to remove Mercurial support from Bitbucket Cloud and its API. Mercurial features and repositories will be officially removed from Bitbucket and its API on June 1, 2020.
https://bitbucket.org/blog/sunsetting-mercurial-support-in-bitbucket
https://sandfox.me/misc/bitbucket-mercurial.html


PHP access private methods and fields


These two simple functions can come in handy as helpers for something like PsySH.PHP >= 7.0 is required.

Note

Don’t use them in actual production code! That would be awful

Call private method of an object:

<?php
function call_private_method($object, string $method, ...$args)
{
return (function ($method, ...$args) {
return call_user_func_array([$this, $method], $args);
})->call($object, $method, ...$args);
}

Get private field of an object:

<?php
function get_private_field($object, string $field)
{
return (function ($field) {
return $this->$field;
})->call($object, $field);
}

Example:

<?php
class A
{
private $secret = 'SECRET234';

private function doStuff($whatever)
{
return $whatever . '!';
}
}

$a = new A;

get_private_field($a, 'secret'); // SECRET234

call_private_method($a, 'doStuff', 'whatever'); // whatever!

UPD: “Why not make a library out of it”, I thought. So it’s now a library: github.com
https://sandfox.me/2016/11/16/php-private-access.html


Embracing CommonMark as the One True Markdown


As you may know, CommonMark is a project aiming to create unified and unambiguous Markdown syntax specification. So, I’m in. I want to spread the word and even use it in my own blog.

The trouble number one is that Jekyll uses kramdown by default. So we find a gem and the gem is jekyll-commonmark. Oh hell, we lost syntax highlighting 🙁

The trouble number two is that CommonMark standard lacks support for server side syntax highlighting. That’s bad, I don’t want any JavaScript on my static pages. Let’s try to wrap it somehow and enable syntax highligting.

The strong side of Ruby CommonMark implementation, CommonMarker is its ability to parse a document to the abstract syntax tree, so let’s use it to extract our blocks and highlight them with Rouge for example.

# get our abstract syntax tree
ast = CommonMarker.render_doc('some markdown here')

# search code blocks
ast.walk do |node|
if node.type == :code_block
next if node.fence_info == '' # skip if we don't know how to highlight

source = node.string_content # get node content that's our source code

# now try to use highlighter
# I prefer Rouge which is also a default choice in Jekyll

# `node.fence_info` will hold the language we want to highlight
# for example,
# ```ruby
# # code here
# ```
# will have node.fence_info == 'ruby'
lexer = Rouge::Lexer.find_fancy(node.fence_info)
formatter = Rouge::Formatters::HTML.new # get most common formatter

# format our html
html = '<div class="highlighter-rouge">' +
formatter.format(lexer.lex(source)) +
'</div>'

# and render it
new_node = CommonMarker::Node.new(:html)
new_node.string_content = html

# insert our new parsed content and remove original code block
node.insert_before(new_node)
node.delete
end
end

# done! we have a document with highlighted source blocks
puts ast.to_html

To avoid this headache in the future I released this scenario as a gem:commonmarker-rouge. And now by just forking jekyll-commonmark and changing CommonMarker to CommonMarker::Rouge I have a blog parsed as CommonMark with syntax highlighting intact.
https://sandfox.me/2016/04/06/embracing-commonmark.html


What Is Dead May Never Die


Let’s have some fun with theDrowned God andUnix signals.

This is a simple program that catches SIGINT and SIGTERM

#include <stdio.h> // for printf() && perror()
#include <stdlib.h> // for exit()
#include <signal.h> // for all the signal fun
#include <unistd.h> // for sleep()

/**
* catch signals
*/
void catch(int sig)
{
static int counter = 0;

// prevent exit by SIGINT and SIGTERM 3 times and then exit program
if (sig == SIGINT || sig == SIGTERM) {
if (counter < 3) {
printf("What is dead may never die\n");
counter += 1;
} else {
printf("Okay... 🙁\n");
exit(0);
}
}
}

int main(int ac, char ** av)
{
// set catcher for the interrupt signal
if (signal(SIGINT, catch) == SIG_ERR) {
perror("Can't catch SIGINT\n");
}

// set catcher for the kill signal
if (signal(SIGTERM, catch) == SIG_ERR) {
perror("Can't catch SIGTERM\n");
}

printf("We do not sow\n");

// keep running in background, we exit by other means
while(1) {
sleep(1);
}
}

Compile it and run, then try to kill all Greyjoy 😀

[sandfox@paloalto fun]$ clang -o greyjoy greyjoy.c
[sandfox@paloalto fun]$ ./greyjoy &
[1] 31366
We do not sow
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
What is dead may never die
[sandfox@paloalto fun]$ killall greyjoy
Okay... 🙁
[1]+ Done ./greyjoy
[sandfox@paloalto fun]$

It seems they are somehow protected 😀

A good example of signals handling can be found here:www.thegeekstuff.com
https://sandfox.me/2016/03/21/greyjoy.html
This entry was edited (5 years ago)



Farewell to Jekyll
Just ported the blog to Pelican and removed add Jekyll files. Currently it seems the most logical choice for me

First, I started to use reST much more extensively than Markdown and I want a blog generator that supports it better

Second is my new interest in Python

Third, Pelican seems to have much more features that I like compared to Jekyll and other static generators that I tested, especially Python ones (however Nikola also seems a good alternative but I had to stop at something)
https://sandfox.me/2019/01/18/farewell-to-jekyll.html



journald-native and journald-logger transferred to the Foreman
Yesterday I moved two of my ruby gems, journald-native and journald-logger, to theforemanGitHub namepace. Developing them further is out of my current professional interest and hopefullythe Foreman project will be a good home for them.

It’s hard to say farewell however to the most popular library I created so far 😁 (8 GitHub stars, 57000 downloads)
https://sandfox.me/2018/10/10/farewell-journald.html



Private Composer Repo with Gitlab and Satis
You can easily create your own composer repository using Satis and Gitlab. I will use global https://gitlab.com/feed.xml but it should be most useful for private corporate Gitlab installations. You will need CI and Pages

Our repo should contain only 2 files: satis.json and .gitlab-ci.yml

satis.json


satis.json should describe the repo you want. It is very close by structure to composer.json. Refer to Satis documentation for advanced use cases, I will go with the simplest one: add some packages from Github and require all of them

{
"name": "My Satis Repo",
"homepage": "https://sandfox.gitlab.io/satis/",
"repositories": [{
"type": "vcs",
"url": "https://github.com/sandfoxme/bencode"
}, {
"type": "vcs",
"url": "https://github.com/sandfoxme/composer-viz"
}],
"require-all": true
}

.gitlab-ci.yml


Now the tricky part that took me quite some time to debug, but you probably can just copy-paste my solution. You need to set a private variable AUTH_JSON which should contain the content of your auth.json like Github Oauth Token or access data for your private Gitlab instance. (Set it to {} if you need none of it)

Note

Jan 19, 2019: code has been updated to create auth.json in base path not in composer path

# The only image where dind works on GitLab.com
image: gitlab/dind

# So we can use Docker inside build script
services:
- docker:dind

# Task for GitHub Pages
pages:
stage: deploy
# cache composer data (especially useful if you set up Satis to download packages)
cache:
paths:
- composer
script:
- if [ ! -d composer ]; then mkdir composer; fi
# create auth.json from variable
- echo "$AUTH_JSON" > auth.json
# run satis from docker image
- docker run --rm -i -v `pwd`:/build -v `pwd`/composer:/composer composer/satis
# gitlab requires directory to be named public for whatever reason
- mv output public
# artifacts for Pages
artifacts:
paths:
- public
# do this only on master branch
only:
- master

Result


You can find my example repo project at https://gitlab.com/sandfox/satis/ and generated Satis repo athttps://sandfox.gitlab.io/satis/
https://sandfox.me/2018/03/09/satis-gitlab.html



PhpStorm Advanced Metadata Exporter
As a Silex user I liked Pimple Container Dumper that worked with Silex Idea Plugin to enable code completion for Pimple DI in PhpStorm. But now with Silex EOL’d I have to move to Slim.

I’ve found no such projects so I had to write my own. Here it is: sandfoxme/phpstorm-metadata-export. It currently supports exporting data from Pimple and has 3 integration middlewares: for Slim, for Silex and for Psr-15 compatible frameworks.

P.S. Code completion support for ArrayAccess containers seem to be currently broken in PhpStorm (WI-33309, WI-35503). So I don’t currently recommend replacing Silex Idea Plugin with this library unless you use Pimple in Psr-11 compliant way (like Slim does by default)
https://sandfox.me/2018/03/06/phpstorm-metadata.html