Lewati navigasi


To reduce the number of blogs that I have to maintain, I’m deciding to move back all technical stuffs to my min blog petrabarus.net.


Just share a bit. When we want to commit source code, it’s better to check locally before pushing the source code to repository which then check them at the build server.

Here’s a source code for the wrapper script. The needed binaries are PHPCS, ESLint, and Stylelint.

#!/bin/bash
###############################################################################
# Check style for list of code
# For source code
# - PHP
# - JS (js, es6, jsx)
# - CSS (css, scss, less)
# This can be used in build server or pre-commit hook in git, depends on the
# SOURCE_FILE variable.
###############################################################################
# Binaries
PHP_BIN=${PHP_BIN:-'php'}
PHPCS_BIN=${PHPCS_BIN:-'./vendor/bin/phpcs'}
ESLINT_BIN=${ESLINT_BIN:-'./node_modules/.bin/eslint'}
STYLELINT_BIN=${STYLELINT_BIN:-'./node_modules/.bin/stylelint'}
# Getting list of files. Default is diff-ing with HEAD.
SOURCE_FILES=${SOURCE_FILES:-`git diff-index --name-only --diff-filter=ACMR HEAD`}
if [ "$SOURCE_FILES" == "" ]; then
exit 0
fi
# Create temporary copy of staging area and move all Added, Copied, Modified, Renamed.
TMP_STAGING='./tmp_staging'
FILE_PATTERN="\.(php|phtml|js|jsx|es6|css|scss|less)$"
if [ -e $TMP_STAGING ]; then
rm -rf $TMP_STAGING
fi
mkdir $TMP_STAGING
for FILE in $SOURCE_FILES; do
echo "$FILE" | egrep -q "$FILE_PATTERN"
RETVAL=$?
if [ "$RETVAL" -eq "0" ]; then
cp --parents $FILE $TMP_STAGING
fi
done
########################################################
# PHP
########################################################
echo "Checking PHP..."
ERRORS_BUFFER=""
PHP_FILE_PATTERN='.(php|phtml)$'
for FILE in `find $TMP_STAGING | grep -E $PHP_FILE_PATTERN`; do
ERRORS=$(${PHP_BIN} -l $FILE 2>&1 | grep "Parse error")
ERRORS_BUFFER="$ERRORS_BUFFER\n$ERRORS"
done
ERRORS_BUFFER="$(echo -e "${ERRORS_BUFFER}" | sed -e 's/^[[:space:]]*//')"
if [ -n "$ERRORS_BUFFER" ]; then
echo "Found PHP parse errors: "
echo -e $ERRORS_BUFFER
echo "PHP parse errors found. Fix errors and commit again."
exit 1
fi
PHPCS_CODING_STANDARD=./etc/phpcs/ruleset.xml
PHPCS_OPTS=${PHPCS_OPTS:-''}
PHP_STAGED_FILES=''
for FILE in `find $TMP_STAGING -type f | grep -E $PHP_FILE_PATTERN`; do
PHP_STAGED_FILES="$PHP_STAGED_FILES $FILE"
done
PHPCS_RETVAL=0
if [ "$PHP_STAGED_FILES" != "" ]; then
PHPCS_OUTPUT=$(${PHPCS_BIN} $PHPCS_OPTS --standard=$PHPCS_CODING_STANDARD $PHP_STAGED_FILES)
PHPCS_RETVAL=$?
fi
########################################################
# JS
# The config file should be stored in one directory
# config.js.yml, config.es6.yml, config.jsx.yml
# https://github.com/eslint/eslint/pull/8081
########################################################
echo "Checking JS..."
JS_EXT=(js jsx es6)
ESLINT_OUTPUT=""
ESLINT_STANDARD_DIR=./etc/eslint/
ESLINT_RETVAL=0
for EXT in "${JS_EXT[@]}";
do
FILES=$(find $TMP_STAGING -type f | grep -E ".${EXT}$")
if [ "$FILES" == "" ]; then
continue
fi
ESLINT_EXT_ERRORS=$(${ESLINT_BIN} --no-ignore --no-color -c $ESLINT_STANDARD_DIR/config.${EXT}.yml $FILES)
ESLINT_EXT_RETVAL=$?
ESLINT_OUTPUT="$ESLINT_OUTPUT\n$ESLINT_EXT_ERRORS"
ESLINT_RETVAL=$((ESLINT_RETVAL+ESLINT_EXT_RETVAL))
done
########################################################
# CSS
########################################################
echo "Checking CSS..."
STYLELINT_OPTS=${STYLELINT_OPTS:-''}
CSS_FILE_PATTERN='.(css|scss|less)$'
CSS_FILES=`find $TMP_STAGING -type f | grep -E $CSS_FILE_PATTERN`
STYLELINT_RETVAL=0
if [ "$CSS_FILES" != "" ]; then
STYLELINT_OUTPUT=$(${STYLELINT_BIN} $STYLELINT_OPTS $CSS_FILES)
STYLELINT_RETVAL=$?
fi
################################################################################
# Displaying all
################################################################################
rm -rf $TMP_STAGING
if [ $PHPCS_RETVAL -ne 0 ]; then
echo "$PHPCS_OUTPUT"
fi
if [ $ESLINT_RETVAL -ne 0 ]; then
echo "$ESLINT_OUTPUT"
fi
if [ $STYLELINT_RETVAL -ne 0 ]; then
echo "$STYLELINT_OUTPUT"
fi
RETVAL=$(($PHPCS_RETVAL+$ESLINT_RETVAL+$STYLELINT_RETVAL))
exit $RETVAL
view raw checkstyle.sh hosted with ❤ by GitHub

