Skip to content

Commit a1d66a1

Browse files
Merge branch 'master' into issue_6720
2 parents 3a123cf + 0f166cb commit a1d66a1

File tree

12 files changed

+206
-149
lines changed

12 files changed

+206
-149
lines changed

.ci/README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ Test jobs:
1313
- `test-lin-dev-gcc-strict-cran` - `--as-cran` on Linux, `r-devel` built with `-enable-strict-barrier --disable-long-double`, test for compilation warnings, test for new NOTEs/WARNINGs from `R CMD check`.
1414
- `test-lin-dev-clang-cran` - same as `gcc-strict` job but R built with `clang` and no `--enable-strict-barrier --disable-long-double` flags.
1515
- `test-lin-ancient-cran` - Stated R dependency version (currently 3.4.0) on Linux.
16-
- `test-lin-dev-san` - `r-devel` on Linux built with `clang -fsanitize=address,undefined` (including LeakSanitizer), test for sanitizer output in tests and examples.
16+
- `test-lin-dev-clang-san` - `r-devel` on Linux built with `clang -fsanitize=address,undefined` (including LeakSanitizer), test for sanitizer output in tests and examples.
17+
- `test-lin-dev-gcc-san` - `r-devel` on Linux built with `gcc -fsanitize=address,undefined` (including LeakSanitizer), test for sanitizer output in tests and examples.
1718
- `test-win-rel` - `r-release` on Windows.
1819
- `test-win-dev` - `r-devel` on Windows.
1920
- `test-win-old` - `r-oldrel` on Windows.
@@ -49,6 +50,23 @@ Base R implemented helper script, [originally proposed to base R](https://svn.r-
4950

5051
Base R implemented helper script to orchestrate generation of most artifacts and to arrange them nicely. It is being used only in [_integration_ stage in GitLab CI pipeline](./../.gitlab-ci.yml).
5152

53+
### [`lint.R`](./lint.R)
54+
55+
Base R runner for the manual (non-`lintr`) lint checks to be run from GitHub Actions during the code quality check. The command line arguments are as follows:
56+
1. Path to the directory containing files defining the linters. A linter is a function that accepts one argument (typically the path to the file) and signals an error if it fails the lint check.
57+
2. Path to the directory containing files to check.
58+
3. A regular expression matching the files to check.
59+
60+
One of the files in the linter directory may define the `.preprocess` function, which must accept one file path and return a value that other linter functions will understand. The function may also return `NULL` to indicate that the file must be skipped.
61+
62+
Example command lines:
63+
64+
```sh
65+
Rscript .ci/lint.R .ci/linters/c src '[.][ch]$'
66+
Rscript .ci/lint.R .ci/linters/po po '[.]po$'
67+
Rscript .ci/lint.R .ci/linters/md . '[.]R?md$'
68+
```
69+
5270
## GitLab Open Source Program
5371

5472
We are currently part of the [GitLab for Open Source Program](https://about.gitlab.com/solutions/open-source/). This gives us 50,000 compute minutes per month for our GitLab CI. Our license needs to be renewed yearly (around July) and is currently managed by @ben-schwen.

.ci/lint.R

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/Rscript
2+
# Runner for the manual lint checks in .ci/linters
3+
args = commandArgs(TRUE)
4+
if (identical(args, '--help')) {
5+
writeLines(c(
6+
'Usage: Rscript .ci/lint.R .ci/linters/<KIND> <WHERE> <WHAT> [PREPROCESS]',
7+
'KIND must name the directory containing the *.R files defining the linter functions.',
8+
'WHERE must name the directory containing the files to lint, e.g. "po", or "src".',
9+
"WHAT must contain the regular expression matching the files to lint, e.g., '[.]po$', or '[.][ch]$'.",
10+
))
11+
q('no')
12+
}
13+
stopifnot(`Invalid arguments, see .ci/lint.R --help` = length(args) == 3)
14+
15+
linter_env = list2env(list(.preprocess = identity))
16+
for (f in list.files(args[[1]], full.names=TRUE)) sys.source(f, linter_env)
17+
if (!length(ls(linter_env))) stop(
18+
"No linters found after sourcing files in ", dQuote(args[[1]])
19+
)
20+
21+
sources = list.files(args[[2]], pattern = args[[3]], full.names = TRUE, recursive = TRUE)
22+
if (!length(sources)) stop(
23+
"No files to lint found in directory ", dQuote(args[[2]]), " for mask ", dQuote(args[[3]])
24+
)
25+
sources = Filter(Negate(is.null), lapply(setNames(nm = sources), linter_env$.preprocess))
26+
27+
okay = TRUE
28+
for (src in names(sources))
29+
for (linter in ls(linter_env)) tryCatch(
30+
linter_env[[linter]](sources[[src]]),
31+
error = function(e) {
32+
message('Source file ', dQuote(src), ' failed lint check ', dQuote(linter), ': ', conditionMessage(e))
33+
okay <<- FALSE
34+
}
35+
)
36+
stopifnot(`Please fix the issues above.` = okay)

.ci/linters/c/00preprocess.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.preprocess = function (f) list(
2+
c_obj = f, lines = readLines(f),
3+
preprocessed = system2(
4+
"gcc", shQuote(c("-fpreprocessed", "-E", f)),
5+
stdout = TRUE, stderr = FALSE
6+
)
7+
)

.ci/linters/md/heading_id_linter.R

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
any_mismatch = FALSE
2-
31
# ensure that ids are limited to alphanumerics and dashes
42
# (in particular, dots and underscores break the links)
53
check_header_ids = function(md) {
4+
if (!grepl('[.]Rmd$', md)) return(invisible())
5+
md = readLines(md)
66
# A bit surprisingly, some headings don't start with a letter.
77
# We're interested in those that set an id to link to, i.e., end with {#id}.
88
heading_captures = regmatches(md, regexec("^#+ \\S.*[{]#([^}]*)[}]$", md))
@@ -14,13 +14,5 @@ check_header_ids = function(md) {
1414
"On line %d, bad heading id '%s':\n%s\n",
1515
line, heading_captures[[line]][2], heading_captures[[line]][1]
1616
))
17-
!all(good_ids)
17+
stopifnot('Please fix the vignette issues above' = all(good_ids))
1818
}
19-
20-
any_error = FALSE
21-
for (vignette in list.files('vignettes', pattern = "[.]Rmd$", recursive = TRUE, full.name = TRUE)) {
22-
cat(sprintf("Checking vignette file %s...\n", vignette))
23-
rmd_lines = readLines(vignette)
24-
any_error = check_header_ids(rmd_lines) || any_error
25-
}
26-
if (any_error) stop("Please fix the vignette issues above.")

.ci/linters/md/news_linter.R

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
any_mismatch = FALSE
2-
31
# ensure that numbered list in each section is in sequence
42
check_section_numbering = function(news) {
3+
if (!grepl("NEWS", news)) return(invisible())
4+
news = readLines(news)
55
# plain '#' catches some examples; 'd' for 'data.table'
66
sections = grep("^#+ [A-Zd]", news)
77
entries = grep("^[0-9]+[.]", news)
88
entry_value = as.integer(gsub("^([0-9]+)[.].*", "\\1", news[entries]))
99
section_id = findInterval(entries, sections)
10-
10+
1111
any_mismatch = FALSE
1212
for (id in unique(section_id)) {
1313
section_entries = entry_value[section_id == id]
@@ -22,11 +22,12 @@ check_section_numbering = function(news) {
2222
paste0(" [", section_entries[!matched], " --> ", intended_value[!matched], "]", collapse="\n")
2323
))
2424
}
25-
return(any_mismatch)
25+
stopifnot("Please fix the NEWS issues above" = !any_mismatch)
2626
}
2727

