នៅក្នុងប្រកាសមុនរបស់យើង យើងបានឃើញពីរបៀបរកឃើញ និងការពារប្រឆាំងនឹងការពុលដោយផ្ទាល់ Pipeline ការប្រតិបត្តិ (D-PPE)។ យើងក៏បានឃើញពីរបៀបរកឃើញភាពងាយរងគ្រោះនោះដោយប្រើ ម៉ាស៊ីនស្កេន Xygeniក៏ដូចជាយន្តការការពារមួយចំនួន។
ពុល Pipeline ការប្រតិបត្តិ (PPE) ត្រូវបានបង្កើតឡើងនៅពេលដែលអ្នកវាយប្រហារអាចកែប្រែ pipeline តក្កវិជ្ជាតាមវិធីមួយក្នុងចំណោមវិធីពីរយ៉ាង៖
- ដោយការកែប្រែឯកសារកំណត់រចនាសម្ព័ន្ធ CI (the pipeline) -> សម្ភារៈការពារផ្ទាល់ខ្លួន (PPE) ដោយផ្ទាល់ (D-PPE)
- ដោយការកែប្រែឯកសារដែលបានយោងដោយ pipeline (ឧទាហរណ៍៖ ស្គ្រីបដែលបានយោងពីក្នុង pipeline ឯកសារកំណត់រចនាសម្ព័ន្ធ) -> សម្ភារៈការពារផ្ទាល់ខ្លួនដោយប្រយោល (I-PPE)

