@@ -550,6 +550,28 @@ get_semver_patch() {
550
550
fi
551
551
}
552
552
553
+ # Generates the markdown anchor corresponding to the given title taking
554
+ # markdown flavors into account.
555
+ # Expected args:
556
+ # 1. the section title
557
+ # 2. the markdown flavor (github, gitlab, ...)
558
+ normalize_markdown_anchor () {
559
+ local SECTION_TITLE=" $1 "
560
+ local MARKDOWN_FLAVOR=" $2 "
561
+
562
+ case " $MARKDOWN_FLAVOR " in
563
+ github)
564
+ echo " $SECTION_TITLE " | tr ' /' ' -'
565
+ ;;
566
+ gitlab)
567
+ echo " $SECTION_TITLE " | tr -d ' /'
568
+ ;;
569
+ * )
570
+ echo " $SECTION_TITLE "
571
+ ;;
572
+ esac
573
+ }
574
+
553
575
# ## Git
554
576
# ##
555
577
@@ -1623,10 +1645,19 @@ build_docs () {
1623
1645
end_group " Building docs for $REPOSITORY ..."
1624
1646
}
1625
1647
1626
- # Build e2e tests
1648
+ # ## e2e tests
1649
+ # ##
1650
+
1651
+ # Build the e2e tests container
1627
1652
# Expected arguments
1628
- # 1. Root directory
1629
- # 2: true to publish result on harbor
1653
+ # 1. the app root directory
1654
+ # 2. the subdomain where the app is deployed
1655
+ # 3: true to publish built container on a registry
1656
+ # 4. the registry url, eg. "docker.io"
1657
+ # 5. the username to login the registry
1658
+ # 6. a file where the password is stored in cleartext
1659
+ # 7. the name to give to the built container image
1660
+ # 8. the tag to give to the built container image
1630
1661
build_e2e_tests () {
1631
1662
local ROOT_DIR=" $1 "
1632
1663
local SUBDOMAIN=" $2 "
@@ -1649,7 +1680,7 @@ build_e2e_tests () {
1649
1680
local FLAVOR
1650
1681
FLAVOR=$( get_app_flavor)
1651
1682
1652
- begin_group " Building $IMAGE_NAME :$IMAGE_TAG ..."
1683
+ begin_group " Building $REGISTRY_URL / $ IMAGE_NAME :$IMAGE_TAG ..."
1653
1684
1654
1685
docker login --username " $REGISTRY_USERNAME " --password-stdin " $REGISTRY_URL " < " $REGISTRY_PASSWORD_FILE "
1655
1686
# DOCKER_BUILDKIT is here to be able to use Dockerfile specific dockerginore (e2e-tests.Dockerfile.dockerignore)
@@ -1669,53 +1700,244 @@ build_e2e_tests () {
1669
1700
1670
1701
docker logout " $REGISTRY_URL "
1671
1702
1672
- end_group " Building $IMAGE_NAME :$IMAGE_TAG ..."
1703
+ end_group " Building $REGISTRY_URL / $ IMAGE_NAME :$IMAGE_TAG ..."
1673
1704
}
1674
1705
1675
1706
# Run e2e tests
1676
- # Specific error handling: set -uo pipefail to bypass errors
1677
1707
# Expected arguments
1678
- # 1. Root directory
1708
+ # 1. the app root directory
1679
1709
# 2: the app name
1680
- # 3: the slack webhook apps
1681
1710
run_e2e_tests () {
1682
1711
local ROOT_DIR=" $1 "
1683
1712
local APP=" $2 "
1684
- local SLACK_WEBHOOK_APPS=" $3 "
1685
-
1686
- # # Run tests & redirect output to a log file
1687
- # #
1713
+ local TESTS_RESULTS=" $ROOT_DIR /test/run/chrome"
1688
1714
1689
1715
# Chrome
1690
- mkdir -p " $ROOT_DIR /test/run/chrome"
1691
- yarn test:client > " $ROOT_DIR /test/run/chrome/chrome_logs.txt" 2>&1
1692
- local RET_CODE=$?
1716
+ mkdir -p " $TESTS_RESULTS "
1717
+ yarn test:client 2>&1 | tee " $TESTS_RESULTS /chrome_logs.txt"
1693
1718
1694
1719
# Firefox
1695
1720
# PUPPETEER_PRODUCT=firefox yarn add puppeteer
1696
1721
# yarn link "@kalisio/kdk" --link-folder /opt/kalisio/yarn-links
1697
1722
# export BROWSER="firefox"bucket
1698
1723
# mkdir -p "$ROOT_DIR/test/run/firefox"
1699
- # yarn test:client > "$ROOT_DIR/test/run/chrome/firefox_logs.txt" 2>&1
1724
+ return $? # return the exit code of the tests
1725
+ }
1700
1726
1701
- # # Upload logs & screenshots to S3
1702
- # #
1727
+ # Upload e2e tests artefacts to some s3 storage.
1728
+ # Expected args:
1729
+ # 1. the app root dir
1730
+ # 2. the app name
1731
+ # 3. the s3 bucket where to upload artefacts (with a rclone remote, like ovh:e2e-test/blabla)
1732
+ # 4. the rclone.conf file to use to upload artefacts
1733
+ # 5. the file where the upload report will be written (json)
1734
+ upload_e2e_tests_artefacts () {
1735
+ local ROOT_DIR=" $1 "
1736
+ local APP=" $2 "
1737
+ local S3_BUCKET=" $3 "
1738
+ local RCLONE_CONF=" $4 "
1739
+ local UPLOAD_REPORT_FILE=" $5 "
1740
+
1741
+ local TIMESTAMP
1742
+ TIMESTAMP=" $( date +" %d-%m-%Y" ) "
1743
+ local TESTS_RESULTS_DIR=" $ROOT_DIR /test/run/chrome"
1744
+ local WORK_DIR=" $TMP_DIR /artefacts/$APP /$TIMESTAMP /e2e"
1745
+ local REMOTE_DIR=" $S3_BUCKET /$APP /$TIMESTAMP /e2e"
1746
+
1747
+ mkdir -p " $WORK_DIR "
1748
+
1749
+ # zip the whole tests results folder
1750
+ local ZIP_FILE=" $WORK_DIR /e2e-artefacts.zip"
1751
+ cd " $TESTS_RESULTS_DIR "
1752
+ zip -r " $ZIP_FILE " .
1753
+ cd ~ -
1703
1754
1704
- local CURRENT_DATE
1705
- CURRENT_DATE=$( date +" %d-%m-%Y" )
1706
- local CHROME_LOGS_LINK=" "
1707
- local SCREEN_LINK=" "
1755
+ # keep log file as is
1756
+ cp " $TESTS_RESULTS_DIR /logs.txt" " $WORK_DIR /logs.txt"
1708
1757
1709
- zip -r " $TMP_DIR /screenshots.zip" " $ROOT_DIR /test/run"
1758
+ # and keep captures and diffs for failed tests
1759
+ local FAILED_TESTS=()
1760
+ readarray -d ' ' DIFF_FILES < <( find " $TESTS_RESULTS_DIR " -type f -name ' diff.*.png' -print0)
1761
+ for DIFF_FILE in " ${DIFF_FILES[@]} " ; do
1762
+ local BASE_DIFF_FILE
1763
+ BASE_DIFF_FILE=" $( basename " $DIFF_FILE " ) "
1764
+ local BASE_CAPTURE_FILE=" ${BASE_DIFF_FILE# diff.* } "
1765
+ local CAPTURE_FILE
1766
+ CAPTURE_FILE=" $( dirname " $DIFF_FILE " ) /$BASE_CAPTURE_FILE "
1710
1767
1711
- rclone copy " $ROOT_DIR /test/run/chrome/chrome_logs.txt" " ovh-s3:/dev/e2e-tests/$APP /$CURRENT_DATE "
1712
- CHROME_LOGS_LINK=$( rclone link " ovh-s3:/dev/e2e-tests/$APP /$CURRENT_DATE /chrome_logs.txt" )
1768
+ local TEST_DIR
1769
+ TEST_DIR=" $( realpath -s --relative-to=" $TESTS_RESULTS_DIR " " $DIFF_FILE " ) "
1770
+ TEST_DIR=" $( dirname " $TEST_DIR " ) "
1771
+ TEST_DIR=" $( dirname " $TEST_DIR " ) "
1713
1772
1714
- rclone copy " $TMP_DIR /screenshots.zip " " ovh-s3:/dev/e2e-tests/ $APP / $CURRENT_DATE "
1715
- SCREEN_LINK= $( rclone link " ovh-s3:/dev/e2e-tests/ $APP / $CURRENT_DATE /screenshots.zip " )
1773
+ local TEST_NAME
1774
+ TEST_NAME= " $TEST_DIR / ${BASE_CAPTURE_FILE % . * } "
1716
1775
1717
- # # Report outcome to slack
1718
- # #
1776
+ FAILED_TESTS+=(" $TEST_NAME " )
1777
+
1778
+ mkdir -p " $WORK_DIR /$TEST_DIR "
1779
+ cp " $DIFF_FILE " " $WORK_DIR /$TEST_DIR "
1780
+ cp " $CAPTURE_FILE " " $WORK_DIR /$TEST_DIR "
1781
+ done
1782
+
1783
+ rclone --config " $RCLONE_CONF " copy " $TMP_DIR /artefacts" " $S3_BUCKET "
1784
+
1785
+ rm -fR " $WORK_DIR "
1786
+
1787
+ # now generate public http links
1788
+ local ARTEFACTS_LINK
1789
+ ARTEFACTS_LINK=" $( rclone --config " $RCLONE_CONF " link " $REMOTE_DIR /e2e-artefacts.zip" ) "
1790
+ local LOGS_LINK
1791
+ LOGS_LINK=" $( rclone --config " $RCLONE_CONF " link " $REMOTE_DIR /logs.txt" ) "
1792
+
1793
+ printf ' { "app": "%s", "timestamp": "%s", "artefacts": "%s", "logs": "%s", "num_failed": "%d", "failed": [' " $APP " " $TIMESTAMP " " $ARTEFACTS_LINK " " $LOGS_LINK " " ${# FAILED_TESTS[@]} " > " $UPLOAD_REPORT_FILE "
1794
+
1795
+ local COMMA=" "
1796
+ for TEST_NAME in " ${FAILED_TESTS[@]} " ; do
1797
+ local CAPTURE_LINK
1798
+ CAPTURE_LINK=" $( rclone --config " $RCLONE_CONF " link " $REMOTE_DIR /$TEST_NAME .png" ) "
1799
+ local DIFF_FILE
1800
+ DIFF_FILE=" $( dirname " $TEST_NAME " ) /diff.$( basename " $TEST_NAME " ) .png"
1801
+ local DIFF_LINK
1802
+ DIFF_LINK=" $( rclone --config " $RCLONE_CONF " link " $REMOTE_DIR /$DIFF_FILE " ) "
1803
+ printf ' %s { "name": "%s", "capture": "%s", "diff": "%s" }' " $COMMA " " $TEST_NAME " " $CAPTURE_LINK " " $DIFF_LINK " >> " $UPLOAD_REPORT_FILE "
1804
+ COMMA=" ,"
1805
+ done
1806
+
1807
+ printf " ] }" >> " $UPLOAD_REPORT_FILE "
1808
+ }
1809
+
1810
+ # Generates a markdown report file from the upload report file
1811
+ # generated by the upload_e2e_tests_artefacts function.
1812
+ # Expected args:
1813
+ # 1. the same upload report file used in upload_e2e_tests_artefacts
1814
+ # 2. the file where to write the markdown report
1815
+ # 3. the flavor to use for the markdown (see normalize_markdown_anchor)
1816
+ generate_e2e_tests_markdown_report () {
1817
+ local UPLOAD_REPORT_FILE=" $1 "
1818
+ local MD_REPORT_FILE=" $2 "
1819
+ local MD_FLAVOR=" $3 "
1820
+
1821
+ local APP
1822
+ APP=$( get_json_value " $UPLOAD_REPORT_FILE " " app" )
1823
+ local TIMESTAMP
1824
+ TIMESTAMP=$( get_json_value " $UPLOAD_REPORT_FILE " " timestamp" )
1825
+ local ARTEFACTS_LINK
1826
+ ARTEFACTS_LINK=$( get_json_value " $UPLOAD_REPORT_FILE " " artefacts" )
1827
+ local LOGS_LINK
1828
+ LOGS_LINK=$( get_json_value " $UPLOAD_REPORT_FILE " " logs" )
1829
+ local NUM_FAILED
1830
+ NUM_FAILED=$( get_json_value " $UPLOAD_REPORT_FILE " " num_failed" )
1831
+
1832
+ printf " # [%s] (e2e run from %s)\n\n" " $( echo " $APP " | tr ' [:lower:]' ' [:upper:]' ) " " $TIMESTAMP " > " $MD_REPORT_FILE "
1833
+ printf " [All artefacts](%s), [logs](%s)\n\n" " $ARTEFACTS_LINK " " $LOGS_LINK " >> " $MD_REPORT_FILE "
1834
+
1835
+ if (( NUM_FAILED == 0 )) ; then
1836
+ printf " > [!TIP]\n> All tests have passed\n" >> " $MD_REPORT_FILE "
1837
+ else
1838
+ printf " > [!CAUTION]\n> **%d** tests have failed\n" " $NUM_FAILED " >> " $MD_REPORT_FILE "
1839
+
1840
+ local SECTIONS=()
1841
+ for (( i = 0 ; i < NUM_FAILED; ++ i )) ; do
1842
+ local TEST_NAME
1843
+ TEST_NAME=$( get_json_value " $UPLOAD_REPORT_FILE " " failed[$i ].name" )
1844
+ printf " > - [%s](#%s)\n" " $TEST_NAME " " $( normalize_markdown_anchor " $TEST_NAME " " $MD_FLAVOR " ) " >> " $MD_REPORT_FILE "
1719
1845
1720
- slack_e2e_report " $APP " " $RET_CODE " " $SLACK_WEBHOOK_APPS " " $CHROME_LOGS_LINK " " $SCREEN_LINK "
1846
+ local CAPTURE_LINK
1847
+ CAPTURE_LINK=$( get_json_value " $UPLOAD_REPORT_FILE " " failed[$i ].capture" )
1848
+ local DIFF_LINK
1849
+ DIFF_LINK=$( get_json_value " $UPLOAD_REPORT_FILE " " failed[$i ].diff" )
1850
+
1851
+ read -r -d ' ' SECTION << EOF
1852
+ ## $TEST_NAME
1853
+ Captured file | Diff file
1854
+ --------------|----------
1855
+  | 
1856
+
1857
+ EOF
1858
+
1859
+ SECTIONS+=(" $SECTION " )
1860
+ done
1861
+
1862
+ printf " \n" >> " $MD_REPORT_FILE "
1863
+
1864
+ for SECTION in " ${SECTIONS[@]} " ; do
1865
+ printf " %s\n" " $SECTION " >> " $MD_REPORT_FILE "
1866
+ done
1867
+ fi
1868
+ }
1869
+
1870
+ # Add and commit the e2e tests report in a git repository.
1871
+ # Expected args:
1872
+ # 1. the same upload report file as upload_e2e_tests_artefacts
1873
+ # 2. the report file to add to the repo
1874
+ # 3. the repository url to use to clone and push (must be able to push!)
1875
+ # 4. a folder in which the report will be moved
1876
+ push_e2e_tests_report_to_git_repo () {
1877
+ local UPLOAD_FILE=" $1 "
1878
+ local REPORT_FILE=" $2 "
1879
+ local REPOSITORY_URL=" $3 "
1880
+ local REPORTS_BASE=" $4 "
1881
+
1882
+ local APP
1883
+ APP=$( get_json_value " $UPLOAD_FILE " " app" )
1884
+ local TIMESTAMP
1885
+ TIMESTAMP=$( get_json_value " $UPLOAD_FILE " " timestamp" )
1886
+
1887
+ local WORK_DIR
1888
+ WORK_DIR=" $( mktemp -d -p " $TMP_DIR " push.XXXXXX) "
1889
+
1890
+ # Clone repo to a temp location
1891
+ git clone --depth 1 " $REPOSITORY_URL " " $WORK_DIR "
1892
+ # Copy report
1893
+ local REPORT_DIR=" $WORK_DIR "
1894
+ [[ " $REPORTS_BASE " != " " ]] && REPORT_DIR=" $REPORT_DIR /$REPORTS_BASE "
1895
+ REPORT_DIR=" $REPORT_DIR /$APP /$TIMESTAMP "
1896
+ mkdir -p " $REPORT_DIR "
1897
+
1898
+ cp " $REPORT_FILE " " $REPORT_DIR "
1899
+ cd " $WORK_DIR "
1900
+ git add --all
1901
+ git -c user.name=
" CI bot" -c user.email=
" [email protected] " commit --message
" ci: e2e tests report from $TIMESTAMP "
1902
+ git push origin
1903
+ cd ~ -
1904
+
1905
+ rm -fR " $WORK_DIR "
1906
+ }
1907
+
1908
+ # Take all steps to run e2e test and push results to a git repository. Binary artefacts
1909
+ # are uploaded on an s3 bucket.
1910
+ # Expected args:
1911
+ # 1. the app root dir
1912
+ # 2. the app name
1913
+ # 3. the s3 bucket where to upload binary artefacts
1914
+ # 4. the rclone.conf file to use with rclone
1915
+ # 5. the git repository url where we'll push the final report (must be able to push!)
1916
+ # 6. a folder in which the report will be moved
1917
+ run_and_publish_e2e_tests_to_git_repo () {
1918
+ local ROOT_DIR=" $1 "
1919
+ local APP=" $2 "
1920
+ local S3_BUCKET=" $3 "
1921
+ local RCLONE_CONF=" $4 "
1922
+ local REPOSITORY_URL=" $5 "
1923
+ local REPORTS_BASE=" $6 "
1924
+
1925
+ run_e2e_tests " $ROOT_DIR " " $APP "
1926
+
1927
+ local MD_FLAVOR
1928
+ [[ " $REPOSITORY_URL " = * gitlab* ]] && MD_FLAVOR=" gitlab"
1929
+ [[ " $REPOSITORY_URL " = * github* ]] && MD_FLAVOR=" github"
1930
+
1931
+ local UPLOAD_REPORT_FILE=" $TMP_DIR /e2e-upload-report.json"
1932
+ local MD_REPORT_FILE=" $TMP_DIR /e2e.md"
1933
+
1934
+ upload_e2e_tests_artefacts \
1935
+ " $ROOT_DIR " " $APP " \
1936
+ " $S3_BUCKET " " $RCLONE_CONF " \
1937
+ " $UPLOAD_REPORT_FILE "
1938
+ generate_e2e_tests_markdown_report \
1939
+ " $UPLOAD_REPORT_FILE " " $MD_REPORT_FILE " " $MD_FLAVOR "
1940
+ push_e2e_tests_report_to_git_repo \
1941
+ " $UPLOAD_REPORT_FILE " " $MD_REPORT_FILE " \
1942
+ " $REPOSITORY_URL " " $REPORTS_BASE "
1721
1943
}
0 commit comments