# https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions
name: XCrawler - Build & Tests
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
on:
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
pull_request:
branches: [ develop ]
types: [ opened, synchronize ]
jobs:
sonar_cloud:
name: SonarCloud
uses: ./.github/workflows/sonar_cloud.yml
secrets: inherit
security_check:
name: Security check
uses: ./.github/workflows/security_check.yml
secrets: inherit
code_standards:
name: Code standards check
needs: [ sonar_cloud, security_check ]
strategy:
matrix:
lint: [ phpstan, phpmd, phpcs ]
uses: ./.github/workflows/code_standards.yml
with:
lint: ${{ matrix.lint }}
secrets: inherit
tests:
name: Execute UnitTest
needs: [ code_standards ]
strategy:
matrix:
test: [ Client, JAV, Flickr, Core ]
uses: ./.github/workflows/unittest.yml
with:
test: ${{ matrix.test }}
secrets: inherit
finalizing_build:
name: "All Parallel Tests passed"
needs: [ tests ]
uses: ./.github/workflows/codecov.yml
secrets: inherit
Continue reading Github action – Reusable Author: jooservices
Laravel – Code structure with UnitTest
Giả sử ta có một code structure như sau
Controller
- Gọi Services để thực thi và respond
Services
- Gọi Repository khi cần tương tác database
- Trigger Event
- Gọi các Services khác hoặc các code logic khác.
Vậy UnitTest sẽ cần những gì. Trong quan điểm mình là đi từ thấp nhất lên cao nhất
- Repositories : Đảm bảo database được thực thi, assert các data như mong đợi.
- Assert events đã dispatched.
- Events : Dispatch events và assert data như mong đợi
- Services
- Nếu services có các events ẢNH HƯỞNG TRỰC TIẾP đến kết quả thì mình sẽ không fake event mà để event thực thi và assert kết quả
- Nếu các events đó dùng cho 3rd thì mình assert để make sure events dispatched như mong đợi
Tất nhiên nếu service đó thuần túy gọi tới 3rd party thì mình chỉ việc mock và test respond từ 3rd party thôi.
Và sau cùng là assert controller trả về data như mong đợi
[Tip] Ubuntu 22.04 Missing lock screen menu item