To execute in the pre-commit, you can just use this.

SOURCE_FILES=${SOURCE_FILES:-`git diff-index --name-only --diff-filter=ACMR HEAD`}
export SOURCE_FILES
./checkstyle.sh

exit $?

This was just an idea popped up when I had trouble sleeping last night. Basically we can use Thrift for defining the data and service going in and out Lambda service instead of plain REST API.

Below is the code for the server. To make it easier to deploy I am using Serverless Framework.

import sys
sys.path.append('gen-py')
sys.path.append('vendored')
from thrift.protocol import TBinaryProtocol, TJSONProtocol
from thrift.server import TServer
from thrift.transport import TTransport
from lambda_thrift_service import MultiplicationService
class MultiplicationServiceHandler(object):
def multiply(self, i, j):
return i * j
handler = MultiplicationServiceHandler()
processor = MultiplicationService.Processor(handler)
# I tried using TBinaryProtocol but somewhat it won't work, TJSONProtocol works
protocol_factory = TJSONProtocol.TJSONProtocolFactory()
server = TServer.TServer(processor, None, None, None, protocol_factory, protocol_factory)
def multiply(event, context):
body = event['body']
itrans = TTransport.TMemoryBuffer(body)
otrans = TTransport.TMemoryBuffer()
iprot = server.inputProtocolFactory.getProtocol(itrans)
oprot = server.outputProtocolFactory.getProtocol(otrans)
server.processor.process(iprot, oprot)
return {'statusCode': 200, 'body': otrans.getvalue()}
view raw handler.py hosted with ❤ by GitHub

This is still lack authentication process whatsoever so I don’t think this should be use in production until I figure it out.

The full source code is hosted here: https://github.com/petrabarus/aws-lambda-thrift-example


Putting this here too (I’m in habit for putting scripts into blog).

#!/usr/bin/env bash
seq 10 | xargs -I X bash -c "echo X \$RANDOM"
view raw command.sh hosted with ❤ by GitHub

Just drop this again..

#!/usr/bin/env bash
seq 12 | pr -7ats, | xargs -I X echo "SELECT * FROM Table WHERE id IN (X)"
#output
#SELECT * FROM Table WHERE id IN (1,2,3,4,5,6,7)
#SELECT * FROM Table WHERE id IN (8,9,10,11,12)
seq 12 | pr -7ats | xargs -I X mysql database -e "DELETE FROM Table WHERE id IN (X)"
view raw command.sh hosted with ❤ by GitHub