2828
# ensure that GitHub link text & URL actually agree
2929
check_gh_links = function(news) {
30+
news = readLines(news)
3031
gh_links_info = gregexpr(
3132
"\\[#(?<md_number>[0-9]+)\\]\\(https://github.com/Rdatatable/data.table/(?<link_type>[^/]+)/(?<link_number>[0-9]+)\\)",
3233
news,
@@ -48,14 +49,5 @@ check_gh_links = function(news) {
4849
"In line %d, link pointing to %s %s is written #%s\n",
4950
line_number, link_type, link_number, md_number
5051
)))
51-
return(TRUE)
52-
}
53-
54-
any_error = FALSE
55-
for (news in list.files(pattern = "NEWS")) {
56-
cat(sprintf("Checking NEWS file %s...\n", news))
57-
news_lines = readLines(news)
58-
any_error = check_section_numbering(news_lines) || any_error
59-
any_error = check_gh_links(news_lines) || any_error
52+
stop("Please fix the NEWS issues above.")
6053
}
61-
if (any_error) stop("Please fix the NEWS issues above.")

.ci/linters/po/00preprocess.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.preprocess = function (f) {
2+
diff_v_master = system2('git', c('diff', 'master', f), stdout=TRUE)
3+
if (length(diff_v_master)) f
4+
}

.github/workflows/code-quality.yaml

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -40,35 +40,20 @@ jobs:
4040
run: /usr/bin/sudo apt-get -y install coccinelle
4141
- name: Lint
4242
run: |
43-
linter_env = new.env()
44-
for (f in list.files('.ci/linters/c', full.names=TRUE)) sys.source(f, linter_env)
45-
for (f in list.files('src', pattern='[.][ch]$', full.names=TRUE)) {
46-
c_obj = list(path = f, lines = readLines(f))
47-
c_obj$preprocessed = system2("gcc", c("-fpreprocessed", "-E", f), stdout=TRUE, stderr=FALSE)
48-
for (linter in ls(linter_env)) linter_env[[linter]](c_obj)
49-
# TODO(#6272): Incorporate more checks from CRAN_Release
50-
}
51-
shell: Rscript {0}
43+
Rscript .ci/lint.R .ci/linters/c src '[.][ch]$'
5244
lint-po:
5345
runs-on: ubuntu-latest
5446
steps:
5547
- uses: actions/checkout@v4
5648
- uses: r-lib/actions/setup-r@v2
5749
- name: Check translations
50+
# only pay attention to files edited in the current PR, otherwise we can get
51+
# a situation like after #6424 where some untranslated messages were added
52+
# as part of non-translation maintenance, but this GHA would go red repeatedly
53+
# until a translation is added or the blank/fuzzy translations removed. We'd
54+
# rather only have the failure on one PR, then ignore these files later.
5855
run: |
59-
linter_env = new.env()
60-
for (f in list.files('.ci/linters/po', full.names=TRUE)) sys.source(f, linter_env)
61-
for (po_file in list.files(pattern = "[.]po$", full.names=TRUE)) {
62-
# only pay attention to files edited in the current PR, otherwise we can get
63-
# a situation like after #6424 where some untranslated messages were added
64-
# as part of non-translation maintenance, but this GHA would go red repeatedly
65-
# until a translation is added or the blank/fuzzy translations removed. We'd
66-
# rather only have the failure on one PR, then ignore these files later.
67-
diff_v_master = system2("git", c("diff", "master", po_file), stdout=TRUE)
68-
if (!length(diff_v_master)) next
69-
for (linter in ls(linter_env)) linter_env[[linter]](po_file)
70-
}
71-
shell: Rscript {0}
56+
Rscript .ci/lint.R .ci/linters/po po '[.]po$'
7257
lint-md:
7358
runs-on: ubuntu-latest
7459
steps:
@@ -77,17 +62,3 @@ jobs:
7762
- name: Lint
7863
run: for (f in list.files('.ci/linters/md', full.names=TRUE)) source(f)
7964
shell: Rscript {0}
80-
build:
81-
runs-on: ubuntu-latest
82-
steps:
83-
- uses: actions/checkout@v2
84-
- uses: r-lib/actions/setup-r@v2
85-
- name: Install remotes
86-
run: Rscript -e "install.packages('remotes')"
87-
- name: Install dependencies
88-
run: Rscript -e 'remotes::install_deps(dependencies = TRUE)'
89-
- name: Check documentation and options consistency
90-
run: Rscript .ci/check-options.R
91-
- name: Run R CMD check
92-
run: Rscript -e 'devtools::check()'
93-

.gitlab-ci.yml

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ test-lin-ancient-cran:
218218
# Restore checking vignettes if upgrading our R dependency means knitr can be installed, or when we switch to litedown.
219219
- R CMD check --no-manual --no-build-vignettes --ignore-vignettes $(ls -1t data.table_*.tar.gz | head -n 1)
220220