gsettings set org.gnome.desktop.lockdown disable-lock-screen false
Github action – Slack notification
Here is good one package to use
https://github.com/slackapi/slack-github-action
And here is my implement
- name: Slack Notification
id: slack
uses: slackapi/[email protected]
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
with:
# Slack channel id, channel name, or user id to post message.
# See also: https://api.slack.com/methods/chat.postMessage#channels
# You can pass in multiple channels to post to by providing a comma-delimited list of channel IDs.
channel-id: 'xcrawler-github'
# This data can be any valid JSON from a previous step in the GitHub Action
# For posting a rich message using Block Kit
payload: |
{
"attachments": [
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Github Action",
"emoji": true
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Name:*\n ${{ github.event_name }} "
},
{
"type": "mrkdwn",
"text": "*Type:*\n ${{ github.event.action }} ${{ github.event.ref_type }} ${{ github.event.ref }}"
}
]
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Branch:*\n ${{ github.event.pull_request.head.ref }}"
},
{
"type": "mrkdwn",
"text": "*Status:*\n `${{ job.status }}`"
}
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
}
]
}
]
}
]
}
PHP Development tools i have used
Editor
- PHPStorm : Of course no one can work with PHP without PHPStorm
- Sublime : Very light editor
Bug tracking
- Sentry : It’s simply fatal error tracking with friendly GUI without digging into log files
My hosted version at https://sentry.jooservices.com/auth/login/jooservices/
Microservice – XClient
https://github.com/jooservices/XClient
As a part of refactoring XCrawler. XClient under development
- Receive crawl request from another service and process request to 3rd party
- Receive queue request from another service. Queue will be scheduling process later and process callback to another service
Caching also provided
By this way, we don’t need care anything about Curl / Guzzle in another project / service.
Laravel – Different between Model trait boot & initialization
Trace back to Model we have
protected static function bootTraits()
{
$class = static::class;
$booted = [];
static::$traitInitializers[$class] = [];
foreach (class_uses_recursive($class) as $trait) {
$method = 'boot'.class_basename($trait);
if (method_exists($class, $method) && ! in_array($method, $booted)) {
forward_static_call([$class, $method]);
$booted[] = $method;
}
if (method_exists($class, $method = 'initialize'.class_basename($trait))) {
static::$traitInitializers[$class][] = $method;
static::$traitInitializers[$class] = array_unique(
static::$traitInitializers[$class]
);
}
}
}
Theo như code trên có thể thấy
boot
sẽ call đến static method. Hay nói cách khác sẽ tác động tới mọi instances của Model này- trong khi đó `
initialize
thì ngược lại. Chỉ tác động tới instance hiện tại.
1 ví dụ thực tế
trait HasSlug
{
public function initializeHasSystem()
{
$this->mergeCasts([
'slug' => 'string'
]);
$this->mergeFillable([
'slug'
]);
}
public static function bootHasSlug()
{
static::creating(function ($model) {
$model->{$model->getSlugName()} = Str::slug($model->name);
});
static::updating(function ($model) {
$model->{$model->getSlugName()} = Str::slug($model->name);
});
}
public function scopeSlug($query, $uuid)
{
return $query->where($this->getSlugName(), $uuid);
}
public function getSlugName()
{
return property_exists($this, 'slug') ? $this->slug : 'slug';
}
}
HAProxy Health check fails
backend be_staging
option httpchk
server staging 192.168.1.60:80 check
Web server sử dụng Nginx
Đối với config trên thì HAProxy báo be_staging
not available dù rằng mọi access đều working fine. !
Check Nginx log ta có
192.168.1.4 - - [27/Aug/2023:21:36:00 +0700] "OPTIONS / HTTP/1.0" 405 166 "-" "-"
Vậy là do Nginx nó trả về 405 cho OPTIONS requests.
Update HAProxy
backend be_staging
option httpchk GET /
http-check expect status 200
server staging 192.168.1.60:80 check
Và mọi thứ trở về lại bình thường !
Laravel – Stable Diffusion
Sau một thời gian nghịch Stable Diffusion thì giờ cũng chút hứng thú với … code Laravel cho em nó.
https://github.com/jooservices/Stable-Diffusion
Về cơ bản
- Tạo ra queues để liên tục generate images
- Tạo ra các “base prompt” để có thể tái` sử dụng ( ví dụ có thể tạo `
`$prompt->portraits('Irene Aronson')
thì sẽ tự add prompt là portraits của nghệ sĩ Irene Aronson
Alrite. Tuy nhiên trước đó thì cần chuẩn bị 1 số thứ
- Stable Diffusion ( webUI ) chạy service
Description=systemd service start stable-diffusion
[Service]
Type=simple
Restart=always
RestartSec=1
ExecStart=/bin/bash /home/joos/stable-diffusion-webui/webui.sh
User=joos
WorkingDirectory=/home/joos/stable-diffusion-webui/
StandardOutput=append:/var/log/sdwebui.log
StandardError=append:/var/log/sdwebui.log
[Install]
WantedBy=multi-user.target
- 1 em cron để chạy schedule:run của Laravel
Xong ! Giờ thì ta có 2 cách
- Generate ra “queues” qua command
php artisan stable-diffusion:generate --prompt="a beautiful girl at 20 years old. she has colorful hair"
Command này sẽ sinh ra 1.001 queues ứng với prompt trên và … toàn bộ models mình đang có.
- Code thêm theo ý
$response = $service
->txt2img()
->generate($payload)
->save($queue->uuid)
->getResponse();
Ubuntu – Create system user without login
sudo groupadd --system prometheus
sudo useradd -s /sbin/nologin --system -g prometheus prometheus