From d20dd3c059c5803a8f88f99a47ffb06d16bf6629 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Mon, 1 Jun 2026 15:02:14 +0300 Subject: [PATCH 01/10] GHA: add locale-specific checks --- .github/workflows/R-CMD-check.yaml | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 80ea70ed73..9f252f1874 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -71,3 +71,54 @@ jobs: - uses: yihui/actions/check-r-package@HEAD with: check-args: "--no-manual --as-cran" + + R-CMD-check-locale: + runs-on: ${{ matrix.os }} + + name: ${{ matrix.os }}, R-${{ matrix.r }}, LC_CTYPE=${{ matrix.locale }} + + strategy: + fail-fast: true + matrix: + os: [ubuntu-22.04] + r: ['release'] + locale: ['fr_CA.ISO-8859-1', 'zh_CN.GB18030', 'ru_RU.KOI8-R'] + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + _R_CHECK_RD_CHECKRD_MINLEVEL_: -Inf + _R_CHECK_RD_CONTENTS_VALUE_: 1 + + steps: + - uses: actions/checkout@v6 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.r }} + + - name: Configure locale + run: | + echo ${{ matrix.locale }} `echo ${{ matrix.locale }} | sed 's/.*\.//'` | sudo tee -a /etc/locale.gen + sudo locale-gen --keep-existing + + - uses: yihui/actions/setup-r-dependencies@HEAD + + - name: Override R for locale-specific check + run: | + sudo mkdir -p /override + # poor man's luit that doesn't require a tty + sudo tee /override/R < expand backticks, dollars + #!/bin/bash + set -o pipefail + exec stdbuf -o L -e L `which R` "\$@" 2>&1 | while read line; do + echo "\$line" | iconv -t UTF-8 + done + EOF + sudo chmod +x /override/R + echo PATH=/override:$PATH >> $GITHUB_ENV + + - uses: yihui/actions/check-r-package@HEAD + with: + check-args: "--no-manual" + env: + LC_CTYPE: ${{ matrix.locale }} From c2aeadee3b8cd6b36b231907cbf14c4baad704f9 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Sat, 18 Jul 2026 20:12:22 +0300 Subject: [PATCH 02/10] Drop unnecessary environment variables --- .github/workflows/R-CMD-check.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 9f252f1874..13c2779296 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -86,8 +86,6 @@ jobs: env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - _R_CHECK_RD_CHECKRD_MINLEVEL_: -Inf - _R_CHECK_RD_CONTENTS_VALUE_: 1 steps: - uses: actions/checkout@v6 From e5b3b62fe1299c52b09d08f7ac1ff32a2913d785 Mon Sep 17 00:00:00 2001 From: chiricom Date: Wed, 5 Aug 2026 22:28:47 +0000 Subject: [PATCH 03/10] Put encoding configs in R-CMD-check-occasional, enabling them for now --- .github/workflows/R-CMD-check-occasional.yaml | 15 ++++++ .github/workflows/R-CMD-check.yaml | 49 ------------------- 2 files changed, 15 insertions(+), 49 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 7f3dc36d89..8ccf1f6f69 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -1,4 +1,5 @@ on: + push: schedule: - cron: '17 13 23 * *' # 23rd of month at 13:17 UTC workflow_dispatch: @@ -20,6 +21,8 @@ jobs: locale: ['en_US.utf8', # Multibyte characters: Mandarin 'zh_CN.utf8', + # Encoding: non-UTF-8 locales for French, Mandarin, and Russian + 'fr_CA.ISO-8859-1', 'zh_CN.GB18030', 'ru_RU.KOI8-R', # Collate order (#3502, see also #7837): Latvian, Azeri, Hungarian, Faroese, Albanian 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8', # Local time formatting (for R bug #19117) @@ -31,6 +34,12 @@ jobs: # only run non-English locale CI on Ubuntu - os: macOS-latest locale: 'zh_CN.utf8' + - os: macOS-latest + locale: 'fr_CA.ISO-8859-1' + - os: macOS-latest + locale: 'zh_CN.GB18030' + - os: macOS-latest + locale: 'ru_RU.KOI8-R' - os: macOS-latest locale: 'lv_LV.utf8' - os: macOS-latest @@ -45,6 +54,12 @@ jobs: locale: 'vi_VN.utf8' - os: windows-latest locale: 'zh_CN.utf8' + - os: windows-latest + locale: 'fr_CA.ISO-8859-1' + - os: windows-latest + locale: 'zh_CN.GB18030' + - os: windows-latest + locale: 'ru_RU.KOI8-R' - os: windows-latest locale: 'lv_LV.utf8' - os: windows-latest diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 13c2779296..80ea70ed73 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -71,52 +71,3 @@ jobs: - uses: yihui/actions/check-r-package@HEAD with: check-args: "--no-manual --as-cran" - - R-CMD-check-locale: - runs-on: ${{ matrix.os }} - - name: ${{ matrix.os }}, R-${{ matrix.r }}, LC_CTYPE=${{ matrix.locale }} - - strategy: - fail-fast: true - matrix: - os: [ubuntu-22.04] - r: ['release'] - locale: ['fr_CA.ISO-8859-1', 'zh_CN.GB18030', 'ru_RU.KOI8-R'] - - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - - steps: - - uses: actions/checkout@v6 - - - uses: r-lib/actions/setup-r@v2 - with: - r-version: ${{ matrix.r }} - - - name: Configure locale - run: | - echo ${{ matrix.locale }} `echo ${{ matrix.locale }} | sed 's/.*\.//'` | sudo tee -a /etc/locale.gen - sudo locale-gen --keep-existing - - - uses: yihui/actions/setup-r-dependencies@HEAD - - - name: Override R for locale-specific check - run: | - sudo mkdir -p /override - # poor man's luit that doesn't require a tty - sudo tee /override/R < expand backticks, dollars - #!/bin/bash - set -o pipefail - exec stdbuf -o L -e L `which R` "\$@" 2>&1 | while read line; do - echo "\$line" | iconv -t UTF-8 - done - EOF - sudo chmod +x /override/R - echo PATH=/override:$PATH >> $GITHUB_ENV - - - uses: yihui/actions/check-r-package@HEAD - with: - check-args: "--no-manual" - env: - LC_CTYPE: ${{ matrix.locale }} From 0a3723f69e447775b07a5fecf227f8bb8eec91c6 Mon Sep 17 00:00:00 2001 From: chiricom Date: Wed, 5 Aug 2026 23:17:30 +0000 Subject: [PATCH 04/10] leave ISO-8859-1 implicit for fr_CA --- .github/workflows/R-CMD-check-occasional.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 8ccf1f6f69..fd9a1c7109 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -22,7 +22,7 @@ jobs: # Multibyte characters: Mandarin 'zh_CN.utf8', # Encoding: non-UTF-8 locales for French, Mandarin, and Russian - 'fr_CA.ISO-8859-1', 'zh_CN.GB18030', 'ru_RU.KOI8-R', + 'fr_CA', 'zh_CN.GB18030', 'ru_RU.KOI8-R', # fr_CA is implicitly 'ISO-8859-1' # Collate order (#3502, see also #7837): Latvian, Azeri, Hungarian, Faroese, Albanian 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8', # Local time formatting (for R bug #19117) From b46563823adc1d0d245e3feeb636b77b79d2e9e9 Mon Sep 17 00:00:00 2001 From: chiricom Date: Wed, 5 Aug 2026 23:28:55 +0000 Subject: [PATCH 05/10] Gemini: iconv to prevent gibberish in GHA logs --- .github/workflows/R-CMD-check-occasional.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index fd9a1c7109..e2537722c3 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -100,6 +100,18 @@ jobs: with: r-version: ${{ matrix.r }} + - name: Override R for locale-specific check + if: matrix.os == 'ubuntu-latest' && !contains(matrix.locale, 'utf8') + run: | + sudo mkdir -p /override + sudo tee /override/R << 'EOF' + #!/bin/bash + set -o pipefail + exec $(which R) "$@" 2>&1 | iconv -c -t UTF-8 + EOF + sudo chmod +x /override/R + echo "PATH=/override:$PATH" >> $GITHUB_ENV + - name: Set script permissions run: chmod +x configure cleanup 2>/dev/null || true # Silence some GHA Annotations shell: bash From 61293b742443d2f9a7e52d3fecbee9c487cd68a8 Mon Sep 17 00:00:00 2001 From: chiricom Date: Thu, 6 Aug 2026 05:52:35 +0000 Subject: [PATCH 06/10] Gemini: try iconv directly on the 'Check' step --- .github/workflows/R-CMD-check-occasional.yaml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index e2537722c3..d32f48880d 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -100,18 +100,6 @@ jobs: with: r-version: ${{ matrix.r }} - - name: Override R for locale-specific check - if: matrix.os == 'ubuntu-latest' && !contains(matrix.locale, 'utf8') - run: | - sudo mkdir -p /override - sudo tee /override/R << 'EOF' - #!/bin/bash - set -o pipefail - exec $(which R) "$@" 2>&1 | iconv -c -t UTF-8 - EOF - sudo chmod +x /override/R - echo "PATH=/override:$PATH" >> $GITHUB_ENV - - name: Set script permissions run: chmod +x configure cleanup 2>/dev/null || true # Silence some GHA Annotations shell: bash @@ -202,7 +190,7 @@ jobs: stop("R CMD check failed") } } - shell: Rscript {0} + shell: bash -c 'set -o pipefail; Rscript {0} 2>&1 | iconv -c -t UTF-8' - name: Upload check results if: failure() From 2a368926775b2806903d11dd251460328ba5bc50 Mon Sep 17 00:00:00 2001 From: chiricom Date: Thu, 6 Aug 2026 06:30:28 +0000 Subject: [PATCH 07/10] Gemini: back to overwriting R binary, but using R.home() for subprocesses too --- .github/workflows/R-CMD-check-occasional.yaml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index d32f48880d..0803b2f95b 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -100,6 +100,21 @@ jobs: with: r-version: ${{ matrix.r }} + - name: Override R for locale-specific check + if: matrix.os == 'ubuntu-latest' && !contains(matrix.locale, 'utf8') + run: | + R_BIN_DIR=$(Rscript -e 'cat(R.home("bin"))') + for bin in R Rscript; do + target="${R_BIN_DIR}/${bin}" + sudo mv "$target" "${target}.orig" + sudo tee "$target" << EOF + #!/bin/bash + set -o pipefail + exec "${target}.orig" "\$@" 2>&1 | iconv -c -t UTF-8 + EOF + sudo chmod +x "$target" + done + - name: Set script permissions run: chmod +x configure cleanup 2>/dev/null || true # Silence some GHA Annotations shell: bash @@ -190,7 +205,7 @@ jobs: stop("R CMD check failed") } } - shell: bash -c 'set -o pipefail; Rscript {0} 2>&1 | iconv -c -t UTF-8' + shell: Rscript {0} - name: Upload check results if: failure() From c9ec1fb3431bc178b3ae2fdd8973465817e34325 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Thu, 6 Aug 2026 13:44:06 +0300 Subject: [PATCH 08/10] Install dependencies and build in current locale If the locale encoding is not UTF-8, run R CMD check and convert its output. When running R CMD check, print the check log unconditionally. --- .github/workflows/R-CMD-check-occasional.yaml | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 0803b2f95b..6cb405ee5d 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -91,8 +91,7 @@ jobs: if: matrix.os == 'ubuntu-latest' run: | sudo locale-gen "${{ matrix.locale }}" - echo "LC_ALL=${{ matrix.locale }}" >> $GITHUB_ENV - echo "LANGUAGE=$(echo '${{ matrix.locale }}' | cut -d'.' -f1)" >> $GITHUB_ENV + echo "R_CMD_CHECK_LC_ALL=${{ matrix.locale }}" >> $GITHUB_ENV - uses: actions/checkout@v7 @@ -100,21 +99,6 @@ jobs: with: r-version: ${{ matrix.r }} - - name: Override R for locale-specific check - if: matrix.os == 'ubuntu-latest' && !contains(matrix.locale, 'utf8') - run: | - R_BIN_DIR=$(Rscript -e 'cat(R.home("bin"))') - for bin in R Rscript; do - target="${R_BIN_DIR}/${bin}" - sudo mv "$target" "${target}.orig" - sudo tee "$target" << EOF - #!/bin/bash - set -o pipefail - exec "${target}.orig" "\$@" 2>&1 | iconv -c -t UTF-8 - EOF - sudo chmod +x "$target" - done - - name: Set script permissions run: chmod +x configure cleanup 2>/dev/null || true # Silence some GHA Annotations shell: bash @@ -192,16 +176,23 @@ jobs: build_args = "--no-build-vignettes" check_args = c(check_args, "--no-build-vignettes", "--ignore-vignettes") } - if (requireNamespace("rcmdcheck", quietly=TRUE)) { + locale = Sys.getenv("R_CMD_CHECK_LC_ALL") # only set on Linux + utf8locale = grepl("utf8", locale) + if (requireNamespace("rcmdcheck", quietly=TRUE) && utf8locale) { + if (nzchar(locale)) Sys.setenv(LC_ALL = locale) rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check") } else { Rbin = if (.Platform$OS.type == "windows") "R.exe" else "R" system2(Rbin, c("CMD", "build", ".", build_args)) dt_tar = list.files(pattern = "^data[.]table_.*[.]tar[.]gz$") if (!length(dt_tar)) stop("Built tar.gz not found among: ", toString(list.files())) + if (nzchar(locale)) Sys.setenv(LC_ALL = locale) res = system2(Rbin, c("CMD", "check", dt_tar[1L], check_args), stdout=TRUE, stderr=TRUE) - if (!is.null(attr(res, "status")) || anyNA(res) || any(grepl("^Status:.*(ERROR|WARNING)", res))) { - writeLines(as.character(res)) + status = attr(res, "status") + if (!utf8locale) + res = iconv(res, sub(".*[.]", "", locale), "UTF-8", "byte") + writeLines(res, useBytes = TRUE) + if (!is.null(status) || anyNA(res) || any(grepl("^Status:.*(ERROR|WARNING)", res))) { stop("R CMD check failed") } } From fed7e50232787389d3dcf6cee6b24aa25fa09235 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Thu, 6 Aug 2026 18:43:27 +0300 Subject: [PATCH 09/10] Set fr_CA.ISO-8859-1 explicitly, just in case --- .github/workflows/R-CMD-check-occasional.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 6cb405ee5d..e26190114d 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -22,7 +22,7 @@ jobs: # Multibyte characters: Mandarin 'zh_CN.utf8', # Encoding: non-UTF-8 locales for French, Mandarin, and Russian - 'fr_CA', 'zh_CN.GB18030', 'ru_RU.KOI8-R', # fr_CA is implicitly 'ISO-8859-1' + 'fr_CA.ISO-8859-1', 'zh_CN.GB18030', 'ru_RU.KOI8-R', # Collate order (#3502, see also #7837): Latvian, Azeri, Hungarian, Faroese, Albanian 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8', # Local time formatting (for R bug #19117) From dc269ad1aa3f8a492b14f83d48086f85fb0d6ab6 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Thu, 6 Aug 2026 18:52:58 +0300 Subject: [PATCH 10/10] Do use rcmdcheck on non-Linux --- .github/workflows/R-CMD-check-occasional.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index e26190114d..71072bacc1 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -176,21 +176,21 @@ jobs: build_args = "--no-build-vignettes" check_args = c(check_args, "--no-build-vignettes", "--ignore-vignettes") } - locale = Sys.getenv("R_CMD_CHECK_LC_ALL") # only set on Linux - utf8locale = grepl("utf8", locale) - if (requireNamespace("rcmdcheck", quietly=TRUE) && utf8locale) { - if (nzchar(locale)) Sys.setenv(LC_ALL = locale) + testing_locale = Sys.getenv("R_CMD_CHECK_LC_ALL") # only set on Linux + non_utf8_locale = nzchar(testing_locale) && !grepl("utf8", testing_locale) + if (requireNamespace("rcmdcheck", quietly=TRUE) && !non_utf8_locale) { + if (nzchar(testing_locale)) Sys.setenv(LC_ALL = testing_locale) rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check") } else { Rbin = if (.Platform$OS.type == "windows") "R.exe" else "R" system2(Rbin, c("CMD", "build", ".", build_args)) dt_tar = list.files(pattern = "^data[.]table_.*[.]tar[.]gz$") if (!length(dt_tar)) stop("Built tar.gz not found among: ", toString(list.files())) - if (nzchar(locale)) Sys.setenv(LC_ALL = locale) + if (nzchar(testing_locale)) Sys.setenv(LC_ALL = testing_locale) res = system2(Rbin, c("CMD", "check", dt_tar[1L], check_args), stdout=TRUE, stderr=TRUE) status = attr(res, "status") - if (!utf8locale) - res = iconv(res, sub(".*[.]", "", locale), "UTF-8", "byte") + if (non_utf8_locale) + res = iconv(res, sub(".*[.]", "", testing_locale), "UTF-8", "byte") writeLines(res, useBytes = TRUE) if (!is.null(status) || anyNA(res) || any(grepl("^Status:.*(ERROR|WARNING)", res))) { stop("R CMD check failed")