From 52ce4eac120c1476c3054e4db0fbf940d6944ba8 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 22 Nov 2023 11:45:38 -0500 Subject: [PATCH 1/5] Remove remaining references of stable Fixes #1964 --- doc/md/Docker.md | 1 - doc/md/Upgrade-and-migration.md | 11 +++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/doc/md/Docker.md b/doc/md/Docker.md index 69c62897c..0be56023e 100644 --- a/doc/md/Docker.md +++ b/doc/md/Docker.md @@ -44,7 +44,6 @@ Shaarli images are available on [GitHub Container Registry](https://github.com/s - `latest`: master (development) branch - `vX.Y.Z`: shaarli [releases](https://github.com/shaarli/Shaarli/releases) - `release`: always points to the last release -- `stable` and `master`: **deprecated**. These tags are no longer maintained and may be removed without notice These images are built automatically on Github Actions and rely on: diff --git a/doc/md/Upgrade-and-migration.md b/doc/md/Upgrade-and-migration.md index 2f14baf97..5090b6b84 100644 --- a/doc/md/Upgrade-and-migration.md +++ b/doc/md/Upgrade-and-migration.md @@ -127,22 +127,21 @@ Receiving objects: 100% (3015/3015), 2.59 MiB | 918.00 KiB/s, done. Resolving deltas: 100% (1899/1899), completed with 48 local objects. From https://github.com/shaarli/Shaarli * [new branch] master -> origin/master - * [new branch] stable -> origin/stable [...] * [new tag] v0.6.4 -> v0.6.4 * [new tag] v0.7.0 -> v0.7.0 ``` -### Step 2: use the stable community branch +### Step 2: use the release community branch ```bash -$ git checkout origin/stable -b stable -Branch stable set up to track remote branch stable from origin. -Switched to a new branch 'stable' +$ git checkout origin/release -b release +Branch release set up to track remote branch release from origin. +Switched to a new branch 'release' $ git branch -vv master 029f75f [sebsauvage/master] Update README.md -* stable 890afc3 [origin/stable] Merge pull request #509 from ArthurHoaro/v0.6.5 +* release 890afc3 [origin/release] Merge tag 'v0.13.0' into release ``` Shaarli >= `v0.8.x`: install/update third-party PHP dependencies using [Composer](https://getcomposer.org/): From e7492c61016b4f64dc470571447d94e4b5b5cbc6 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 25 Nov 2023 11:24:29 -0500 Subject: [PATCH 2/5] PHP 8.x intl incompatibility: failback C locale with en_US (#2044) --- application/Utils.php | 22 ++++++++++++++- .../controller/visitor/FeedController.php | 2 +- application/http/HttpUtils.php | 2 +- index.php | 2 +- tests/languages/de/UtilsDeTest.php | 28 +++++++++---------- tests/languages/en/UtilsEnTest.php | 28 +++++++++---------- tests/languages/fr/UtilsFrTest.php | 28 +++++++++---------- 7 files changed, 66 insertions(+), 46 deletions(-) diff --git a/application/Utils.php b/application/Utils.php index 48d474155..4d284ccbc 100644 --- a/application/Utils.php +++ b/application/Utils.php @@ -322,7 +322,7 @@ function format_date($date, $time = true, $intl = true) return $date->format($format); } $formatter = new IntlDateFormatter( - setlocale(LC_TIME, 0), + get_locale(LC_TIME), IntlDateFormatter::LONG, $time ? IntlDateFormatter::LONG : IntlDateFormatter::NONE ); @@ -503,3 +503,23 @@ function exception2text(Throwable $e): string { return $e->getMessage() . PHP_EOL . $e->getFile() . $e->getLine() . PHP_EOL . $e->getTraceAsString(); } + +/** + * Get the current locale, overrides 'C' locale which is no longer compatible with PHP-intl + * + * @param int $category Category of the locale (LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_ALL) + * + * @return string|false The locale, or false if not found. + * + * @see https://github.com/php/php-src/issues/12561 + */ +function get_locale(int $category = LC_CTYPE) +{ + $locale = setlocale($category, 0); + + if ($locale === 'C' || startsWith($locale, 'C.')) { + $locale = 'en_US.utf8'; // failback + } + + return $locale; +} diff --git a/application/front/controller/visitor/FeedController.php b/application/front/controller/visitor/FeedController.php index edc7ef43a..5f9ea1c07 100644 --- a/application/front/controller/visitor/FeedController.php +++ b/application/front/controller/visitor/FeedController.php @@ -38,7 +38,7 @@ protected function processRequest(string $feedType, Request $request, Response $ } // Generate data. - $this->container->feedBuilder->setLocale(strtolower(setlocale(LC_COLLATE, 0))); + $this->container->feedBuilder->setLocale(strtolower(get_locale(LC_COLLATE))); $this->container->feedBuilder->setHideDates($this->container->conf->get('privacy.hide_timestamps', false)); $this->container->feedBuilder->setUsePermalinks( null !== $request->getParam('permalinks') || !$this->container->conf->get('feed.rss_permalinks') diff --git a/application/http/HttpUtils.php b/application/http/HttpUtils.php index 4bde1d5b8..a63b1fb45 100644 --- a/application/http/HttpUtils.php +++ b/application/http/HttpUtils.php @@ -55,7 +55,7 @@ function get_http_response( 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0)' . ' Gecko/20100101 Firefox/45.0'; $acceptLanguage = - substr(setlocale(LC_COLLATE, 0), 0, 2) . ',en-US;q=0.7,en;q=0.3'; + substr(get_locale(LC_COLLATE), 0, 2) . ',en-US;q=0.7,en;q=0.3'; $maxRedirs = 3; if (!function_exists('curl_init')) { diff --git a/index.php b/index.php index 2a0246b7b..cd5170457 100644 --- a/index.php +++ b/index.php @@ -81,7 +81,7 @@ autoLocale($_SERVER['HTTP_ACCEPT_LANGUAGE']); } -new Languages(setlocale(LC_MESSAGES, 0), $conf); +new Languages(get_locale(LC_MESSAGES), $conf); $conf->setEmpty('general.timezone', date_default_timezone_get()); $conf->setEmpty('general.title', t('Shared bookmarks on ') . escape(index_url($_SERVER))); diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php index d7a16eaca..014320d18 100644 --- a/tests/languages/de/UtilsDeTest.php +++ b/tests/languages/de/UtilsDeTest.php @@ -20,7 +20,7 @@ public function testIntlDateFormatter() */ public function testDateFormat() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('de-de'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2\. Januar 2017 (um )?20:11:12 GMT\+0?3(:00)?/', format_date($date, true, true)); @@ -32,7 +32,7 @@ public function testDateFormat() */ public function testDateFormatNoTime() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('de-de'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2\. Januar 2017/', format_date($date, false, true)); @@ -62,10 +62,10 @@ public function testDateFormatDefaultNoTime() */ public function testAutoLocaleValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'en-us'; autoLocale($header); - $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -75,10 +75,10 @@ public function testAutoLocaleValid() */ public function testAutoLocaleValidAlternative() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'en_US.UTF-8'; autoLocale($header); - $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -88,10 +88,10 @@ public function testAutoLocaleValidAlternative() */ public function testAutoLocaleMultipleFirstValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'en-us,de-de'; autoLocale($header); - $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -101,10 +101,10 @@ public function testAutoLocaleMultipleFirstValid() */ public function testAutoLocaleMultipleSecondAvailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'mgg_IN,fr-fr'; autoLocale($header); - $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('fr_FR.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -114,9 +114,9 @@ public function testAutoLocaleMultipleSecondAvailable() */ public function testAutoLocaleBlank() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale(''); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -126,9 +126,9 @@ public function testAutoLocaleBlank() */ public function testAutoLocaleUnavailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('mgg_IN'); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } diff --git a/tests/languages/en/UtilsEnTest.php b/tests/languages/en/UtilsEnTest.php index f1e21b9a3..ee2b96fb0 100644 --- a/tests/languages/en/UtilsEnTest.php +++ b/tests/languages/en/UtilsEnTest.php @@ -20,7 +20,7 @@ public function testIntlDateFormatter() */ public function testDateFormat() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('en_US.UTF-8'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/January 2, 2017 (at )?8:11:12 PM GMT\+0?3(:00)?/', format_date($date, true, true)); @@ -32,7 +32,7 @@ public function testDateFormat() */ public function testDateFormatNoTime() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('en_US.UTF-8'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/January 2, 2017/', format_date($date, false, true)); @@ -62,10 +62,10 @@ public function testDateFormatDefaultNoTime() */ public function testAutoLocaleValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -75,10 +75,10 @@ public function testAutoLocaleValid() */ public function testAutoLocaleValidAlternative() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de_de.UTF8'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -88,10 +88,10 @@ public function testAutoLocaleValidAlternative() */ public function testAutoLocaleMultipleFirstValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de;en-us'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -101,10 +101,10 @@ public function testAutoLocaleMultipleFirstValid() */ public function testAutoLocaleMultipleSecondAvailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'mgg_IN,fr-fr'; autoLocale($header); - $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('fr_FR.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -114,9 +114,9 @@ public function testAutoLocaleMultipleSecondAvailable() */ public function testAutoLocaleBlank() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale(''); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -126,9 +126,9 @@ public function testAutoLocaleBlank() */ public function testAutoLocaleUnavailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('mgg_IN'); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } diff --git a/tests/languages/fr/UtilsFrTest.php b/tests/languages/fr/UtilsFrTest.php index 799fa5c96..a6ae0e4b1 100644 --- a/tests/languages/fr/UtilsFrTest.php +++ b/tests/languages/fr/UtilsFrTest.php @@ -20,7 +20,7 @@ public function testIntlDateFormatter() */ public function testDateFormat() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('fr-fr'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2 janvier 2017 (à )?20:11:12 UTC\+0?3(:00)?/', format_date($date)); @@ -32,7 +32,7 @@ public function testDateFormat() */ public function testDateFormatNoTime() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('fr-fr'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2 janvier 2017/', format_date($date, false, true)); @@ -62,10 +62,10 @@ public function testDateFormatDefaultNoTime() */ public function testAutoLocaleValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -75,10 +75,10 @@ public function testAutoLocaleValid() */ public function testAutoLocaleValidAlternative() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de_de.UTF8'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -88,10 +88,10 @@ public function testAutoLocaleValidAlternative() */ public function testAutoLocaleMultipleFirstValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de;en-us'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -101,10 +101,10 @@ public function testAutoLocaleMultipleFirstValid() */ public function testAutoLocaleMultipleSecondAvailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'mgg_IN,de-de'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -114,9 +114,9 @@ public function testAutoLocaleMultipleSecondAvailable() */ public function testAutoLocaleBlank() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale(''); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -126,9 +126,9 @@ public function testAutoLocaleBlank() */ public function testAutoLocaleUnavailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('mgg_IN'); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } From eda9e2e10f9ff8d5f2eb6f2957b02298ad37e267 Mon Sep 17 00:00:00 2001 From: nodiscc Date: Sun, 27 Aug 2023 13:00:15 +0200 Subject: [PATCH 3/5] github actions: run daily trivy security scans on release docker image, composer/yarn dependencies - add badge to README - any time a new vulnerability is found by this workflow, means it is probably time to update Shaarli's base docker image and perform a new release, and/or update npm dependencies (npm audit fix) or composer dependencies (composer update) - similar jobs already exist in the pipeline for master/latest docker image but will not raise an error - fixes https://github.com/shaarli/Shaarli/issues/1531 --- .github/workflows/trivy-release.yml | 25 +++++++++++++++++++++++++ Makefile | 6 ++++++ README.md | 1 + 3 files changed, 32 insertions(+) create mode 100644 .github/workflows/trivy-release.yml diff --git a/.github/workflows/trivy-release.yml b/.github/workflows/trivy-release.yml new file mode 100644 index 000000000..8981cea79 --- /dev/null +++ b/.github/workflows/trivy-release.yml @@ -0,0 +1,25 @@ +name: trivy security scans (release) +on: + schedule: + - cron: '0 17 * * *' + workflow_dispatch: + +jobs: + trivy-repo: + runs-on: ubuntu-latest + name: trivy scan (release composer/yarn dependencies) + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Run trivy scanner on repository + run: make test_trivy_repo TRIVY_TARGET_BRANCH=origin/release TRIVY_EXIT_CODE=1 + trivy-docker: + runs-on: ubuntu-latest + name: trivy scan (release docker image) + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Run trivy scanner on release docker image + run: make test_trivy_docker TRIVY_TARGET_DOCKER_IMAGE=ghcr.io/shaarli/shaarli:release diff --git a/Makefile b/Makefile index 8f8d335b3..487241578 100644 --- a/Makefile +++ b/Makefile @@ -199,6 +199,8 @@ TRIVY_VERSION=0.44.0 TRIVY_EXIT_CODE=1 # default docker image to scan with trivy TRIVY_TARGET_DOCKER_IMAGE=ghcr.io/shaarli/shaarli:latest +# branch on which test_trivy_repo should be run. leave undefined for the current branch +#TRIVY_TARGET_BRANCH=origin/release ### download trivy vulneravbility scanner download_trivy: @@ -211,5 +213,9 @@ test_trivy_docker: download_trivy ### run trivy vulnerability scanner on composer/yarn dependency trees test_trivy_repo: download_trivy +ifdef TRIVY_TARGET_BRANCH + git checkout $(TRIVY_TARGET_BRANCH) composer.lock + git checkout $(TRIVY_TARGET_BRANCH) yarn.lock +endif ./trivy --exit-code $(TRIVY_EXIT_CODE) fs composer.lock ./trivy --exit-code $(TRIVY_EXIT_CODE) fs yarn.lock diff --git a/README.md b/README.md index 348868d8a..8dc5fc515 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ _It is designed to be personal (single-user), fast and handy._ [![](https://img.shields.io/badge/release-v0.13.0-blue.svg)](https://github.com/shaarli/Shaarli/releases/tag/v0.13.0) [![](https://img.shields.io/badge/master-v0.13.x-blue.svg)](https://github.com/shaarli/Shaarli) [![](https://github.com/shaarli/Shaarli/actions/workflows/ci.yml/badge.svg)](https://github.com/shaarli/Shaarli/actions) +[![](https://github.com/shaarli/Shaarli/actions/workflows/trivy-release.yml/badge.svg)](https://github.com/shaarli/Shaarli/actions) [![Join the chat at https://gitter.im/shaarli/Shaarli](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/shaarli/Shaarli) [![Docker repository](https://img.shields.io/docker/pulls/shaarli/shaarli.svg)](https://github.com/shaarli/Shaarli/pkgs/container/shaarli) From 52f232b57e02a1fa7849f93b349282e429e1767b Mon Sep 17 00:00:00 2001 From: nodiscc Date: Sun, 3 Dec 2023 14:29:09 +0100 Subject: [PATCH 4/5] tools: github actions: don't mark latest docker image build as failed when trivy detects vulnerabilities --- .github/workflows/docker-latest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-latest.yml b/.github/workflows/docker-latest.yml index ad885b6a4..76f797063 100644 --- a/.github/workflows/docker-latest.yml +++ b/.github/workflows/docker-latest.yml @@ -42,4 +42,4 @@ jobs: - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} - name: Run trivy scanner on latest docker image - run: make test_trivy_docker TRIVY_TARGET_DOCKER_IMAGE=ghcr.io/${{ secrets.DOCKER_IMAGE }}:latest + run: make test_trivy_docker TRIVY_EXIT_CODE=0 TRIVY_TARGET_DOCKER_IMAGE=ghcr.io/${{ secrets.DOCKER_IMAGE }}:latest From 7287d7b875ae69a2dda548ab4e00db6f34c97976 Mon Sep 17 00:00:00 2001 From: nodiscc Date: Sun, 3 Dec 2023 16:22:26 +0100 Subject: [PATCH 5/5] docker: update base alpine linux docker image to v3.16.8 - https://alpinelinux.org/posts/Alpine-3.15.11-3.16.8-3.17.6-3.18.5-released.html --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8e995a6ad..da3ce7c15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ RUN cd shaarli \ # Stage 4: # - Shaarli image -FROM alpine:3.16.7 +FROM alpine:3.16.8 LABEL maintainer="Shaarli Community" RUN apk --update --no-cache add \