"Life is all about sharing. If we are good at something, pass it on." - Mary Berry

Automate office tasks with Python


Hàng tháng bạn nhận được một file excel về danh sách D. Từ danh sách này bạn cần filter cột C theo tiêu chí T1 để lấy ra danh sách D1. Có được D1 rồi bạn Save As thành t1.xlsx. Làm xong T1, bạn tiếp tục với T2 -> t2.xlsx … Làm tiếp cho đến Tn -> tn.xlsx. Có được các danh sách t1.xlsx -> tn.xlsx này rồi, giờ bạn cần gửi mail:


The power of praise


K, 9 tuổi.

Dạo này đang luyện: cắm cơm, nhặt rau. Hôm trước học bài mới: gọt su su. Bài này hơi khó hơn chút: đầu tiên dùng dao cắt đúng khía thành các miếng nhỏ, sau đó gọt sạch, cuối cùng là bỏ lõi. Cứ mỗi lần làm xong một miếng, K lại hỏi:

Và đúng là nó đẹp hơn thật. Lời khen đã giúp K làm tốt hơn.


condition form of depends_on in docker-compose version 3


As version 3 no longer supports the condition form of depends_on, what is the alternative way to wait for a container to be started completely?

From 1.27.0, 2.x and 3.x are merged with COMPOSE_SPEC schema.

version is now optional. So, you can just remove it and specify a condition as before:

 2  web:
 3    build: .
 4    depends_on:
 5      redis:
 6        condition: service_healthy
 7  redis:
 8    image: redis
 9    healthcheck:
10      test: ["CMD", "redis-cli", "ping"]
11      interval: 1s
12      timeout: 3s
13      retries: 30


Let's Encrypt too many certificates already issued


Traefik is configured to use Let’s Encrypt to generate certificate for my blog (and other services) automatically. One day after restarting, I cannot access to my blog via HTTPS anymore (NET::ERR_CERT_AUTHORITY_INVALID). Why?

By looking at the Traefik logs, I found this:

time=“2021-02-04T01:54:33Z” level=error msg=“Unable to obtain ACME certificate for domains \“quantonganh.com\”: unable to generate a certificate for the domains [quantonganh.com]: acme: error: 429 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rateLimited :: Error creating new order :: too many certificates already issued for exact set of domains: quantonganh.com: see https://letsencrypt.org/docs/rate-limits/, url: “ providerName=le.acme routerName=blog-secured@docker rule=“Host(quantonganh.com)”


plugins/docker failed to resolve Keycloak hostname?


After integrating Docker registry with Keycloak, the publishing step failed to authenticate with Docker Registry.

The full error message is:

1time="2021-01-26T13:44:18.485121053Z" level=error msg="Handler for POST /v1.40/auth returned error: Get https://docker.domain.com/v2/: Get https://sso.domain.com/auth/realms/application/protocol/docker-v2/auth?account=******&client_id=docker&offline_token=true&service=aws-docker-registry: dial tcp: lookup sso.domain.com on no such host"

sso.domain.com is a local hostname which can be resolved on the host. How can I make it resolvable inside the plugins/docker container?

I found some similar issues:

but they are slightly differences.

Look at this: http://plugins.drone.io/drone-plugins/drone-docker/


How to run a pipeline step only when pushing to a new branch?


GitHub sends push hook when pushing to a new branch and merging a PR. How can we distinguish between them?

We are running integration test by triggering a downstream build when a PR is merged into specific branches. In the downstream repository, we pull all the docker images which has been built and pushed from upstream. The thing is we also used the drone-convert-pathschanged to only publish what modules has been changed.

So, what happens when pushing to a new release-* branch?


How to add full text search to my static website?


After building the website, I want to add search function. There are some ways to do it:

So, is there any search engine written in Go?

Bleve has more star and be maintained more often than riot, I would like to give it a try first.


Looking at the documentation, there are three steps to add search to your website:


Unable to obtain ACME certificate for domains


Lets Encrypt tells me that my domain contains an invalid character. What is it?

remark42 is configured like this:

 1  remark42:
 2    image: umputun/remark42:arm64
 3    container_name: "remark42"
 4    restart: always
 5    labels:
 6      - traefik.enable=true
 7      - traefik.http.routers.remark42.rule=Host(`${REMARK_URL}`)
 8      - traefik.http.routers.remark42.entrypoints=https
 9      - traefik.http.routers.remark42.tls.certresolver=le
10      - traefik.http.services.remark42.loadbalancer.server.port=8080


A && B || C is not the same as if-then-else


I have been thought that if-then-else statement can be written in one line by using A && B || C but I was wrong.

To speed up my Drone CI time, I configured the static-check step to only run when there are some .go files have been changed:

1git --no-pager diff --name-only ${DRONE_COMMIT_LINK##*/} | grep -q "\.go$" && golangci-lint run --deadline 2m -v ./... || true

I was thought that A && B || C is the same as:


How to perform integration testing in Go?


Integration testing can be triggered by using Drone downstream plugin:

 2- name: trigger
 3  image: plugins/downstream:linux-amd64
 4  settings:
 5    params:
 7    repositories:
 8    - repo/integration-test@${DRONE_COMMIT_BRANCH}
 9    server: https://drone.example.com
10    token:
11      from_secret: drone_token

It can be separated with unit tests by using build tags:

1// +build integration
3package webserver_test

Then we can write code to perform integration test as usual.