at first I’m using awk, but turns out there is pr command.

Source: Stackoverflow.


Just dropping by here

#!/usr/bin/env bash
aws ec2 describe-spot-instance-requests | \
jq -r '.SpotInstanceRequests | .[] | select(.LaunchSpecification.InstanceType == "c4.8xlarge" and .State == "active") | .InstanceId' | \
xargs -I X sh -c "aws ec2 describe-instances --instance-id X | jq -r .Reservations[0].Instances[0].PublicDnsName" | \
xargs -I X ssh -i ~/mykey.pem ubuntu@X "echo \"Hello WOrld\""
view raw gistfile1.sh hosted with ❤ by GitHub

Just met a problem when I tried to serialize a PHP DateInterval object in HHVM (at least for 3.9.1). Turns out the DateInterval is unserializable. Create a bit workaround for this.

<?php

$dateinterval1 = new DateInterval('PT1H');
$baseDate = new DateTimeImmutable();
$date1 = $baseDate->add($dateinterval1);
$string1 = $dateinterval1->format('%y years %m months %d days %h hours %i minutes %s seconds');

$dateinterval2 = DateInterval::createFromDateString($string1);
$date2 = $baseDate->add($dateinterval2);

$string2 = $dateinterval2->format('%y years %m months %d days %h hours %i minutes %s seconds');
if ($string1 == $string2) {
    print "Formats are equal\n";
}
if ($date1 == $date2) {
    print "Objects are equal\n";
}
if ($date1->getTimestamp() == $date2->getTimestamp()) {
    print "Timestamp are equal\n";
}

The test can be seen here: https://3v4l.org/HvLFP


Usually before committing a file we need to check modified files against the code convention before committing to the code repository.

Here’s a single line to run modified files in Git against PHPCS.

git ls-files -m | grep '\.php$' | xargs ./vendor/bin/phpcs -s --standard=etc/phpcs/ruleset.xml

Code above assumes you install PHPCS using composer and have your own standard located in the etc/phpcs/ruleset.xml.

UPDATE

To check all uncommited files, run this

git ls-files --others --exclude-standard | grep '\.php$' | xargs ./vendor/bin/phpcs -s --standard=etc/phpcs/ruleset.xml

I just watched The Last: Naruto The Movie a couple of days ago and I recalled that it’s been almost a quarter of decade since I last read the mangascan.

Reading Naruto in Kindle

Reading Naruto in Kindle

So I got a complete 2GB of mangascan pictures from my friend from volume 1 until volume 72. I’ve been a fan of Kindle e-book reader and I want to read the mangascan in my Kindle device. Here’s how I converted the PNG and JPG files to PDF so it can be readable in Kindle.

Basically what I need is imagemagick library to convert the images to PDF. Here is how to use the imagemagick to do the conversion.

As long as the JPG/PNG files is named with proper file naming, doing a batch conversion in zipped files is as simple as this. It shouldn’t take too long to convert all of the images to PDF. In my case it took less than an hour. The quality of the PDF is not that bad, but I think we can configure the imagemagick to increase the quality. I assume it reduces the quality by a bit.

for zipfile in $(find . -type f -iname &quot;*.zip&quot; | sort -n); do
    echo &quot;$zipfile&quot;
    filename=$(basename &quot;$zipfile&quot;)
    filename=&quot;${filename%.*}&quot;
    echo &quot;$filename&quot;
    unzip $zipfile -d $filename
    echo &quot;Converting....&quot;
    find $filename | sort -n | tr '\n' ' ' | sed &quot;s/$/\ ${filename}.pdf/&quot; | xargs convert -verbose
done

See? Pretty simple, right? (The fact that it’s really simple is why I posted here. Might be useful for me in the future).


To accept Angular $http.post that is formatted as JSON in Yii2, just set this in the Yii2 application component.

        'request' => [
            'parsers' => [
                'application/json' => 'yii\web\JsonParser',
            ]
        ],

To use the data, don’t use global $_POST. Instead use

$data = Yii::$app->getRequest->post();
%d blogger menyukai ini: