From b698fd3c55d5691b4a215cf44ba402a092f40905 Mon Sep 17 00:00:00 2001 From: Dennis Yatunin Date: Tue, 26 Mar 2024 11:23:00 -0700 Subject: [PATCH] Add preliminary files for setting up package --- .dev/Project.toml | 5 ++ .dev/clima_formatter_options.jl | 8 +++ .dev/climaformat.jl | 85 ++++++++++++++++++++++++++++ .dev/hooks/pre-commit | 41 ++++++++++++++ .github/pull_request_template.md | 0 .github/workflows/CodeCov.yml | 43 ++++++++++++++ .github/workflows/CompatHelper.yml | 16 ++++++ .github/workflows/JuliaFormatter.yml | 43 ++++++++++++++ .github/workflows/TagBot.yml | 15 +++++ .github/workflows/ci.yml | 46 +++++++++++++++ .github/workflows/invalidations.yml | 40 +++++++++++++ .gitignore | 25 ++++++++ LICENSE | 21 +++++++ Project.toml | 17 ++++++ src/UnrolledUtilities.jl | 5 ++ test/aqua.jl | 17 ++++++ test/runtests.jl | 5 ++ 17 files changed, 432 insertions(+) create mode 100644 .dev/Project.toml create mode 100644 .dev/clima_formatter_options.jl create mode 100644 .dev/climaformat.jl create mode 100755 .dev/hooks/pre-commit create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/CodeCov.yml create mode 100644 .github/workflows/CompatHelper.yml create mode 100644 .github/workflows/JuliaFormatter.yml create mode 100644 .github/workflows/TagBot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/invalidations.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Project.toml create mode 100644 src/UnrolledUtilities.jl create mode 100644 test/aqua.jl create mode 100644 test/runtests.jl diff --git a/.dev/Project.toml b/.dev/Project.toml new file mode 100644 index 0000000..71708c8 --- /dev/null +++ b/.dev/Project.toml @@ -0,0 +1,5 @@ +[deps] +JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" + +[compat] +JuliaFormatter = "1" diff --git a/.dev/clima_formatter_options.jl b/.dev/clima_formatter_options.jl new file mode 100644 index 0000000..1db65e8 --- /dev/null +++ b/.dev/clima_formatter_options.jl @@ -0,0 +1,8 @@ +clima_formatter_options = ( + indent = 4, + margin = 80, + always_for_in = true, + whitespace_typedefs = true, + whitespace_ops_in_indices = true, + remove_extra_newlines = false, +) diff --git a/.dev/climaformat.jl b/.dev/climaformat.jl new file mode 100644 index 0000000..713a518 --- /dev/null +++ b/.dev/climaformat.jl @@ -0,0 +1,85 @@ +#!/usr/bin/env julia +# +# This is an adapted version of format.jl from JuliaFormatter with the +# following license: +# +# MIT License +# Copyright (c) 2019 Dominique Luna +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to permit +# persons to whom the Software is furnished to do so, subject to the +# following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +# USE OR OTHER DEALINGS IN THE SOFTWARE. +# +using Pkg +Pkg.activate(@__DIR__) +Pkg.instantiate() + +using JuliaFormatter + +include("clima_formatter_options.jl") + +help = """ +Usage: climaformat.jl [flags] [FILE/PATH]... + +Formats the given julia files using the CLIMA formatting options. If paths +are given it will format the julia files in the paths. Otherwise, it will +format all changed julia files. + + -v, --verbose + Print the name of the files being formatted with relevant details. + + -h, --help + Print this message. +""" + +function parse_opts!(args::Vector{String}) + i = 1 + opts = Dict{Symbol, Union{Int, Bool}}() + while i ≤ length(args) + arg = args[i] + if arg[1] != '-' + i += 1 + continue + end + if arg == "-v" || arg == "--verbose" + opt = :verbose + elseif arg == "-h" || arg == "--help" + opt = :help + else + error("invalid option $arg") + end + if opt in (:verbose, :help) + opts[opt] = true + deleteat!(args, i) + end + end + return opts +end + +opts = parse_opts!(ARGS) +if haskey(opts, :help) + write(stdout, help) + exit(0) +end +if isempty(ARGS) + filenames = readlines(`git ls-files "*.jl"`) +else + filenames = ARGS +end + +format(filenames; clima_formatter_options..., opts...) diff --git a/.dev/hooks/pre-commit b/.dev/hooks/pre-commit new file mode 100755 index 0000000..0e56ed0 --- /dev/null +++ b/.dev/hooks/pre-commit @@ -0,0 +1,41 @@ +#!/usr/bin/env julia +# +# Called by git-commit with no arguments. This checks to make sure that all +# .jl files are indented correctly before a commit is made. +# +# To enable this hook, make this file executable and copy it in +# $GIT_DIR/hooks. + +toplevel_directory = chomp(read(`git rev-parse --show-toplevel`, String)) + +using Pkg +Pkg.activate(joinpath(toplevel_directory, ".dev")) +Pkg.instantiate() + +using JuliaFormatter + +include(joinpath(toplevel_directory, ".dev", "clima_formatter_options.jl")) + +needs_format = false + +for diffoutput in split.(readlines(`git diff --name-status --cached`)) + status = diffoutput[1] + filename = diffoutput[end] + (!startswith(status, "D") && endswith(filename, ".jl")) || continue + + a = read(`git show :$filename`, String) + b = format_text(a; clima_formatter_options...) + + if a != b + fullfilename = joinpath(toplevel_directory, filename) + + @error """File $filename needs to be indented with: + julia $(joinpath(toplevel_directory, ".dev", "climaformat.jl")) $fullfilename + and added to the git index via + git add $fullfilename + """ + global needs_format = true + end +end + +exit(needs_format ? 1 : 0) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..e69de29 diff --git a/.github/workflows/CodeCov.yml b/.github/workflows/CodeCov.yml new file mode 100644 index 0000000..62b5dde --- /dev/null +++ b/.github/workflows/CodeCov.yml @@ -0,0 +1,43 @@ +name: CodeCov + +on: + push: + branches: + - main + tags: '*' + pull_request: + merge_group: + +jobs: + codecov: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Julia + uses: julia-actions/setup-julia@latest + with: + version: '1.10' + + - name: Test with coverage + env: + JULIA_PROJECT: "@." + run: | + julia --project=@. -e 'using Pkg; Pkg.instantiate()' + julia --project=@. -e 'using Pkg; Pkg.test(coverage=true)' + + - name: Generate coverage file + env: + JULIA_PROJECT: "@." + run: julia --project=@. -e 'using Pkg; Pkg.add("Coverage"); + using Coverage; + LCOV.writefile("coverage-lcov.info", Codecov.process_folder())' + if: success() + + - name: Submit coverage + uses: codecov/codecov-action@v3 + with: + token: ${{secrets.CODECOV_TOKEN}} + if: success() + diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml new file mode 100644 index 0000000..bcdb51a --- /dev/null +++ b/.github/workflows/CompatHelper.yml @@ -0,0 +1,16 @@ +name: CompatHelper +on: + schedule: + - cron: '00 00 * * *' + workflow_dispatch: +jobs: + CompatHelper: + runs-on: ubuntu-latest + steps: + - name: Pkg.add("CompatHelper") + run: julia -e 'using Pkg; Pkg.add("CompatHelper")' + - name: CompatHelper.main() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }} # optional + run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/.github/workflows/JuliaFormatter.yml b/.github/workflows/JuliaFormatter.yml new file mode 100644 index 0000000..e84ee69 --- /dev/null +++ b/.github/workflows/JuliaFormatter.yml @@ -0,0 +1,43 @@ +name: JuliaFormatter + +on: + push: + branches: + - main + tags: '*' + pull_request: + merge_group: + +jobs: + format: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.4.0 + with: + access_token: ${{ github.token }} + + - uses: actions/checkout@v4 + + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + julia_file_change: + - added|modified: '**.jl' + + - uses: julia-actions/setup-julia@latest + if: steps.filter.outputs.julia_file_change == 'true' + with: + version: '1.10' + + - name: Apply JuliaFormatter + if: steps.filter.outputs.julia_file_change == 'true' + run: | + julia --project=.dev .dev/climaformat.jl . + + - name: Check formatting diff + if: steps.filter.outputs.julia_file_change == 'true' + run: | + git diff --color=always --exit-code diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml new file mode 100644 index 0000000..f49313b --- /dev/null +++ b/.github/workflows/TagBot.yml @@ -0,0 +1,15 @@ +name: TagBot +on: + issue_comment: + types: + - created + workflow_dispatch: +jobs: + TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' + runs-on: ubuntu-latest + steps: + - uses: JuliaRegistries/TagBot@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + ssh: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..919b89c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: ci +on: + push: + branches: + - main + tags: '*' + pull_request: + merge_group: + +jobs: + test: + name: ci ${{ matrix.version }} - ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: + - '1.10' + os: + - ubuntu-latest + - macOS-latest + - windows-latest + arch: + - x64 + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - uses: actions/cache@v1 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v1 + with: + file: lcov.info diff --git a/.github/workflows/invalidations.yml b/.github/workflows/invalidations.yml new file mode 100644 index 0000000..881ebec --- /dev/null +++ b/.github/workflows/invalidations.yml @@ -0,0 +1,40 @@ +name: Invalidations + +on: + pull_request: + +concurrency: + # Skip intermediate builds: always. + # Cancel intermediate builds: always. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + evaluate: + # Only run on PRs to the default branch. + # In the PR trigger above branches can be specified only explicitly whereas this check should work for master, main, or any other default branch + if: github.base_ref == github.event.repository.default_branch + runs-on: ubuntu-latest + steps: + - uses: julia-actions/setup-julia@v1 + with: + version: '1' + - uses: actions/checkout@v4 + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-invalidations@v1 + id: invs_pr + + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-invalidations@v1 + id: invs_default + + - name: Report invalidation counts + run: | + echo "Invalidations on default branch: ${{ steps.invs_default.outputs.total }} (${{ steps.invs_default.outputs.deps }} via deps)" >> $GITHUB_STEP_SUMMARY + echo "This branch: ${{ steps.invs_pr.outputs.total }} (${{ steps.invs_pr.outputs.deps }} via deps)" >> $GITHUB_STEP_SUMMARY + - name: Check if the PR does increase number of invalidations + if: steps.invs_pr.outputs.total > steps.invs_default.outputs.total + run: exit 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79c5d2b --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Files generated by invoking Julia with --code-coverage +*.jl.cov +*.jl.*.cov + +# Files generated by invoking Julia with --track-allocation +*.jl.mem +*.html + +# System-specific files and directories generated by the BinaryProvider and BinDeps packages +# They contain absolute paths specific to the host computer, and so should not be committed +deps/deps.jl +deps/build.log +deps/downloads/ +deps/usr/ +deps/src/ + +# Build artifacts for creating documentation generated by the Documenter package +docs/build/ +docs/site/ + +# File generated by Pkg, the package manager, based on a corresponding Project.toml +# It records a fixed state of all packages used by the project. As such, it should not be +# committed for packages, but should be committed for applications that require a static +# environment. +Manifest.toml diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b2a5c38 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Charles Kawczynski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Project.toml b/Project.toml new file mode 100644 index 0000000..6ea7814 --- /dev/null +++ b/Project.toml @@ -0,0 +1,17 @@ +name = "UnrolledUtilities" +uuid = "0fe1646c-419e-43be-ac14-22321958931b" +authors = ["CliMA Contributors "] +version = "0.1.0" + +[compat] +julia = "1.10" + +[extras] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" +SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["Aqua", "BenchmarkTools", "JET", "SafeTestsets", "Test"] diff --git a/src/UnrolledUtilities.jl b/src/UnrolledUtilities.jl new file mode 100644 index 0000000..9191479 --- /dev/null +++ b/src/UnrolledUtilities.jl @@ -0,0 +1,5 @@ +module UnrolledUtilities + +# TODO: Add source code. + +end diff --git a/test/aqua.jl b/test/aqua.jl new file mode 100644 index 0000000..d7becf1 --- /dev/null +++ b/test/aqua.jl @@ -0,0 +1,17 @@ +import Aqua, UnrolledUtilities + +# This is separate from all the other tests because Aqua.test_all checks for +# ambiguities in Base and Core in addition to the ones in UnrolledUtilities, +# resulting in a lot of false positives. Setting recursive to true ensures that +# sub-modules of UnrolledUtilities are also checked for ambiguities. +@testset "Method ambiguity" begin + Aqua.test_ambiguities(UnrolledUtilities; recursive = true) +end + +# Run the other Aqua tests, which are already wrapped in @testset blocks. Do not +# check for compat entries of dependencies that are only used for testing. +Aqua.test_all( + UnrolledUtilities; + ambiguities = false, + deps_compat = (; check_extras = false), +) diff --git a/test/runtests.jl b/test/runtests.jl new file mode 100644 index 0000000..2d1aac4 --- /dev/null +++ b/test/runtests.jl @@ -0,0 +1,5 @@ +using SafeTestsets + +#! format: off +@safetestset "Aqua" begin @time include("aqua.jl") end +#! format: on