នៅក្នុងអត្ថបទនេះ យើងនឹងសិក្សាស៊ីជម្រៅអំពី Indirect PPE។ ប៉ុន្តែមុននឹងនោះ និងជាការបំពេញបន្ថែមលើអត្ថបទមុនរបស់ខ្ញុំ ចូរយើងមើលជាមុនសិនថាតើ GitHub គ្រប់គ្រងការប្រតិបត្តិរបស់... pipelineនិងអ្វីទៅជាយន្តការការពារប្រឆាំងនឹង D-PPE។
តើ GitHub ការពារការប្រតិបត្តិយ៉ាងដូចម្តេច pipelineមកពី PR មែនទេ?
តើ GitHub ដំណើរការយ៉ាងដូចម្តេចទាក់ទងនឹងការប្រតិបត្តិនៃអ្វីដែលបានកែប្រែ pipelines?
បានកែប្រែ pipelines អាចមកពី Pushes ឬ Pull Requests (ប។ ព។ ) ។ ក្នុងនាមជាការអនុវត្តល្អបំផុតដ៏សំខាន់មួយ វាត្រូវបានណែនាំយ៉ាងមុតមាំឱ្យជៀសវាងការ "រុញ" ដោយផ្ទាល់ទៅកាន់សាខាដែលមានការការពារ និងការប្រើប្រាស់ Pull Requests ជាយន្តការមួយដើម្បីអនុវត្តការពិនិត្យឡើងវិញមួយចំនួនមុនពេលទទួលយកកូដដែលបានរួមចំណែកណាមួយ។
Pull Requests អាចមកពីប្រភពពីរផ្សេងគ្នា៖
- PR មកពី សម
- PR មកពី សាខា
PR ពី សម អាចមកពីណាក៏បាន សាធារណៈ or ឯកជន ឃ្លាំង។
ខណៈពេលដែលយើងកំពុងដោះស្រាយជាមួយ PPE (ថ្នាំពុល) Pipeline ការប្រតិបត្តិ) ចំណុចសំខាន់របស់យើងមិនមែនជា "ការទទួលយក" នៃ PR ទេ ប៉ុន្តែជាការប្រតិបត្តិនៃការកែប្រែ pipeline ក្នុងអំឡុងពេលដំណើរការទទួលយក/អនុម័តរបស់ PR។ នៅក្នុងស្នូលនៃការវាយប្រហារ PPE មានការប្រតិបត្តិដោយអចេតនានៃការកែប្រែ "ព្យាបាទ" pipeline.
និយាយឲ្យខ្លីទៅ ពុលហើយ Pipeline ការប្រតិបត្តិ (PPE) ត្រូវបានផលិតនៅពេល អ្នកវាយប្រហារអាចកែប្រែ pipeline តក្ក.
មានពីរ វ៉ារ្យ៉ង់:
- សម្ភារៈការពារផ្ទាល់ខ្លួនដោយផ្ទាល់ (សម្ភារៈការពារផ្ទាល់ខ្លួន (D-PPE)នៅក្នុងសេណារីយ៉ូ D-PPE អ្នកវាយប្រហារកែប្រែឯកសារកំណត់រចនាសម្ព័ន្ធ CI នៅក្នុងឃ្លាំងទិន្នន័យ ដែលពួកគេមានសិទ្ធិចូលប្រើ ទាំងដោយការរុញការផ្លាស់ប្តូរដោយផ្ទាល់ទៅកាន់សាខាពីចម្ងាយដែលមិនបានការពារនៅលើ repo ឬដោយការបញ្ជូន PR ជាមួយនឹងការផ្លាស់ប្តូរពីសាខា ឬពី fork។ ចាប់តាំងពី CI pipeline ការប្រតិបត្តិត្រូវបានកំណត់ដោយពាក្យបញ្ជានៅក្នុងឯកសារកំណត់រចនាសម្ព័ន្ធ CI ដែលបានកែប្រែ ពាក្យបញ្ជាព្យាបាទរបស់អ្នកវាយប្រហារនឹងដំណើរការនៅក្នុងណូតសាងសង់នៅពេលដែលការសាងសង់ pipeline ត្រូវបានកេះ។
- សម្ភារៈការពារផ្ទាល់ខ្លួនដោយប្រយោល (ឧបករណ៍ការពារផ្ទាល់ខ្លួន (I-PPE)ក្នុងករណីខ្លះ លទ្ធភាពនៃ D-PPE មិនមានសម្រាប់សត្រូវដែលអាចចូលប្រើបាន SCM ឃ្លាំងសម្ងាត់ (ឧទាហរណ៍ ប្រសិនបើ pipeline ត្រូវបានកំណត់រចនាសម្ព័ន្ធដើម្បីទាញយកឯកសារកំណត់រចនាសម្ព័ន្ធ CI ពីសាខាដាច់ដោយឡែក និងការពារនៅក្នុងឃ្លាំងដូចគ្នា)។ ក្នុងស្ថានភាពបែបនេះ ជាជាងការបំពុល pipeline ខ្លួនវាផ្ទាល់ អ្នកវាយប្រហារចាក់កូដព្យាបាទចូលទៅក្នុងឯកសារដែលបានយោងដោយ pipeline (ឧទាហរណ៍៖ ស្គ្រីបដែលបានយោងពីក្នុង pipeline ឯកសារកំណត់រចនាសម្ព័ន្ធ)
ក្នុងករណីទាំងពីរនេះ GitHub នឹងប្រតិបត្តិឯកសារដែលបានកែប្រែ pipeline ដោយមិនចាំបាច់មានការពិនិត្យឡើងវិញ ឬការអនុម័តពីមុនមកទេ.
ទំនាក់ទំនងសាធារណៈពី forks បន្ត សាធារណៈ repos
GitHub អនុញ្ញាតឱ្យកំណត់រចនាសម្ព័ន្ធឥរិយាបថនៅពេលដំណើរការ ទំនាក់ទំនងសាធារណៈមកពីសមភាគីនៅក្នុងឃ្លាំងសាធារណៈ.
នៅពេលដែល PR មកពី fork មួយ GitHub តែងតែបង្ខំឱ្យមានកម្រិត "ការយល់ព្រម" មួយចំនួនមុនពេលប្រតិបត្តិ pipeline ជាប់ទាក់ទងនឹង PRកម្រិតនៃការយល់ព្រមនេះផ្លាស់ប្តូរពីការយល់ព្រមខ្សោយទៅជាការយល់ព្រមតឹងរ៉ឹង។
At កម្រិតអង្គការ (អង្គការ>>ការកំណត់>>សកម្មភាព>>ទូទៅ) អ្នកអាចសម្រេចចិត្តក្នុងចំណោមជម្រើស "ការអនុម័ត" ជាច្រើន៖

តឹងរ៉ឹងបំផុតគឺចុងក្រោយ ("តម្រូវឱ្យមានការយល់ព្រមពីអ្នកសហការខាងក្រៅទាំងអស់”) ពីព្រោះ GitHub នឹងតែងតែតម្រូវឱ្យមានការយល់ព្រម នៅពេលដែល PR មកពី forks ពីអ្នកសហការខាងក្រៅ។
ប៉ុន្តែសូម្បីតែក្នុងករណីដ៏តឹងរ៉ឹងនេះក៏ដោយ ក៏នៅមាន ភាពខុសគ្នារវាងអ្នកសហការដែលមានសិទ្ធិអាន និងសរសេរ.
- នៅពេលដែល PR មកពី អាន អ្នកប្រើប្រាស់, នេះ ការប្រតិបត្តិនៃ pipeline ត្រូវបានបញ្ឈប់ រហូតដល់មានការអនុម័តលើការផ្លាស់ប្តូរ។ ប្រសិនបើការអនុម័តគឺល្អ នោះការកែប្រែ pipeline ត្រូវបានប្រតិបត្តិ។
- នៅពេលដែល PR មកពី សរសេរ អ្នកប្រើប្រាស់, នេះ ការអនុម័តគឺមិនចាំបាច់ទេ ហើយការកែប្រែ pipeline ត្រូវបានប្រតិបត្តិជានិច្ច !!

សរុបមក PR ដែលមកពី forks នៅលើឃ្លាំងសាធារណៈត្រូវបានការពារស្រាលពី PPE។ មានការការពារខ្លះប្រឆាំងនឹងអ្នកប្រើប្រាស់ខាងក្រៅ (អាន) ប៉ុន្តែគ្មានអ្វីទាក់ទងនឹងអ្នកប្រើប្រាស់ផ្ទៃក្នុង (សរសេរ) ទេ។
អំពីអ្វី ទំនាក់ទំនងសាធារណៈមកពីការបំបែកចេញពីឃ្លាំងឯកជន?
ទំនាក់ទំនងសាធារណៈពី forks បន្ត ឯកជន repos
នៅក្នុងសេណារីយ៉ូនេះ GitHub ផ្តល់នូវការកំណត់រចនាសម្ព័ន្ធមានប្រយោជន៍មួយចំនួន។

ការកំណត់ខាងលើអាចត្រូវបានកំណត់រចនាសម្ព័ន្ធនៅ សរីរាង្គ ឬនៅ repo កម្រិត។
ពេលណា គ្មានជម្រើសណាមួយត្រូវបានធីកទេ, GitHub នឹង ស្នើសុំការយល់ព្រម និង វានឹងមិនអនុវត្តការកែប្រែទេ pipelineនេះគឺជាការកំណត់រចនាសម្ព័ន្ធដែលមានសុវត្ថិភាពបំផុត!!
ចំពោះ ការកំណត់រចនាសម្ព័ន្ធដែលមិនមានសុវត្ថិភាពបំផុត គឺពេលណា។ "ដំណើរការលំហូរការងារពី fork pull request"ត្រូវបានពិនិត្យក្នុងករណីនេះ ដូចគ្នាសម្រាប់ទាំងអ្នកប្រើប្រាស់អាន និងសរសេរ Github នឹងប្រតិបត្តិដោយស្វ័យប្រវត្តិនូវការកែប្រែ pipeline!! ហើយស្ថានភាពនេះអាចមានសូម្បីតែ កាន់តែអាក្រក់ ប្រសិនបើ "ផ្ញើថូខឹនសរសេរទៅកាន់លំហូរការងារពីសមស្រប pull requests"និង"ផ្ញើអាថ៌កំបាំង និងអថេរទៅកាន់លំហូរការងារពីសម (fork) pull requests"ត្រូវបានធីក។ កុំធ្វើបែបនេះលុះត្រាតែមានហេតុផលច្បាស់លាស់!!
បើ“តម្រូវឱ្យមានការយល់ព្រមសម្រាប់សម pull request លំហូរការងារ"ត្រូវបានធីក ស្ថានភាពខាងលើត្រូវបានបង្កើនប្រសិទ្ធភាពខ្លះ៖ GitHub នឹងស្នើសុំការយល់ព្រម ហើយមិនប្រតិបត្តិអ្វីដែលបានកែប្រែនោះទេ។ pipeline សម្រាប់អ្នកប្រើប្រាស់អាន ប៉ុន្តែវានៅតែនឹងប្រតិបត្តិវាសម្រាប់អ្នកប្រើប្រាស់សរសេរ។

ឃើញសមហើយ ចុះយ៉ាងណាចំពោះ PR មកពីសាខានានា?
PR ពី សាខា
ដើម្បីការពារសេណារីយ៉ូនេះ អ្នកត្រូវតែពឹងផ្អែកលើ ច្បាប់ការពារសាខា.
នៅកម្រិត repo អ្នកអាចបង្កើតច្បាប់ការពារសាខាសម្រាប់សាខាណាមួយ។ ច្បាប់ទាំងនេះបន្ថែមច្បាប់មួយចំនួន ការរឹតបន្តឹងចំពោះការកែប្រែសាខាដែលត្រូវបានការពារ.
ទោះបីជាអ្នកកំណត់រចនាសម្ព័ន្ធច្បាប់ទៅ "ទាមទារ ក pull request មុនពេលបញ្ចូលគ្នា"និង"តម្រូវឱ្យមានការយល់ព្រម" ដែលបានកែប្រែ pipeline នឹងត្រូវបានប្រតិបត្តិដោយស្វ័យប្រវត្តិនៅពេលបង្កើត PR«ការអនុម័ត» នឹងអនុវត្តចំពោះតែសកម្មភាពបញ្ចូលគ្នាប៉ុណ្ណោះ។

ចុះយ៉ាងណាចំពោះការពុលដោយប្រយោល Pipeline ការប្រតិបត្តិ
ដូចដែលយើងបានឃើញខាងលើ D-PPE អាចត្រូវបានកាត់បន្ថយដោយការប្រើប្រាស់ ទាញ_សំណើ_គោលដៅ, ប៉ុន្តែវា មិនអនុវត្តចំពោះ I-PPE ទេ.
ប្រសិនបើអ្នកប្រើ pull_request_target ការត្រួតពិនិត្យលំនាំដើមនឹងជាលេខកូដមូលដ្ឋាន។ ប៉ុន្តែប្រសិនបើអ្នកចង់ផ្ទៀងផ្ទាត់ការត្រួតពិនិត្យមួយចំនួនលើលេខកូដដែលបានរួមចំណែក (លេខកូដ PR) អ្នកត្រូវពិនិត្យមើលលេខកូដ PR យ៉ាងច្បាស់លាស់។ ដូច្នេះ ប្រសិនបើលេខកូដ PR បានកែប្រែស្គ្រីបសែលណាមួយដែលត្រូវបានហៅដោយ pipeline, “មូលដ្ឋាន” (សុវត្ថិភាព) pipeline នឹងហៅស្គ្រីបសែល "កែប្រែ" → PPE ដោយប្រយោល!!
ដំណោះស្រាយចំពោះបញ្ហានេះគឺស្មុគស្មាញជាងបន្តិច (មិនមានវិធីវេទមន្តដូច pull_request_target ទេ)។
របស់យើង pipeline ឥឡូវនេះមានសុវត្ថិភាពចំពោះ D-PPE ពីព្រោះយើងកំពុងប្រើ pull_request_target។ ប៉ុន្តែវានៅតែងាយរងគ្រោះចំពោះ I-PPE។
នៅក្នុងឧទាហរណ៍សាកល្បងរបស់យើង យើងត្រូវពិនិត្យមើលលេខកូដ PR ជាមូលដ្ឋានដើម្បីបង្កើត build ប៉ុន្តែការធ្វើតេស្តត្រូវបានប្រតិបត្តិលើ artifact ដែលបង្កើតដោយ build។
អញ្ចឹង .. ហេតុអ្វីមិនពិនិត្យមើលមូលដ្ឋានកូដទាំងពីរ?
- សូមពិនិត្យមើលលេខកូដ PR ពីព្រោះវាជាលេខកូដដែលបានរួមចំណែកដែលយើងចង់បង្កើត និងសាកល្បង។
- កូដមូលដ្ឋានសម្រាប់ដំណើរការកំណែដើមនៃ Checkout pipeline និងស្គ្រីបសាងសង់/សាកល្បង
នេះអាចត្រូវបានធ្វើដោយ កំពុងពិនិត្យមើលមូលដ្ឋានកូដទាំងនោះទៅកាន់ថតឯកសារផ្សេងៗគ្នាកូដមូលដ្ឋានអាចត្រូវបានពិនិត្យចេញទៅថតឯកសារដើម ហើយ PR ទៅថតឯកសារផ្សេង។ ក្នុងករណីនេះ យើងនឹងប្រតិបត្តិស្គ្រីបសាងសង់ និងសាកល្បងពីថតឯកសារដើមទល់នឹងកូដដែលដាក់ក្នុងថតឯកសារថ្មី។
ជាការពិតណាស់ នេះជាដំណោះស្រាយងាយស្រួលមួយ!! ប៉ុន្តែ សម្រាប់គោលបំណងសិក្សា ខ្ញុំចង់ណែនាំវ៉ារ្យ៉ង់គួរឱ្យចាប់អារម្មណ៍មួយ (...)
GitHub ដំណើរការការងារ ព្រឹត្តិការណ៍បង្កឲ្យមានបញ្ហា
ក្រៅពី ទាញ_សំណើ_គោលដៅGitHub ផ្តល់នូវព្រឹត្តិការណ៍បង្កកមួយផ្សេងទៀត៖ ដំណើរការការងារព្រឹត្តិការណ៍នេះអនុញ្ញាតឱ្យ ការប្រតិបត្តិនៃ pipeline ត្រូវបានកំណត់លក្ខខណ្ឌទៅមួយផ្សេងទៀត pipelineការប្រតិបត្តិរបស់.
ដំណើរការការងារ និង ទាញ_សំណើ_គោលដៅ ទ្រីកឃើរគឺស្រដៀងគ្នាក្នុងទិដ្ឋភាពមួយ៖ ទាំងពីរនឹងត្រូវបានប្រតិបត្តិក្នុងរបៀបដែលមានសិទ្ធិ និង បើទោះបីជាមានការកែប្រែ PR ក៏ដោយ មូលដ្ឋាន pipeline នឹងត្រូវប្រហារជីវិត!!
តោះមើលបច្ចុប្បន្នរបស់យើង pipeline:
name: PR TARGET CI
on:
pull_request_target:
branches: [ main ]
env:
MY_SECRET: ${{ secrets.MY_SECRET }}
jobs:
prt_build_test_and_merge:
runs-on: ubuntu-latest
steps:
# checkout PR code
- name: Checkout repository
uses: actions/checkout@v4
with:
# This is to get the PR code instead of the repo code
ref: ${{ github.event.pull_request.head.sha }}
# Simulation of a compilation
- name: Building ...
run: |
mkdir ./bin
touch ./bin/mybin.exe
ls -lR
# Simulation of running tests
- name: Running tests ...
id : run_tests
run: |
echo Running tests..
chmod +x runtests.sh
./runtests.sh
echo Tests executed.
#
# Let’s omit the check conditions at this moment …
#
- name: pr_check_conditions_to_merge
[...]
ផ្នែកសាងសង់មានសុវត្ថិភាពចំពោះ D-PPE ប៉ុន្តែផ្នែកធ្វើតេស្តនៅតែងាយរងគ្រោះចំពោះ I-PPE។
ចំពោះ pipeline ខ្លួនវាមានសុវត្ថិភាពចំពោះ D-PPE ដោយសារតែ ទាញ_សំណើ_គោលដៅ បង្កឱ្យមានកំហុស។ ប៉ុន្តែជំហានសាកល្បងនៅតែងាយរងគ្រោះចំពោះ I-PPE ដោយសារតែការហៅស្គ្រីបសែលខាងក្រៅ។
ការជៀសវាង I-PPE
គោលបំណងនៃខាងលើ pipeline គឺដើម្បីបង្កើត និងសាកល្បងកូដដែលបានរួមចំណែក ដោយមានសុវត្ថិភាពចំពោះ PPE។
អញ្ចឹង .. ហេតុអ្វីមិនបែងចែក pipeline ទៅជាពីរ? មួយសម្រាប់សាងសង់ និងមួយទៀតសម្រាប់សាកល្បង..
- ទី ១ pipeline (បង្កើត CI) នឹង ពិនិត្យមើលលេខកូដ PR (ដើម្បីបង្កើតវា), ធ្វើការសាងសង់ និងបង្កើតវត្ថុបុរាណ។
- ទី ៤២ pipeline (សាកល្បង CI) នឹង ពិនិត្យមើលលេខកូដមូលដ្ឋាន (ដើម្បីជៀសវាងការកែប្រែស្គ្រីបសែល) និងប្រតិបត្តិស្គ្រីបដើមប្រឆាំងនឹងវត្ថុបុរាណ។
- ដើម្បីធ្វើសមកាលកម្ម CI សាកល្បង pipeline ដើម្បីដំណើរការបន្ទាប់ពី Build CI pipeline, យើងនឹងប្រើប្រាស់ ដំណើរការការងារ កេះ។

តាមវិធីនេះ៖
- pipeline បង្កើត CI is សុវត្ថិភាព ទៅទាំងពីរ សម្ភារៈការពារផ្ទាល់ខ្លួន (D-PPE) (ដោយសារតែការ ទាញ_សំណើ_គោលដៅ) និង ឧបករណ៍ការពារផ្ទាល់ខ្លួន (I-PPE) (ព្រោះវាលែងដំណើរការស្គ្រីបសែលទៀតហើយ)។
- pipeline សាកល្បង CI គឺក៏ សុវត្ថិភាព ទៅទាំងពីរ សម្ភារៈការពារផ្ទាល់ខ្លួន (D-PPE) (ដោយសារតែការ ដំណើរការការងារ) និង ឧបករណ៍ការពារផ្ទាល់ខ្លួន (I-PPE) (ព្រោះវាពិនិត្យមើលលេខកូដមូលដ្ឋានដើម្បីទទួលបានស្គ្រីបសែលដើម)
តោះមើលលេខកូដទាំងពីរ pipelines យោងតាមការកែប្រែទាំងនេះ ...
1st pipeline (បង្កើត CI):
name: Build CI
on:
pull_request_target:
branches: [ main ]
env:
MY_SECRET: ${{ secrets.MY_SECRET }}
GITHUB_PAT: ${{ secrets.GH_PAT }}
jobs:
prt_build_and_upload:
runs-on: ubuntu-latest
steps:
- name: Checking out PR code
uses: actions/checkout@v4
if: ${{ github.event_name == 'pull_request_target' }}
with:
# This is to get the PR code instead of the repo code
ref: ${{ github.event.pull_request.head.sha }}
- name: Building ...
run: |
mkdir ./bin
touch ./bin/mybin.exe
# Save some PR info for later use by the 2nd pipeline
echo "${{github.event.pull_request.title}}" > ./bin/PR_TITLE.txt
echo "${{github.event.number}}" > ./bin/PR_ID.txt
# Upload the binary as a pipeline artifact
- name: Archive building artifacts
uses: actions/upload-artifact@v3
with:
name: archive-bin
path: |
bin
2nd pipeline (តេស្ត CI):
ame: Test CI
on:
workflow_run:
workflows: [ 'PR TARGET CI' ]
types: [completed]
env:
MY_SECRET: ${{ secrets.MY_SECRET }}
GITHUB_PAT: ${{ secrets.GH_PAT }}
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
# By default, checks out base code (not PR code)
- name: Checkout repository
uses: actions/checkout@v4
# Download the artifact
- name: 'Download artifact'
uses: actions/github-script@v6
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "archive-bin"
})[0];
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/myartifact.zip`, Buffer.from(download.data));
# Unzip the artifact
- name: 'Unzip artifact'
run: |
unzip -o myartifact.zip
# Runs tests
- name: Running tests ...
id : run_tests
run: |
echo Running tests..
chmod +x runtests.sh
./runtests.sh
echo Tests executed.
#
# Let’s omit the check conditions at this moment …
#
- name: pr_check_conditions_to_merge
[...]
អីយ៉ា… ដំណោះស្រាយល្អណាស់!! ប៉ុន្តែ ….. តើយើងមានសុវត្ថិភាពទេ? ខ្ញុំខ្លាចថាទេ 😭
ជាការពិតណាស់ យើងបានណែនាំចំណុចខ្សោយថ្មីមួយ!! មួយណា? នេះនឹងជាប្រធានបទនៃការបង្ហោះបន្ទាប់របស់យើង 🙂 … សូមតាមដាន!!
PS: សូមអភ័យទោស ខ្ញុំមិនអាចនៅស្ងៀមបានទេ🤐 ..តើអ្នកធ្លាប់ឮអំពី ការពុលវត្ថុបុរាណ ? 😂