221-
# run the main checks with Address(+Leak),UBSanitizer enabled
222-
test-lin-dev-san:
221+
# run the main checks with Address(+Leak),UBSanitizer enabled, GCC _and_ Clang
222+
test-lin-dev-clang-san:
223223
<<: *test-lin
224224
image: registry.gitlab.com/rdatatable/dockerfiles/r-devel-clang-san
225225
variables:
@@ -233,8 +233,27 @@ test-lin-dev-san:
233233
- |
234234
res1=0; ASAN_OPTIONS=detect_leaks=1 R CMD check --no-manual $(ls -1t data.table_*.tar.gz | head -n 1) || res1=$?
235235
res2=0; perl -nle '(print, $a=1) if /: runtime error: |ERROR: LeakSanitizer/../SUMMARY.*Sanitizer/ }{ exit $a' data.table.Rcheck/**/*.Rout* || res2=$?
236+
res3=0; tail -n 1 data.table.Rcheck/00check.log | grep -q -e '^Status: [0-9]* NOTEs*$' -e '^Status: OK$' || res3=$?
236237
# fail if R CMD check had failed or if sanitizer output found
237-
if [ $res1 -ne 0 ] || [ $res2 -ne 0 ]; then exit 1; fi
238+
if [ $res1 -ne 0 ] || [ $res2 -ne 0 ] || [ $res3 -ne 0 ]; then exit 1; fi
239+
240+
test-lin-dev-gcc-san:
241+
<<: *test-lin
242+
image: registry.gitlab.com/rdatatable/dockerfiles/r-devel-gcc-san
243+
variables:
244+
# must be set for most of the process because there are pseudo-leaks everywhere
245+
ASAN_OPTIONS: "detect_leaks=0"
246+
# fontconfig is known to leak; add more suppressions as discovered
247+
LSAN_OPTIONS: "suppressions=$CI_PROJECT_DIR/.dev/lsan.supp"
248+
UBSAN_OPTIONS: "print_stacktrace=1"
249+
script:
250+
- *install-deps
251+
- |
252+
res1=0; ASAN_OPTIONS=detect_leaks=1 R CMD check --no-manual $(ls -1t data.table_*.tar.gz | head -n 1) || res1=$?
253+
res2=0; perl -nle '(print, $a=1) if /: runtime error: |ERROR: LeakSanitizer/../SUMMARY.*Sanitizer/ }{ exit $a' data.table.Rcheck/**/*.Rout* || res2=$?
254+
res3=0; tail -n 1 data.table.Rcheck/00check.log | grep -q -e '^Status: [0-9]* NOTEs*$' -e '^Status: OK$' || res3=$?
255+
# fail if R CMD check had failed or if sanitizer output found
256+
if [ $res1 -ne 0 ] || [ $res2 -ne 0 ] || [ $res3 -ne 0 ]; then exit 1; fi
238257
239258
.test-win-template: &test-win
240259
<<: *test
@@ -338,7 +357,7 @@ integration:
338357
- saas-linux-medium-amd64
339358
only:
340359
- master
341-
needs: ["mirror-packages","build","test-lin-rel","test-lin-rel-cran","test-lin-dev-gcc-strict-cran","test-lin-dev-clang-cran","test-lin-rel-vanilla","test-lin-ancient-cran","test-lin-dev-san","test-win-rel","test-win-dev" ,"test-win-old","test-mac-rel","test-mac-old"]
360+
needs: ["mirror-packages","build","test-lin-rel","test-lin-rel-cran","test-lin-dev-gcc-strict-cran","test-lin-dev-clang-cran","test-lin-rel-vanilla","test-lin-ancient-cran","test-lin-dev-clang-san","test-lin-dev-gcc-san","test-win-rel","test-win-dev" ,"test-win-old","test-mac-rel","test-mac-old"]
342361
script:
343362
- R --version
344363
- *install-deps ## markdown pkg not present in r-pkgdown image

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Authors@R: c(
5555
person("James","Sams", role="ctb"),
5656
person("Martin","Morgan", role="ctb"),
5757
person("Michael","Quinn", role="ctb"),
58-
person("@javrucebo","", role="ctb"),
58+
person(given="@javrucebo", role="ctb", comment="GitHub user"),
5959
person("Marc","Halperin", role="ctb"),
6060
person("Roy","Storey", role="ctb"),
6161
person("Manish","Saraswat", role="ctb"),
@@ -102,6 +102,6 @@ Authors@R: c(
102102
person("Aljaž", "Sluga", role="ctb"),
103103
person("Bill", "Evans", role="ctb"),
104104
person("Reino", "Bruner", role="ctb"),
105-
person(comment=c(github="@badasahog"), role="ctb"),
105+
person(given="@badasahog", role="ctb", comment="GitHub user"),
106106
person("Vinit", "Thakur", role="ctb")
107107
)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
11. Out of sample type bumps now respect `integer64=` selection, [#7032](https://github.com/Rdatatable/data.table/pull/7032).
4444

45+
12. Internal functions used to signal errors are now marked as non-returning, silencing a compiler warning about potentially unchecked allocation failure. Thanks to Prof. Brian D. Ripley for the report and @aitap for the fix, [#7070](https://github.com/Rdatatable/data.table/pull/7070).
46+
4547
### NOTES
4648

4749
1. Continued work to remove non-API C functions, [#6180](https://github.com/Rdatatable/data.table/issues/6180). Thanks Ivan Krylov for the PRs and for writing a clear and concise guide about the R API: https://aitap.codeberg.page/R-api/.

0 commit comments

Comments
 (0)