Compare commits
22 Commits
tilintarka
...
kalenterik
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f02a4b7359 | ||
| f81cc8a5fe | |||
|
|
aa327b7a4b | ||
|
|
c679d184a9 | ||
|
|
e250b03cc0 | ||
|
|
06989eb867 | ||
|
|
fc858d1159 | ||
|
|
0c179c7e28 | ||
|
|
7102d6f9e8 | ||
|
|
1d191d13ae | ||
|
|
55b59913d7 | ||
|
|
599264b212 | ||
|
|
3411949313 | ||
|
|
e2d517a310 | ||
|
|
c561b9859f | ||
|
|
779c73a906 | ||
|
|
732e43d6af | ||
|
|
fe58ce7484 | ||
|
|
a0be6c2c85 | ||
|
|
705280283c | ||
|
|
9cb04480b5 | ||
|
|
45f1f44498 |
13
.ci
Normal file
13
.ci
Normal file
@ -0,0 +1,13 @@
|
||||
[test "website"]
|
||||
command = ./Shake.hs && ./Shake Clean && ./Shake website
|
||||
#TODO: update for new site
|
||||
# trackedFiles = site/_site \
|
||||
# site/csv.md \
|
||||
# site/hledger-ui.md \
|
||||
# site/hledger-web.md \
|
||||
# site/hledger.md \
|
||||
# site/journal.md \
|
||||
# site/manual.md \
|
||||
# site/timeclock.md \
|
||||
# site/timedot.md
|
||||
#
|
||||
13
.ctags
13
.ctags
@ -1,9 +1,14 @@
|
||||
--exclude=.*
|
||||
--exclude=.build
|
||||
--exclude=.idea
|
||||
--exclude=.shake
|
||||
--exclude=.stack-work
|
||||
--exclude=.vagrant
|
||||
--exclude=.vscode
|
||||
--exclude=_*
|
||||
--exclude=bin
|
||||
--exclude=doc/irc
|
||||
--exclude=doc/profs
|
||||
--exclude=dist*
|
||||
--exclude=dist
|
||||
--exclude=examples
|
||||
--exclude=bootstrap*
|
||||
--exclude=excanvas*
|
||||
@ -11,6 +16,6 @@
|
||||
--exclude=jquery*
|
||||
--exclude=typeahead*
|
||||
--exclude=old
|
||||
--exclude=site/out*
|
||||
--exclude=site/src/1*
|
||||
--exclude=site/doc
|
||||
--exclude=site/files
|
||||
--exclude=hledger/test/addons/hledger-*
|
||||
|
||||
13
.ghci
13
.ghci
@ -1,13 +1,7 @@
|
||||
:set prompt "ghci> "
|
||||
import System.Environment
|
||||
setEnv "NO_COLOR" "1"
|
||||
-- TEMP
|
||||
-- :m +*Hledger.Cli.Commands
|
||||
|
||||
-- https://github.com/cdepillabout/pretty-simple
|
||||
-- If not using a cabal environment file with pretty-simple added, this adds itK here:
|
||||
-- :set -package pretty-simple
|
||||
:set -interactive-print=Text.Pretty.Simple.pPrintNoColor
|
||||
:set -package pretty-simple
|
||||
:set -interactive-print=Text.Pretty.Simple.pPrint
|
||||
|
||||
-- ghci commands to be run once at ghci startup
|
||||
-- http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/ghci-commands.html
|
||||
@ -20,9 +14,6 @@ setEnv "NO_COLOR" "1"
|
||||
-- -- :reload and run commands in .ghci2
|
||||
-- :def R \_ -> return ":reload\n:script .ghci2"
|
||||
|
||||
-- Reload (to pick up code changes and flush cached unsafePerformIO values) and run main with the given args
|
||||
:def! rmain \args -> return $ ":reload\n:main "<>args
|
||||
|
||||
-- -- run commands from a file, .ghci2 by default
|
||||
-- :def s \f -> readFile $ if null f then ".ghci2" else f
|
||||
|
||||
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
github: [simonmichael] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
liberapay: simonmichael
|
||||
# patreon: simonmichael # Replace with a single Patreon username
|
||||
patreon: simonmichael # Replace with a single Patreon username
|
||||
open_collective: hledger # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
|
||||
35
.github/ISSUE_TEMPLATE/a-bug.md
vendored
35
.github/ISSUE_TEMPLATE/a-bug.md
vendored
@ -1,30 +1,25 @@
|
||||
---
|
||||
name: A bug
|
||||
about: A defect in the software, core documentation, user/developer experience, or project
|
||||
about: Any problem that seems to be an error or weakness in hledger's software, documentation, marketing, usability...
|
||||
labels: A BUG
|
||||
title: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
Thanks for helping to make hledger better! Here's how to make a good bug report:
|
||||
Thank you for helping to make hledger better!
|
||||
You can delete this template text before submitting.
|
||||
|
||||
1. Check:
|
||||
Some things to check before reporting:
|
||||
|
||||
- `hledger --version` it's best if it's not very old
|
||||
- https://hledger.org/install.html shows the current version and how to upgrade
|
||||
- https://hledger.org/hledger.html the manual (choose your version at top of page)
|
||||
https://hledger.org/hledger-ui.html
|
||||
https://hledger.org/hledger-web.html
|
||||
- https://hledger.org/relnotes.html recent fixes and upgrade notes
|
||||
- https://bugs.hledger.org bugs already reported
|
||||
- https://hledger.org/faq.html answers to common questions
|
||||
- https://hledger.org/support.html if you have other questions
|
||||
- If you're not sure this is a bug, or if some discussion would help,
|
||||
contact us on chat or the mail list first: https://hledger.org/support.html
|
||||
|
||||
2. In your bug report, please include if possible:
|
||||
- Have you looked at (the right version of) the user manual ?
|
||||
Use `hledger help [--help]` to view the built-in manuals,
|
||||
or view the hledger.org -> USER MANUALS and choose the right version
|
||||
at the top of the page.
|
||||
|
||||
- the output of `hledger --version` or (best) `hledger setup`
|
||||
- which operating system you're running on
|
||||
- a link to the most relevant doc that you found, if any
|
||||
- a small reproducible example or instructions to reproduce.
|
||||
Things that can help us resolve your issue faster:
|
||||
|
||||
3. And remove this help text.
|
||||
- A small reproducible example (--anon can help anonymise data)
|
||||
- The output of hledger --version
|
||||
- What platform you're on
|
||||
- Any related docs that you found
|
||||
|
||||
31
.github/ISSUE_TEMPLATE/a-wish.md
vendored
31
.github/ISSUE_TEMPLATE/a-wish.md
vendored
@ -1,25 +1,24 @@
|
||||
---
|
||||
name: A wish
|
||||
about: A proposal for improving hledger or the project
|
||||
about: A request or proposal for improving hledger's software, documentation, marketing, usability...
|
||||
labels: A WISH
|
||||
title: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
Thanks for contributing. But first:
|
||||
Thank you for helping to make hledger better!
|
||||
You can delete this template text before submitting.
|
||||
|
||||
- Have you looked for related features in the hledger manual (latest version) ?
|
||||
https://hledger.org/hledger.html
|
||||
https://hledger.org/hledger-ui.html
|
||||
https://hledger.org/hledger-web.html
|
||||
Some things to check before requesting:
|
||||
|
||||
- Ideas are endless and developers are few, so we try to not clutter the bug tracker with wishes.
|
||||
Often it's best to discuss them on chat/mail list/forum first:
|
||||
https://hledger.org/support
|
||||
- We try to not clutter the bug tracker with too many wishlist items.
|
||||
Often it's best to discuss and attract interest on chat or the mail list first;
|
||||
use your best judgement. https://hledger.org/support.html
|
||||
|
||||
- Concrete proposals with draft docs move forward more quickly. Consider adding:
|
||||
- A draft of user manual changes
|
||||
- A draft of command line help
|
||||
- A mockup of intended output or UI
|
||||
- Have you looked for related features in (the right version of) the user manual ?
|
||||
Use `hledger help [--help]` to view the built-in manuals,
|
||||
or view the hledger.org -> USER MANUALS and choose the proper version
|
||||
at the top of the page.
|
||||
|
||||
(Please remove all of this text before submitting.)
|
||||
Things that will move your request along faster:
|
||||
|
||||
- A small example or mockup of your intended UI/output
|
||||
- A rough draft of intended command line help/reference documentation
|
||||
|
||||
25
.github/ISSUE_TEMPLATE/config.yml
vendored
25
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,18 +1,11 @@
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates
|
||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository
|
||||
|
||||
blank_issues_enabled: false
|
||||
# https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository
|
||||
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
|
||||
- name: (A website issue)
|
||||
url: https://github.com/simonmichael/hledger_site/issues
|
||||
about: Please use the hledger_site issue tracker
|
||||
|
||||
- name: (A support request)
|
||||
url: https://hledger.org/support
|
||||
about: Please use chat, mail list or forum
|
||||
|
||||
- name: (A security issue)
|
||||
url: https://joyful.com
|
||||
about: Please contact Simon directly
|
||||
- name: Questions, Support
|
||||
url: https://hledger.org/#help-feedback
|
||||
about: For questions and support, please use our Chat or Mail list.
|
||||
# doesn't show, mailto: probably not supported
|
||||
# - name: hledger project security issues
|
||||
# url: mailto:simon@joyful.com
|
||||
# about: Please report security vulnerabilities here.
|
||||
|
||||
15
.github/pull_request_template.md
vendored
15
.github/pull_request_template.md
vendored
@ -4,19 +4,8 @@ If you're a new developer, FOSS contributor, or hledger contributor, welcome.
|
||||
|
||||
Much of our best design work and knowledge sharing happens during code review,
|
||||
so be prepared for more work ahead, especially if your PR is large.
|
||||
To minimise waste, and get your hledger PRs accepted quickly,
|
||||
please check the guidelines in the developer docs:
|
||||
To minimise waste, and learn how to get hledger PRs accepted swiftly,
|
||||
please check the latest guidelines in the developer docs:
|
||||
|
||||
https://hledger.org/PULLREQUESTS.html
|
||||
https://hledger.org/COMMITS.html
|
||||
|
||||
You don't need to master our commit conventions, but do add at least one prefix and colon
|
||||
to the commit message summary. The most common prefixes are:
|
||||
|
||||
- feat: for user-visible features
|
||||
- fix: for user-visible fixes
|
||||
- imp: for user-visible improvements
|
||||
- ;doc: for documentation improvements (; at the start enables quicker/cheaper CI tests)
|
||||
- dev: for internal improvements
|
||||
|
||||
-->
|
||||
|
||||
7
.github/workflows/README
vendored
7
.github/workflows/README
vendored
@ -1,8 +1,5 @@
|
||||
The hledger project's github actions workflows.
|
||||
hledger github actions workflows.
|
||||
|
||||
They have greppable one-line TRIGGER: and ACTION: comments near the top,
|
||||
summarising their current intended behaviour.
|
||||
These are carefully worded and should be kept up to date.
|
||||
|
||||
docs:
|
||||
|
||||
@ -37,5 +34,3 @@ https://github.com/mxschmitt/action-tmate
|
||||
https://kodimensional.dev/github-actions
|
||||
"Dead simple cross-platform GitHub Actions for Haskell"
|
||||
|
||||
https://github.com/actions/runner-images/tree/main?tab=readme-ov-file#available-images
|
||||
https://github.com/actions/partner-runner-images/tree/main?tab=readme-ov-file#available-images
|
||||
|
||||
207
.github/workflows/_binaries-linux-arm64-stack.yml
vendored
207
.github/workflows/_binaries-linux-arm64-stack.yml
vendored
@ -1,207 +0,0 @@
|
||||
# TRIGGER: Runs on any push to binaries-linux-arm64-stack or binaries branches.
|
||||
# ACTION: Builds, unit-tests and saves linux arm64 static binaries with stack and the resolver & ghc version below,
|
||||
# in an Alpine linux container which provides the statically-linkable musl.
|
||||
|
||||
name: binaries-linux-arm64-stack
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-linux-arm64-stack ]
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container: alpine:latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Show platform info
|
||||
run: |
|
||||
arch
|
||||
uname -a
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# - name: Check embedded files
|
||||
# run: |
|
||||
# tools/checkembeddedfiles
|
||||
|
||||
# things to be cached/restored:
|
||||
|
||||
# - name: Cache - ghcup-installed tools
|
||||
# id: ghcup
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: ~/.ghcup
|
||||
# key: ${{ runner.os }}-ghcup-${{ hashFiles('**.yaml') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-ghcup
|
||||
|
||||
- name: Cache - stack-installed programs in ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-aarch64-stack-programs-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-aarch64-stack-programs
|
||||
|
||||
- name: Cache - stack global package db
|
||||
id: stack-global
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.stack
|
||||
key: ${{ runner.os }}-aarch64-stack-global-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-aarch64-stack-global
|
||||
|
||||
- name: Cache - .stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-aarch64-stack-work-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-aarch64-stack-work
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-aarch64-hledger-lib-stack-work-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-aarch64-hledger-lib-stack-work
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-aarch64-hledger-stack-work-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-aarch64-hledger-stack-work
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-aarch64-hledger-ui-stack-work-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-aarch64-hledger-ui-stack-work
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-aarch64-hledger-web-stack-work-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-aarch64-hledger-web-stack-work
|
||||
|
||||
# actions:
|
||||
|
||||
# - name: Install general tools with system package manager
|
||||
# run: |
|
||||
# apk --no-cache add binutils-gold curl gcc g++ git ripgrep tar gmp-dev libffi-dev ncurses-dev ncurses-static zlib-dev zlib-static
|
||||
|
||||
# set HOME to /root for stack (do it here in case it matters for ghcup too). workaround from https://github.com/actions/runner/issues/863)
|
||||
- name: Set $HOME to /root for stack
|
||||
run: |
|
||||
apk add sudo
|
||||
echo "setting HOME=/root for stack"
|
||||
echo HOME=/root | sudo tee -a $GITHUB_ENV
|
||||
|
||||
- name: Install System Dependencies
|
||||
run: |
|
||||
# Add dependencies GHC/Stack need for linking
|
||||
apk add stack gmp-dev zlib-dev zlib-static libffi-dev ncurses-dev ncurses-static gcc make musl-dev xz ripgrep
|
||||
|
||||
- name: Configure stack.yaml for static linking
|
||||
run: |
|
||||
# Add the ghc-options section to stack.yaml, using "$all"
|
||||
echo "ghc-options:" >> stack.yaml
|
||||
echo ' "$all": -fPIC -static -pie -Werror' >> stack.yaml
|
||||
echo "Applied new stack.yaml configuration:"
|
||||
cat stack.yaml
|
||||
|
||||
# - name: Install haskell tools if needed
|
||||
# run: |
|
||||
# Try hard to persuade ghcup to install an aarch64 binary
|
||||
#ghcup config set platform-override '{ "arch": "A_64", "platform": { "contents": "Alpine", "tag": "Linux" }, "version": "3.18" }'
|
||||
# cat >~/.ghcup/config.yaml <<END
|
||||
# platform-override:
|
||||
# arch: A_64
|
||||
# platform:
|
||||
# contents: Alpine
|
||||
# tag: Linux
|
||||
# version: '3.18'
|
||||
# END
|
||||
# if [[ ! -x ~/.ghcup/bin/ghc-9.12.2 ]]; then ~/.ghcup/bin/ghcup install ghc 9.12.2 -u https://downloads.haskell.org/~ghc/9.12.2/ghc-9.12.2-aarch64-alpine3_18-linux.tar.xz && ~/.ghcup/bin/ghcup set ghc 9.12.2; fi; printf "ghc: "; ghc --version
|
||||
# if [[ ! -x ~/.ghcup/bin/cabal ]]; then ~/.ghcup/bin/ghcup install cabal 3.14.2.0 && ~/.ghcup/bin/ghcup set cabal 3.14.2.0; fi; printf "cabal: "; cabal --version
|
||||
|
||||
# curl -sSL https://get.haskellstack.org/ | sh
|
||||
# # cat > ~/.stack/global-project/stack.yaml << END
|
||||
# # packages: []
|
||||
# # resolver: nightly-2025-05-01
|
||||
# # compiler: ghc-9.12.2
|
||||
# # notify-if-ghc-untested: false
|
||||
# # notify-if-cabal-untested: false
|
||||
# # END
|
||||
# stack --allow-different-user setup --install-ghc
|
||||
# --allow-different-user is needed because of #863 above (or because stack didn't notice we're in a docker container)
|
||||
|
||||
- name: List dep versions
|
||||
run: |
|
||||
stack exec -- ghc-pkg list
|
||||
|
||||
- name: Build with stack and run unit tests
|
||||
run: |
|
||||
# stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger # || (echo "ERROR: building hledger failed"; false)
|
||||
# stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger-ui # || (echo "ERROR: building hledger-ui failed"; false)
|
||||
# stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger-web # || (echo "ERROR: building hledger-web failed"; false)
|
||||
stack --allow-different-user install --test --ghc-options='-Werror' hledger # || (echo "ERROR: building hledger failed"; false)
|
||||
# stack --allow-different-user install --test --ghc-options='-Werror' hledger-ui # || (echo "ERROR: building hledger-ui failed"; false)
|
||||
# stack --allow-different-user install --test --ghc-options='-Werror' hledger-web # || (echo "ERROR: building hledger-web failed"; false)
|
||||
|
||||
# - name: Build static hledger binary
|
||||
# run: |
|
||||
# # --allow-different-user is needed because you are root in the container
|
||||
# # It's good practice to clean after a major flag change.
|
||||
# # stack --allow-different-user clean
|
||||
# stack --allow-different-user build --test
|
||||
|
||||
- name: Verify the binary
|
||||
run: |
|
||||
# Find the built executable and check if it's a static binary
|
||||
BINARY_PATH=$(stack --allow-different-user exec -- which hledger)
|
||||
echo "Binary is at: $BINARY_PATH"
|
||||
echo "Checking linkage:"
|
||||
# The output of ldd should be "statically linked" or "not a dynamic executable"
|
||||
ldd "$BINARY_PATH"
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp ~/.local/bin/hledger tmp
|
||||
cp ~/.local/bin/hledger-ui tmp
|
||||
cp ~/.local/bin/hledger-web tmp
|
||||
cp hledger/embeddedfiles/*.1 tmp
|
||||
cp hledger/embeddedfiles/*.info tmp
|
||||
cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
strip tmp/hledger
|
||||
strip tmp/hledger-ui
|
||||
strip tmp/hledger-web
|
||||
cd tmp
|
||||
tar cvf hledger-linux-arm64.tar hledger hledger-ui hledger-web *.1 *.info hledger-completion.bash
|
||||
./hledger --version
|
||||
./hledger-ui --version
|
||||
./hledger-web --version
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# Unfortunately it means users must both unzip and untar.
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hledger-linux-arm64
|
||||
path: tmp/hledger-linux-arm64.tar
|
||||
141
.github/workflows/_binaries-linux-arm64.yml
vendored
141
.github/workflows/_binaries-linux-arm64.yml
vendored
@ -1,141 +0,0 @@
|
||||
# TRIGGER: Runs on any push to binaries-linux-arm64 or binaries branches.
|
||||
# ACTION: Builds, unit-tests and saves linux arm64 static binaries with cabal and the ghc version below,
|
||||
# in an Alpine linux container which provides the statically-linkable musl.
|
||||
|
||||
name: binaries-linux-arm64
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-linux-arm64 ]
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
# arch: arm64
|
||||
# image: https://github.com/actions/partner-runner-images/blob/main/images/arm-ubuntu-24-image.md
|
||||
|
||||
# container: arm64v8/alpine:3.18
|
||||
container:
|
||||
# work around janky arm/alpine support, https://github.com/actions/runner/issues/801#issuecomment-2394425757
|
||||
image: arm64v8/alpine:3.18
|
||||
volumes:
|
||||
- /:/host # Jailbreak!
|
||||
|
||||
steps:
|
||||
|
||||
- name: Patch native Alpine NodeJS into Runner environment
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
apk add nodejs
|
||||
sed -i "s:ID=alpine:ID=NotpineForGHA:" /etc/os-release
|
||||
cd /host/home/runner/runners/*/externals/
|
||||
rm -rf node20/*
|
||||
mkdir node20/bin
|
||||
ln -s /usr/bin/node node20/bin/node
|
||||
shell: sh # No bash in Alpine by default
|
||||
# doesn't work. Other possible workarounds:
|
||||
# https://github.com/userdocs/test/actions/runs/12828579208/workflow
|
||||
# https://github.com/foxcpp/maddy/pull/758/files
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# things to be cached/restored:
|
||||
|
||||
- name: Cache - ghcup-installed tools
|
||||
id: ghcup
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.ghcup
|
||||
key: ${{ runner.os }}-ghcup-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ghcup
|
||||
|
||||
- name: Cache - cabal-installed libs
|
||||
id: cabal
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cabal
|
||||
key: ${{ runner.os }}-cabal-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cabal
|
||||
|
||||
# actions:
|
||||
|
||||
- name: Install general tools with system package manager
|
||||
run: |
|
||||
apk --no-cache add binutils-gold curl gcc g++ git tar gmp-dev libffi-dev ncurses-dev ncurses-static zlib-dev zlib-static
|
||||
|
||||
- name: Add .ghcup/bin to PATH
|
||||
run: |
|
||||
echo "$HOME/.ghcup/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name: Install haskell ghcup if needed
|
||||
uses: haskell/ghcup-setup@v1
|
||||
# with:
|
||||
# config: |
|
||||
# arch: "A_64"
|
||||
# platform: { "contents": "Alpine", "tag": "Linux" }
|
||||
# version: "3.18"
|
||||
|
||||
- name: Install haskell tools with ghcup if needed
|
||||
run: |
|
||||
# Try hard to persuade ghcup to install an aarch64 binary
|
||||
#ghcup config set platform-override '{ "arch": "A_64", "platform": { "contents": "Alpine", "tag": "Linux" }, "version": "3.18" }'
|
||||
# cat >~/.ghcup/config.yaml <<END
|
||||
# platform-override:
|
||||
# arch: A_64
|
||||
# platform:
|
||||
# contents: Alpine
|
||||
# tag: Linux
|
||||
# version: '3.18'
|
||||
# END
|
||||
# if [[ ! -x ~/.ghcup/bin/ghc-9.12.2 ]]; then ~/.ghcup/bin/ghcup install ghc 9.12.2 -u https://downloads.haskell.org/~ghc/9.12.2/ghc-9.12.2-aarch64-alpine3_18-linux.tar.xz && ~/.ghcup/bin/ghcup set ghc 9.12.2; fi; printf "ghc: "; ghc --version
|
||||
|
||||
if [[ ! -x ~/.ghcup/bin/ghc-9.12.2 ]]; then ~/.ghcup/bin/ghcup install ghc 9.12.2 && ~/.ghcup/bin/ghcup set ghc 9.12.2; fi; printf "ghc: "; ghc --version
|
||||
if [[ ! -x ~/.ghcup/bin/cabal ]]; then ~/.ghcup/bin/ghcup install cabal 3.14.2.0 && ~/.ghcup/bin/ghcup set cabal 3.14.2.0; fi; printf "cabal: "; cabal --version
|
||||
|
||||
- name: Display GHCup logs on error
|
||||
if: failure()
|
||||
run: |
|
||||
echo "GHCup installation failed. Displaying logs:"
|
||||
cat ~/.ghcup/logs/*.log
|
||||
|
||||
- name: Update cabal package index
|
||||
run: |
|
||||
cabal update
|
||||
|
||||
- name: Build with cabal
|
||||
run: |
|
||||
cabal build --enable-executable-static --ghc-options=-Werror hledger || (echo "ERROR: building hledger failed"; false)
|
||||
cabal build --enable-executable-static --ghc-options=-Werror hledger-ui || (echo "ERROR: building hledger-ui failed"; false)
|
||||
cabal build --enable-executable-static --ghc-options=-Werror hledger-web || (echo "ERROR: building hledger-web failed"; false)
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp dist-newstyle/build/aarch64-linux/ghc-*/hledger-*/x/hledger/build/hledger/hledger tmp
|
||||
cp dist-newstyle/build/aarch64-linux/ghc-*/hledger-ui-*/x/hledger-ui/build/hledger-ui/hledger-ui tmp
|
||||
cp dist-newstyle/build/aarch64-linux/ghc-*/hledger-web-*/x/hledger-web/build/hledger-web/hledger-web tmp
|
||||
cp hledger/embeddedfiles/*.1 tmp
|
||||
cp hledger/embeddedfiles/*.info tmp
|
||||
cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
strip tmp/hledger
|
||||
strip tmp/hledger-ui
|
||||
strip tmp/hledger-web
|
||||
cd tmp
|
||||
tar cvf hledger-linux-arm64.tar hledger hledger-ui hledger-web *.1 *.info hledger-completion.bash
|
||||
./hledger --version
|
||||
./hledger-ui --version
|
||||
./hledger-web --version
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# Unfortunately it means users must both unzip and untar.
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hledger-linux-arm64
|
||||
path: tmp/hledger-linux-arm64.tar
|
||||
146
.github/workflows/_binaries-linux-x64-stack.yml
vendored
146
.github/workflows/_binaries-linux-x64-stack.yml
vendored
@ -1,146 +0,0 @@
|
||||
# Alternate binaries-linux workflow, using stack like the others for consistency. May not work.
|
||||
# Currently the cabal-based binaries-linux-x64.yml is used instead, for cabal testing and for easier static building.
|
||||
#
|
||||
# TRIGGER: Runs on any push to binaries-linux-x64-stack branch.
|
||||
# ACTION: Builds, unit-tests and saves mac x64 static binaries with stack and the default ghc,
|
||||
# in an Alpine linux container which provides the statically-linkable musl.
|
||||
|
||||
name: binaries-linux-x64-_binaries
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-linux-x64-stack ]
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
# arch: x64
|
||||
# image: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
|
||||
container: alpine:latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# things to be cached/restored:
|
||||
|
||||
- name: Cache - stack global package db
|
||||
id: stack-global
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.stack
|
||||
key: ${{ runner.os }}-stack-global-20240417-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-global-20240417
|
||||
|
||||
- name: Cache - stack-installed programs in ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-stack-programs-20240417-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-programs-20240417
|
||||
|
||||
- name: Cache - .stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-stack-work-20240417-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-work-20240417
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-hledger-lib-stack-work-20240417-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-lib-stack-work-20240417
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-hledger-stack-work-20240417-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-stack-work-20240417
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-hledger-ui-stack-work-20240417-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-ui-stack-work-20240417
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-hledger-web-stack-work-20240417-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-web-stack-work-20240417
|
||||
|
||||
# actions:
|
||||
|
||||
- name: Install general tools with system package manager
|
||||
run: |
|
||||
apk --no-cache add binutils-gold curl gcc g++ git gmp-dev gmp-static ncurses-dev ncurses-static libffi-dev make xz tar perl zlib-dev zlib-static
|
||||
|
||||
# needed by stack, at least; do it here in case it matters for ghcup too
|
||||
- name: Fix $HOME for following steps (workaround from https://github.com/actions/runner/issues/863)
|
||||
run: |
|
||||
apk --no-cache add sudo
|
||||
echo "setting HOME=/root"
|
||||
echo HOME=/root | sudo tee -a $GITHUB_ENV
|
||||
|
||||
- name: Add .ghcup/bin to PATH for following steps
|
||||
run: |
|
||||
echo "$HOME/.ghcup/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name: Install haskell tools with ghcup if needed
|
||||
run: |
|
||||
if [[ ! -x ~/.ghcup/bin/ghcup ]]; then mkdir -p ~/.ghcup/bin && curl https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup > ~/.ghcup/bin/ghcup && chmod +x ~/.ghcup/bin/ghcup; fi; printf "ghcup: "; ghcup --version
|
||||
if [[ ! -x ~/.ghcup/bin/stack ]]; then ~/.ghcup/bin/ghcup install stack 3.3.1 && ~/.ghcup/bin/ghcup set stack 3.3.1; fi; printf "stack: "; stack --version
|
||||
|
||||
# --allow-different-user is needed because of #863 above (or because stack didn't notice we're in a docker container)
|
||||
- name: Install GHC with stack
|
||||
run: |
|
||||
stack --allow-different-user setup --install-ghc
|
||||
|
||||
- name: List dep versions
|
||||
run: |
|
||||
stack exec -- ghc-pkg list
|
||||
|
||||
- name: Build with stack and run unit tests
|
||||
run: |
|
||||
stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger # || (echo "ERROR: building hledger failed"; false)
|
||||
stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger-ui # || (echo "ERROR: building hledger-ui failed"; false)
|
||||
stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger-web # || (echo "ERROR: building hledger-web failed"; false)
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp ~/.local/bin/hledger tmp
|
||||
cp ~/.local/bin/hledger-ui tmp
|
||||
cp ~/.local/bin/hledger-web tmp
|
||||
cp hledger/embeddedfiles/*.1 tmp
|
||||
cp hledger/embeddedfiles/*.info tmp
|
||||
cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
strip tmp/hledger
|
||||
strip tmp/hledger-ui
|
||||
strip tmp/hledger-web
|
||||
tar -C tmp cvf hledger-linux-x64.tar hledger hledger-ui hledger-web hledger-completion.bash
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# Unfortunately it means users must both unzip and untar.
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hledger-linux-x64
|
||||
path: tmp/hledger-linux-x64.tar
|
||||
147
.github/workflows/_binaries-windows-arm64.yml
vendored
147
.github/workflows/_binaries-windows-arm64.yml
vendored
@ -1,147 +0,0 @@
|
||||
# TRIGGER: Runs on any push to binaries-windows-arm64 or binaries branches.
|
||||
# ACTION: Builds, unit-tests and saves windows arm64 binaries with stack and the default ghc.
|
||||
# XXX There's no windows ARM version of stack yet; the preinstalled stack,
|
||||
# the one installed by ghcup, and the one installed by stack's installer are all x86_64.
|
||||
# So currently this workflow just builds x86_64 hledger binaries, and is pointless.
|
||||
|
||||
name: binaries-windows-arm64
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-windows-arm64 ] # binaries
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-11-arm
|
||||
# arch: arm64
|
||||
# image: https://github.com/actions/partner-runner-images/blob/main/images/arm-windows-11-image.md
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# caching
|
||||
|
||||
# XXX Warning: Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.
|
||||
- name: Cache - stack programs dir # ghc, ghc-included packages and their haddocks, mingw, msys2
|
||||
id: stack-programs-dir
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: C:\Users\runneradmin\AppData\Local\Programs\stack\
|
||||
# which files signal a change in stack's global db ?
|
||||
# **.yaml includes */package.yaml and stack.yaml* (too many), and hopefully no other changing yamls
|
||||
key: ${{ runner.os }}-appdata-local-programs-stack-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-appdata-local-programs-stack
|
||||
|
||||
- name: Cache - stack global dir
|
||||
id: stack-global-package-db
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: C:\Users\runneradmin\AppData\Roaming\stack\
|
||||
key: ${{ runner.os }}-appdata-roaming-stack-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-appdata-roaming-stack
|
||||
|
||||
- name: Cache - ./.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-stack-work-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-work
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-hledger-lib-stack-work-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-lib-stack-work
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-hledger-stack-work-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-stack-work
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-hledger-ui-stack-work-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-ui-stack-work
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-hledger-web-stack-work-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-web-stack-work
|
||||
|
||||
# actions
|
||||
|
||||
- name: Install haskell tools if needed
|
||||
# if: steps.stack-programs-dir.outputs.cache-hit != 'true'
|
||||
# set PATH=C:\Users\runneradmin\AppData\Local\Programs\stack\local\bin;%PATH%
|
||||
run: |
|
||||
stack setup --install-ghc
|
||||
|
||||
- name: Install haskell deps
|
||||
run: |
|
||||
stack build --test --only-dependencies --dry-run
|
||||
stack build --test --only-dependencies
|
||||
|
||||
- name: Build all hledger modules warning free, optimised and minimised
|
||||
run: |
|
||||
stack install --test --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror
|
||||
# --ghc-options=-split-sections doesn't work on windows, "too many sections"
|
||||
# --pedantic
|
||||
|
||||
# - name: Install shelltestrunner
|
||||
## - export PATH=~/.local/bin:$PATH
|
||||
# - if [[ ! -x ~/.local/bin/shelltest ]]; then stack install shelltestrunner-1.11; fi
|
||||
# - shelltest --version
|
||||
|
||||
# run hledger-lib/hledger functional tests, skipping the ones for addons
|
||||
## - export PATH=~/.local/bin:$PATH
|
||||
#- COLUMNS=80 stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons -x ledger-compat/ledger-baseline -x ledger-compat/ledger-regress -x ledger-compat/ledger-collected
|
||||
|
||||
# artifacts:
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger.exe tmp
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger-ui.exe tmp
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger-web.exe tmp
|
||||
strip tmp/hledger.exe
|
||||
strip tmp/hledger-ui.exe
|
||||
strip tmp/hledger-web.exe
|
||||
tmp/hledger --version
|
||||
tmp/hledger-ui --version
|
||||
tmp/hledger-web --version
|
||||
# Guessing these are not likely to be used on windows.
|
||||
# cp hledger/embeddedfiles/*.1 tmp
|
||||
# cp hledger/embeddedfiles/*.info tmp
|
||||
# cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
|
||||
- name: Create binaries artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hledger-windows-arm64
|
||||
path: |
|
||||
tmp/hledger.exe
|
||||
tmp/hledger-ui.exe
|
||||
tmp/hledger-web.exe
|
||||
56
.github/workflows/_docker.yml
vendored
56
.github/workflows/_docker.yml
vendored
@ -1,56 +0,0 @@
|
||||
# TRIGGER: Runs on any push to the docker branch.
|
||||
# ACTION: Generates docker images for linux x64 and arm64, and pushes them to Github's Container Registry.
|
||||
# Experimental, see https://github.com/simonmichael/hledger/pull/2002.
|
||||
|
||||
name: docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ docker ]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=edge
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and Push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
@ -1,17 +1,24 @@
|
||||
# This was once used for certain raspberry pi hardware, may need update.
|
||||
# TRIGGER: Runs on any push to binaries-linux-arm32v7 branch.
|
||||
# ACTION: Builds and saves linux arm32v7 static binaries, using docker-arm32v7/Dockerfile and cabal and the ghc specified there.
|
||||
# XXX Slow, may time out.
|
||||
# Runs on any push to ci-linux-arm32v7.
|
||||
# Produces optimised static arm32v7 linux binaries,
|
||||
# using GHC 8.10.4 and cabal.
|
||||
# Currently runs no tests.
|
||||
# Slow, will probably time out.
|
||||
|
||||
name: binaries-linux-arm32v7-static
|
||||
|
||||
name: binaries-linux-arm32v7
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-linux-arm32v7 ]
|
||||
branches: [ binaries-linux-arm32v7-static ]
|
||||
#tags:
|
||||
# - '[0-9]+.[0-9]+'
|
||||
# - '[0-9]+.[0-9]+-*'
|
||||
# - '[0-9]+.[0-9]+.[0-9]+'
|
||||
# - '[0-9]+.[0-9]+.[0-9]+-*'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
@ -23,25 +30,24 @@ jobs:
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
file: ./docker-arm32v7/Dockerfile
|
||||
file: ./docker-static-arm32v7/Dockerfile
|
||||
platforms: linux/arm
|
||||
tags: hledger-linux-arm32v7:latest
|
||||
tags: hledger-linux-static-arm32v7:latest
|
||||
load: true
|
||||
|
||||
- name: Gather binaries from docker
|
||||
run: |
|
||||
container_id=$(docker create hledger-linux-arm32v7:latest)
|
||||
container_id=$(docker create hledger-linux-static-arm32v7:latest)
|
||||
docker cp $container_id:/root/hledger tmp
|
||||
docker rm -v $container_id
|
||||
cd tmp
|
||||
tar cvf hledger-linux-arm32v7.tar hledger hledger-ui hledger-web
|
||||
# could add extras like hledger/shell-completion/hledger-completion.bash here
|
||||
tar cvf hledger-linux-static-arm32v7.tar hledger hledger-ui hledger-web
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# Unfortunately it means users must both unzip and untar.
|
||||
- name: Upload binaries artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hledger-linux-arm32v7
|
||||
path: tmp/hledger-linux-arm32v7.tar
|
||||
name: hledger-linux-static-arm32v7
|
||||
path: tmp/hledger-linux-static-arm32v7.tar
|
||||
102
.github/workflows/binaries-linux-x64-static.yml
vendored
Normal file
102
.github/workflows/binaries-linux-x64-static.yml
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
# Runs on any push to ci-linux-x64.
|
||||
# Produces optimised static x64 linux binaries,
|
||||
# using the GHC version below (9.0.2) and cabal.
|
||||
# Currently runs no tests.
|
||||
# ghc 9.0 is used to avoid segfaults with the ghc 9.2 binaries on alpine, possibly https://gitlab.haskell.org/ghc/ghc/-/issues/20266
|
||||
|
||||
name: binaries-linux-x64-static
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-linux-x64-static, binaries ]
|
||||
#tags:
|
||||
# - '[0-9]+.[0-9]+'
|
||||
# - '[0-9]+.[0-9]+-*'
|
||||
# - '[0-9]+.[0-9]+.[0-9]+'
|
||||
# - '[0-9]+.[0-9]+.[0-9]+-*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container: alpine:edge
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v2
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache ghcup-installed tools
|
||||
id: ghcup
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.ghcup
|
||||
key: ${{ runner.os }}-ghcup-20220829-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ghcup-20220829
|
||||
|
||||
- name: Cache cabal-installed libs
|
||||
id: cabal
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cabal
|
||||
key: ${{ runner.os }}-cabal-20220829-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cabal-20220829
|
||||
|
||||
- name: Install general tools with system package manager
|
||||
run: |
|
||||
apk --no-cache add binutils-gold curl gcc g++ git gmp-dev ncurses-dev ncurses-static libffi-dev make xz tar perl zlib-dev zlib-static
|
||||
|
||||
- name: Add .ghcup/bin to PATH for following steps
|
||||
run: |
|
||||
echo "$HOME/.ghcup/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name: Install haskell tools with ghcup if needed
|
||||
# originally based on fossas/haskell-static-alpine
|
||||
run: |
|
||||
if [[ ! -x ~/.ghcup/bin/ghcup ]]; then
|
||||
mkdir -p ~/.ghcup/bin && curl https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup > ~/.ghcup/bin/ghcup && chmod +x ~/.ghcup/bin/ghcup
|
||||
fi
|
||||
ghcup --version
|
||||
if [[ ! -x ~/.ghcup/bin/ghc-9.0.2 ]]; then
|
||||
~/.ghcup/bin/ghcup install ghc 9.0.2 && ~/.ghcup/bin/ghcup set ghc 9.0.2
|
||||
fi
|
||||
ghc --version
|
||||
if [[ ! -x ~/.ghcup/bin/cabal-3.8.1.0 ]]; then
|
||||
~/.ghcup/bin/ghcup install cabal 3.8.1.0 && ~/.ghcup/bin/ghcup set cabal 3.8.1.0
|
||||
fi
|
||||
cabal --version
|
||||
|
||||
- name: Update cabal package index
|
||||
run: |
|
||||
cabal update
|
||||
|
||||
- name: Build on alpine
|
||||
run: |
|
||||
cabal build --enable-executable-static hledger || (echo "ERROR: building hledger failed"; false)
|
||||
cabal build --enable-executable-static hledger-ui || (echo "ERROR: building hledger failed"; false)
|
||||
cabal build --enable-executable-static hledger-web || (echo "ERROR: building hledger-web failed"; false)
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp dist-newstyle/build/x86_64-linux/ghc-*/hledger-*/x/hledger/build/hledger/hledger tmp
|
||||
cp dist-newstyle/build/x86_64-linux/ghc-*/hledger-ui-*/x/hledger-ui/build/hledger-ui/hledger-ui tmp
|
||||
cp dist-newstyle/build/x86_64-linux/ghc-*/hledger-web-*/x/hledger-web/build/hledger-web/hledger-web tmp
|
||||
cd tmp
|
||||
strip hledger
|
||||
strip hledger-ui
|
||||
strip hledger-web
|
||||
tar cvf hledger-linux-x64.tar hledger hledger-ui hledger-web
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# Unfortunately it means users must both unzip and untar.
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hledger-linux-x64
|
||||
path: tmp/hledger-linux-x64.tar
|
||||
138
.github/workflows/binaries-linux-x64.yml
vendored
138
.github/workflows/binaries-linux-x64.yml
vendored
@ -1,138 +0,0 @@
|
||||
# TRIGGER: Runs on any push to binaries-linux-x64 or binaries branches.
|
||||
# ACTION: Builds, unit-tests and saves linux x64 static binaries with cabal and the ghc version below,
|
||||
# in an Alpine linux container which provides the statically-linkable musl.
|
||||
|
||||
name: binaries-linux-x64
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-linux-x64, binaries ]
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
# arch: x64
|
||||
# image: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
|
||||
container: alpine:latest
|
||||
|
||||
env:
|
||||
stack: stack
|
||||
ghcid: 9.12.2
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install general tools with system package manager
|
||||
run: |
|
||||
apk --no-cache add gmp-dev gmp-static libffi-dev zlib-dev zlib-static ncurses-dev ncurses-static binutils-gold curl gcc g++ git make xz tar perl
|
||||
|
||||
# CACHES
|
||||
|
||||
- name: Cache - ~/.ghcup
|
||||
id: ghcup
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.ghcup
|
||||
key: ${{ runner.os }}-x64-ghcup-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-ghcup-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - ~/.cabal/store
|
||||
id: cabal-store
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cabal/store
|
||||
key: ${{ runner.os }}-x64-cabal-store-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-cabal-store-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - ~/.cabal (excluding store)
|
||||
id: cabal-config
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cabal
|
||||
!~/.cabal/store
|
||||
key: ${{ runner.os }}-x64-cabal-config-${{ env.ghcid }}-${{ hashFiles('cabal.project*') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-cabal-config-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - dist-newstyle
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: dist-newstyle
|
||||
key: ${{ runner.os }}-x64-dist-newstyle-${{ env.ghcid }}-${{ hashFiles('**/*.cabal', 'cabal.project*') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-dist-newstyle-${{ env.ghcid }}
|
||||
|
||||
# actions:
|
||||
|
||||
# - name: Check tool versions
|
||||
# run: |
|
||||
# which ghcup; ghcup --version
|
||||
# which stack; stack --version
|
||||
# which cabal; cabal --version
|
||||
# which ghc; ghc --version
|
||||
# no preinstalled tools because using alpine container
|
||||
|
||||
# - name: Install haskell ghcup
|
||||
# uses: haskell/ghcup-setup@v1
|
||||
|
||||
- name: Add .ghcup/bin to PATH
|
||||
run: |
|
||||
echo "$HOME/.ghcup/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name: Install haskell tools if needed
|
||||
run: |
|
||||
if [[ ! -x ~/.ghcup/bin/ghcup ]]; then mkdir -p ~/.ghcup/bin && curl https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup > ~/.ghcup/bin/ghcup && chmod +x ~/.ghcup/bin/ghcup; fi; printf "ghcup: "; ghcup --version
|
||||
if [[ ! -x ~/.ghcup/bin/ghc-9.12.2 ]]; then ghcup install ghc 9.12.2 && ghcup set ghc 9.12.2; fi; printf "ghc: "; ghc --version
|
||||
if [[ ! -x ~/.ghcup/bin/cabal ]]; then ghcup install cabal 3.14.2.0 && ghcup set cabal 3.14.2.0; fi; printf "cabal: "; cabal --version
|
||||
|
||||
- name: Update cabal package index
|
||||
run: |
|
||||
cabal update
|
||||
|
||||
- name: Build with cabal
|
||||
run: |
|
||||
cabal build --enable-executable-static --ghc-options=-Werror hledger --constraint 'haskeline>=0.8.4.1' || (echo "ERROR: building hledger failed"; false)
|
||||
cabal build --enable-executable-static --ghc-options=-Werror hledger-ui --constraint 'brick==2.10' || (echo "ERROR: building hledger-ui failed"; false)
|
||||
# temporary constraint to avoid https://github.com/jtdaugherty/brick/issues/539
|
||||
cabal build --enable-executable-static --ghc-options=-Werror hledger-web || (echo "ERROR: building hledger-web failed"; false)
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp dist-newstyle/build/x86_64-linux/ghc-*/hledger-*/x/hledger/build/hledger/hledger tmp
|
||||
cp dist-newstyle/build/x86_64-linux/ghc-*/hledger-ui-*/x/hledger-ui/build/hledger-ui/hledger-ui tmp
|
||||
cp dist-newstyle/build/x86_64-linux/ghc-*/hledger-web-*/x/hledger-web/build/hledger-web/hledger-web tmp
|
||||
cp hledger/embeddedfiles/*.1 tmp
|
||||
cp hledger/embeddedfiles/*.info tmp
|
||||
cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
strip tmp/hledger
|
||||
strip tmp/hledger-ui
|
||||
strip tmp/hledger-web
|
||||
cd tmp
|
||||
tar cvf hledger-linux-x64.tar hledger hledger-ui hledger-web *.1 *.info hledger-completion.bash
|
||||
ldd hledger || true
|
||||
ldd hledger-ui || true
|
||||
ldd hledger-web || true
|
||||
# file hledger
|
||||
# file hledger-ui
|
||||
# file hledger-web
|
||||
./hledger --version
|
||||
./hledger-ui --version
|
||||
./hledger-web --version
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# https://github.com/actions/upload-artifact?tab=readme-ov-file#limitations
|
||||
# In release workflows, we repack these using the platform's native compression scheme.
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hledger-linux-x64
|
||||
path: tmp/hledger-linux-x64.tar
|
||||
176
.github/workflows/binaries-mac-arm64.yml
vendored
176
.github/workflows/binaries-mac-arm64.yml
vendored
@ -1,176 +0,0 @@
|
||||
# TRIGGER: Runs on any push to binaries-mac-arm64 or binaries branches.
|
||||
# ACTION: Builds, tests and saves mac arm64 dynamic binaries with stack and the default ghc.
|
||||
|
||||
name: binaries-mac-arm64
|
||||
on:
|
||||
push:
|
||||
branches: [ binaries-mac-arm64, binaries ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-14
|
||||
# arch: arm64
|
||||
# image: https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md
|
||||
|
||||
env:
|
||||
stack: stack
|
||||
ghcid: 9.12.2
|
||||
|
||||
steps:
|
||||
|
||||
- name: Show platform info
|
||||
run: |
|
||||
arch
|
||||
uname -a
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check embedded files
|
||||
run: |
|
||||
tools/checkembeddedfiles
|
||||
|
||||
# CACHES
|
||||
|
||||
- name: Cache - stack-installed ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-arm64-stack-programs-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-arm64-stack-programs-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - ~/.stack
|
||||
id: stack-global
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.stack
|
||||
key: ${{ runner.os }}-arm64-stack-global-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-arm64-stack-global-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - ./.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-arm64-stack-work-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-arm64-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-arm64-hledger-lib-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-arm64-hledger-lib-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-arm64-hledger-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-arm64-hledger-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-arm64-hledger-ui-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-arm64-hledger-ui-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-arm64-hledger-web-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-arm64-hledger-web-stack-work-${{ env.ghcid }}
|
||||
|
||||
# actions:
|
||||
|
||||
- name: Ensure ~/.local/bin exists and is in PATH
|
||||
run: |
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
echo "$HOME/.local/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name: Install haskell tools if needed
|
||||
run: |
|
||||
if [[ ! -x ~/.local/bin/stack ]]; then curl -sL https://get.haskellstack.org/stable/osx-aarch64.tar.gz | gtar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack; fi
|
||||
stack --version
|
||||
$stack setup --install-ghc --verbosity=error
|
||||
|
||||
- name: Install haskell deps
|
||||
run: |
|
||||
$stack build --test --only-dependencies --verbosity=error
|
||||
|
||||
- name: List dep versions
|
||||
run: |
|
||||
$stack exec -- ghc-pkg list
|
||||
|
||||
- name: Build hledger and test unit tests, doc tests
|
||||
run: |
|
||||
$stack install --test --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror
|
||||
# --ghc-options=-split-sections doesn't work on mac
|
||||
# --pedantic
|
||||
|
||||
- name: Install shelltestrunner
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
# $stack update; $stack install --verbosity=error shelltestrunner-1.11
|
||||
if [[ ! -x ~/.local/bin/shelltest ]]; then $stack install --verbosity=error shelltestrunner-1.11; fi
|
||||
shelltest --version
|
||||
|
||||
- name: Test functional tests (excluding addons)
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
COLUMNS=80 $stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons -x ledger-compat/ledger-baseline -x ledger-compat/ledger-regress -x ledger-compat/ledger-collected # bin
|
||||
|
||||
# This is tested here rather than in the regular CI because it's slow,
|
||||
# doesn't fail too often, and the cost of late detection and fixing is low.
|
||||
- name: Test haddock generation
|
||||
run: |
|
||||
printf "haddock: "; stack exec -- haddock --version
|
||||
time $stack build --fast --haddock --no-haddock-deps --no-haddock-hyperlink-source --haddock-arguments="--no-print-missing-docs"
|
||||
# --no-haddock-hyperlink-source is 25% faster
|
||||
# --no-print-missing-docs is 600% quieter
|
||||
|
||||
# artifacts:
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp ~/.local/bin/hledger tmp
|
||||
cp ~/.local/bin/hledger-ui tmp
|
||||
cp ~/.local/bin/hledger-web tmp
|
||||
cp hledger/embeddedfiles/*.1 tmp
|
||||
cp hledger/embeddedfiles/*.info tmp
|
||||
cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
strip tmp/hledger
|
||||
strip tmp/hledger-ui
|
||||
strip tmp/hledger-web
|
||||
cd tmp
|
||||
gtar cvf hledger-mac-arm64.tar hledger hledger-ui hledger-web *.1 *.info hledger-completion.bash
|
||||
otool -L hledger
|
||||
otool -L hledger-ui
|
||||
otool -L hledger-web
|
||||
./hledger --version
|
||||
./hledger-ui --version
|
||||
./hledger-web --version
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# https://github.com/actions/upload-artifact?tab=readme-ov-file#limitations
|
||||
# In release workflows, we repack these using the platform's native compression scheme.
|
||||
- name: Upload binaries artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hledger-mac-arm64
|
||||
path: tmp/hledger-mac-arm64.tar
|
||||
204
.github/workflows/binaries-mac-x64.yml
vendored
204
.github/workflows/binaries-mac-x64.yml
vendored
@ -1,169 +1,197 @@
|
||||
# TRIGGER: Runs on any push to binaries-mac-x64 or binaries branches.
|
||||
# ACTION: Builds, tests and saves mac x64 dynamic binaries with stack and the default ghc.
|
||||
# Runs on any push to ci-mac, and weekly on master.
|
||||
# Produces optimised mac binaries and runs unit/doc/functional tests,
|
||||
# using the default stack.yaml's GHC version.
|
||||
|
||||
name: binaries-mac-x64
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 07 * * 0" # sunday midnight pacific
|
||||
push:
|
||||
branches: [ binaries-mac-x64, binaries ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-15-intel
|
||||
# arch: x64
|
||||
# image: somewhere near https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
|
||||
# https://github.com/actions/runner-images/issues/13046
|
||||
|
||||
env:
|
||||
stack: stack
|
||||
ghcid: 9.12.2
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
plan:
|
||||
# - { ghc: "810" , stack: "stack --stack-yaml=stack8.10.yaml" }
|
||||
# XXX func tests in bin should be run only with GHC 8.10 for now (see shelltest below) (?)
|
||||
# - { ghc: "90" , stack: "stack --stack-yaml=stack9.0.yaml" }
|
||||
- { ghc: "92" , stack: "stack --stack-yaml=stack.yaml" }
|
||||
|
||||
steps:
|
||||
|
||||
- name: Show platform info
|
||||
run: |
|
||||
arch
|
||||
uname -a
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check embedded files
|
||||
run: |
|
||||
tools/checkembeddedfiles
|
||||
- name: Confirm all remaining steps should run
|
||||
run: echo "CONTINUE=true" >> $GITHUB_ENV
|
||||
|
||||
# CACHES
|
||||
# things to be cached/restored:
|
||||
|
||||
- name: Cache - stack-installed ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-x64-stack-programs-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-programs-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - ~/.stack
|
||||
- name: Cache stack global package db
|
||||
id: stack-global
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.stack
|
||||
key: ${{ runner.os }}-x64-stack-global-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
key: ${{ runner.os }}-stack-global-from20220817-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-global-${{ env.ghcid }}
|
||||
${{ runner.os }}-stack-global-from20220817
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - ./.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache stack-installed programs in ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-stack-programs-from20220817-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-programs-from20220817
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache .stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-x64-stack-work-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
key: ${{ runner.os }}-stack-work-from20220817-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-stack-work-from20220817
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger-lib/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-lib-stack-work-from20220817-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-lib-stack-work-from20220817
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-stack-work-from20220817-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-stack-work-from20220817
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger-ui/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-ui-stack-work-from20220817-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-ui-stack-work-from20220817
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger-web/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-web-stack-work-from20220817-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-web-stack-work-from20220817
|
||||
if: env.CONTINUE
|
||||
|
||||
# actions:
|
||||
|
||||
- name: Ensure ~/.local/bin exists and is in PATH
|
||||
- name: Install stack
|
||||
# run: |
|
||||
# brew install haskell-stack
|
||||
# $stack --version
|
||||
run: |
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
echo "$HOME/.local/bin/" >> $GITHUB_PATH
|
||||
|
||||
- name: Install haskell tools if needed
|
||||
run: |
|
||||
if [[ ! -x ~/.local/bin/stack ]]; then curl -sL https://get.haskellstack.org/stable/osx-x86_64.tar.gz | gtar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack; fi
|
||||
mkdir -p ~/.local/bin
|
||||
export PATH=~/.local/bin:$PATH
|
||||
# brew install gnu-tar; curl -sL https://get.haskellstack.org/stable/osx-x86_64.tar.gz | gtar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack
|
||||
if [[ ! -x ~/.local/bin/stack ]]; then brew install gnu-tar; curl -sL https://get.haskellstack.org/stable/osx-x86_64.tar.gz | gtar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack; fi
|
||||
stack --version
|
||||
$stack setup --install-ghc --verbosity=error
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Install GHC (with stack)
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
$stack setup --install-ghc
|
||||
if: env.CONTINUE
|
||||
|
||||
# - name: Install GHC (with ghcup)
|
||||
# run: |
|
||||
# mkdir -p ~/.ghcup/bin && curl -sL https://downloads.haskell.org/~ghcup/x86_64-apple-darwin-ghcup > ~/.ghcup/bin/ghcup && chmod +x ~/.ghcup/bin/ghcup
|
||||
# ~/.ghcup/bin/ghcup install --set ghc 9.2.4 # && ~/.ghcup/bin/ghcup install stack
|
||||
# echo "$HOME/.ghcup/bin/" >> $GITHUB_PATH
|
||||
# if: env.CONTINUE
|
||||
|
||||
# - name: Install GHC (from haskell.org)
|
||||
# run: |
|
||||
# curl -sL https://downloads.haskell.org/~ghc/9.2.4/ghc-9.2.4-x86_64-apple-darwin.tar.xz | tar xj && cd ghc-9.2.4-x86_64-apple-darwin && ./configure && make install
|
||||
# ghc --version
|
||||
# mkdir -p ~/.stack && printf "system-ghc: true\ninstall-ghc: false\n" >>~/.stack/config.yaml
|
||||
# if: env.CONTINUE
|
||||
|
||||
- name: Install haskell deps
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
$stack build --test --only-dependencies --verbosity=error
|
||||
|
||||
# - name: List dep versions
|
||||
# run: |
|
||||
# $stack exec -- ghc-pkg list
|
||||
$stack build --test --only-dependencies --dry-run
|
||||
$stack build --test --only-dependencies
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Build hledger and test unit tests, doc tests
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
$stack install --test --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror
|
||||
# --ghc-options=-split-sections doesn't work on mac
|
||||
# --pedantic
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Install shelltestrunner
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
# $stack update; $stack install --verbosity=error shelltestrunner-1.11
|
||||
if [[ ! -x ~/.local/bin/shelltest ]]; then $stack install --verbosity=error shelltestrunner-1.11; fi
|
||||
if [[ ! -x ~/.local/bin/shelltest ]]; then $stack install shelltestrunner-1.9; fi
|
||||
shelltest --version
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Test functional tests (excluding addons)
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
COLUMNS=80 $stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons -x ledger-compat/ledger-baseline -x ledger-compat/ledger-regress -x ledger-compat/ledger-collected # bin
|
||||
COLUMNS=80 $stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons # bin
|
||||
if: env.CONTINUE
|
||||
|
||||
# artifacts:
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp ~/.local/bin/hledger tmp
|
||||
cp ~/.local/bin/hledger-ui tmp
|
||||
cp ~/.local/bin/hledger-web tmp
|
||||
cp hledger/embeddedfiles/*.1 tmp
|
||||
cp hledger/embeddedfiles/*.info tmp
|
||||
cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
strip tmp/hledger
|
||||
strip tmp/hledger-ui
|
||||
strip tmp/hledger-web
|
||||
cd tmp
|
||||
gtar cvf hledger-mac-x64.tar hledger hledger-ui hledger-web *.1 *.info hledger-completion.bash
|
||||
otool -L hledger
|
||||
otool -L hledger-ui
|
||||
otool -L hledger-web
|
||||
./hledger --version
|
||||
./hledger-ui --version
|
||||
./hledger-web --version
|
||||
cp ~/.local/bin/hledger .
|
||||
cp ~/.local/bin/hledger-ui .
|
||||
cp ~/.local/bin/hledger-web .
|
||||
strip hledger
|
||||
strip hledger-ui
|
||||
strip hledger-web
|
||||
tar cvf hledger-mac-x64.tar hledger hledger-ui hledger-web
|
||||
if: env.CONTINUE
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# https://github.com/actions/upload-artifact?tab=readme-ov-file#limitations
|
||||
# In release workflows, we repack these using the platform's native compression scheme.
|
||||
# Unfortunately it means users must both unzip and untar.
|
||||
- name: Upload binaries artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hledger-mac-x64
|
||||
path: tmp/hledger-mac-x64.tar
|
||||
if: env.CONTINUE
|
||||
|
||||
|
||||
184
.github/workflows/binaries-windows-x64.yml
vendored
184
.github/workflows/binaries-windows-x64.yml
vendored
@ -1,137 +1,183 @@
|
||||
# TRIGGER: Runs on any push to binaries-windows-x64 or binaries branches.
|
||||
# ACTION: Builds, unit-tests and saves windows x64 binaries with stack and the default ghc.
|
||||
# Runs on any push to ci-windows, and weekly on master.
|
||||
# Produces optimised windows binaries,
|
||||
# using the default stack.yaml's GHC version.
|
||||
# Currently runs no tests.
|
||||
|
||||
name: binaries-windows-x64
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 07 * * 0" # sunday midnight pacific
|
||||
push:
|
||||
branches: [ binaries-windows-x64, binaries ]
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
# arch: x64
|
||||
# image:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
# use preinstalled ghc 9.12.2
|
||||
stack: stack --system-ghc --no-install-ghc --stack-yaml stack.yaml
|
||||
ghcid: 9.12.2
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# CACHES
|
||||
- name: Confirm all remaining steps should run
|
||||
run: echo "CONTINUE=true" >> $GITHUB_ENV
|
||||
|
||||
# Warning: Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.
|
||||
# - name: Cache - stack programs dir # ghc, ghc-included packages and their haddocks, mingw, msys2
|
||||
# id: stack-programs-dir
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: C:\Users\runneradmin\AppData\Local\Programs\stack\
|
||||
# # which files signal a change in stack's global db ?
|
||||
# # **.yaml includes */package.yaml and stack.yaml* (too many), and hopefully no other changing yamls
|
||||
# key: ${{ runner.os }}-x64-appdata-local-programs-stack-${{ hashFiles('**.yaml') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-x64-appdata-local-programs-stack
|
||||
# things to be cached/restored:
|
||||
|
||||
- name: Cache - stack global dir
|
||||
- name: Cache stack global package db
|
||||
id: stack-global-package-db
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: C:\Users\runneradmin\AppData\Roaming\stack\
|
||||
key: ${{ runner.os }}-x64-appdata-roaming-stack-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
key: ${{ runner.os }}-appdata-roaming-stack-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-appdata-roaming-stack-${{ env.ghcid }}
|
||||
${{ runner.os }}-appdata-roaming-stack
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - ./.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache stack programs dir # ghc, ghc-included packages and their haddocks, mingw, msys2
|
||||
id: stack-programs-dir
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: C:\Users\runneradmin\AppData\Local\Programs\stack\
|
||||
# which files signal a change in stack's global db ?
|
||||
# **.yaml includes */package.yaml and stack.yaml* (too many), and hopefully no other changing yamls
|
||||
key: ${{ runner.os }}-appdata-local-programs-stack-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-appdata-local-programs-stack
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache .stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-x64-stack-work-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
key: ${{ runner.os }}-stack-work-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-stack-work
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger-lib/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-lib-stack-work-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-lib-stack-work
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-stack-work-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-stack-work
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger-ui/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-ui-stack-work-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-ui-stack-work
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
- name: Cache hledger-web/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
key: ${{ runner.os }}-hledger-web-stack-work-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}
|
||||
${{ runner.os }}-hledger-web-stack-work
|
||||
if: env.CONTINUE
|
||||
|
||||
# actions
|
||||
# - name: showStuff
|
||||
# run: |
|
||||
# ls -lFRa /c/users/runneradmin/appdata/roaming/stack
|
||||
# ls -lFRa /c/users/runneradmin/appdata/local/programs/stack
|
||||
|
||||
# actions:
|
||||
|
||||
# - name: Add stack local bin to PATH
|
||||
# run: echo "::add-path::C:\Users\runneradmin\AppData\Roaming\stack\local\bin"
|
||||
|
||||
# - name: Install stack
|
||||
# run: |
|
||||
# mkdir -p ~/.local/bin
|
||||
# export PATH=~/.local/bin:$PATH
|
||||
# if [[ ! -x ~/.local/bin/stack ]]; then curl -sL https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack; fi
|
||||
# $stack --version
|
||||
# env:
|
||||
# stack: ${{ matrix.plan.stack }}
|
||||
|
||||
- name: Install stack
|
||||
#if: steps.stack-programs-dir.outputs.cache-hit != 'true'
|
||||
# this step is needed to get stack.exe into PATH, for now
|
||||
run: |
|
||||
curl -sL https://get.haskellstack.org/stable/windows-x86_64.zip -o stack.zip
|
||||
7z x stack.zip stack.exe
|
||||
which stack
|
||||
stack --version
|
||||
which ./stack
|
||||
./stack --version
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Install GHC
|
||||
# if: steps.stack-programs-dir.outputs.cache-hit != 'true'
|
||||
# set PATH=C:\Users\runneradmin\AppData\Local\Programs\stack\local\bin;%PATH%
|
||||
run: |
|
||||
./stack --no-terminal setup --install-ghc
|
||||
if: env.CONTINUE
|
||||
|
||||
# - name: Install shelltestrunner
|
||||
## - export PATH=~/.local/bin:$PATH
|
||||
# - if [[ ! -x ~/.local/bin/shelltest ]]; then stack install shelltestrunner-1.9; fi
|
||||
# - shelltest --version
|
||||
|
||||
- name: Install haskell deps
|
||||
run: |
|
||||
$stack build --test --only-dependencies
|
||||
./stack --no-terminal build --only-dependencies --dry-run
|
||||
./stack --no-terminal build --only-dependencies
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: List dep versions
|
||||
run: |
|
||||
$stack exec -- ghc-pkg list
|
||||
# use whichever GHC is in default stack.yaml
|
||||
|
||||
- name: Build all hledger modules warning free, optimised and minimised
|
||||
run: |
|
||||
$stack install --test --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror
|
||||
./stack --no-terminal install --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror
|
||||
# --ghc-options=-split-sections doesn't work on windows, "too many sections"
|
||||
# --pedantic
|
||||
if: env.CONTINUE
|
||||
|
||||
# run hledger-lib/hledger functional tests, skipping the ones for addons
|
||||
## - export PATH=~/.local/bin:$PATH
|
||||
#- COLUMNS=80 stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons
|
||||
|
||||
# artifacts:
|
||||
|
||||
- name: Gather binaries
|
||||
run: |
|
||||
mkdir tmp
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger.exe tmp
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger-ui.exe tmp
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger-web.exe tmp
|
||||
strip tmp/hledger.exe
|
||||
strip tmp/hledger-ui.exe
|
||||
strip tmp/hledger-web.exe
|
||||
tmp/hledger --version
|
||||
tmp/hledger-ui --version
|
||||
tmp/hledger-web --version
|
||||
# Guessing these are not likely to be used on windows.
|
||||
# cp hledger/embeddedfiles/*.1 tmp
|
||||
# cp hledger/embeddedfiles/*.info tmp
|
||||
# cp hledger/shell-completion/hledger-completion.bash tmp
|
||||
cd tmp
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger.exe .
|
||||
cp /C/Users/runneradmin/AppData/Roaming/local/bin/hledger-web.exe .
|
||||
strip hledger.exe
|
||||
strip hledger-web.exe
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Create binaries artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hledger-windows-x64
|
||||
path: |
|
||||
tmp/hledger.exe
|
||||
tmp/hledger-ui.exe
|
||||
tmp/hledger-web.exe
|
||||
if: env.CONTINUE
|
||||
|
||||
420
.github/workflows/ci.yml
vendored
420
.github/workflows/ci.yml
vendored
@ -1,420 +0,0 @@
|
||||
# The main hledger continuous integration tests.
|
||||
# Code must pass this successfully before it can be merged or pushed to master.
|
||||
# https://github.com/simonmichael/hledger/settings/branch_protection_rules/17386787
|
||||
# TRIGGER: Runs on any push to ci branch or any pull request against master.
|
||||
# ACTION: Builds, tests and saves linux x64 dynamic binaries with stack and the default ghc.
|
||||
|
||||
name: ci
|
||||
|
||||
on:
|
||||
# When manually triggered in github ui, it runs in master.
|
||||
workflow_dispatch:
|
||||
# When there's a push to the ci branch, it runs in that branch.
|
||||
# After it passes, those commits can be merged/pushed to master.
|
||||
# (Don't use these branches for pull requests, or it will run twice,
|
||||
# https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662/2)
|
||||
push:
|
||||
branches: [ ci ]
|
||||
# When there's a pull request against master, it runs in the pull request's branch.
|
||||
# After it passes, that branch can be merged/pushed to master.
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
# Uncomment to run it only for changes to these paths: (but that could prevent merging)
|
||||
# paths:
|
||||
# - '.github/workflows/pushpull.yml'
|
||||
# - 'stack*.yaml'
|
||||
# - 'hledger-lib/**'
|
||||
# - 'hledger/**'
|
||||
# - 'hledger-ui/**'
|
||||
# - 'hledger-web/**'
|
||||
# - 'bin/*.hs'
|
||||
# - 'examples/**'
|
||||
# Or to ignore certain paths:
|
||||
# # examples
|
||||
# - '!**.journal'
|
||||
# - '!**.j'
|
||||
# - '!**.ledger'
|
||||
# - '!**.csv'
|
||||
# # docs
|
||||
# - '!**.m4'
|
||||
# - '!**.md'
|
||||
# - '!**.1'
|
||||
# - '!**.5'
|
||||
# - '!**.info'
|
||||
# - '!**.txt'
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-24.04
|
||||
# arch: x64
|
||||
# image: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
|
||||
|
||||
env:
|
||||
stack: stack
|
||||
ghcid: 9.10.1
|
||||
cachedate: 20250615 # bump this when new caches are needed
|
||||
|
||||
# flag for skipping later steps, declared here to prevent "Context access might be invalid" warnings
|
||||
do-all:
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for hledger's --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# - name: Print some context for troubleshooting
|
||||
# env:
|
||||
# GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
# run: |
|
||||
# echo $GITHUB_CONTEXT
|
||||
# # echo "$GITHUB_SHA"
|
||||
# # echo "$GITHUB_REF"
|
||||
# # echo "$GITHUB_HEAD_REF"
|
||||
# # echo "$GITHUB_BASE_REF"
|
||||
# # git log "$GITHUB_BASE_REF"..
|
||||
# # tools/commitlint "$GITHUB_BASE_REF"..
|
||||
|
||||
|
||||
# EARLY ACTIONS
|
||||
|
||||
- name: Check commit messages
|
||||
# keep this step synced in all workflows which do it
|
||||
# For a PR, the range will be: master..origin/$GITHUB_HEAD_REF
|
||||
# For a push it will be: $BEFORE..
|
||||
# For a force push, BEFORE is the previous HEAD, and on github (though not locally) this is an "invalid revision range".
|
||||
# 202310: we skip this check when we can't detect the commits, which happens in certain cases
|
||||
# related: https://stackoverflow.com/questions/64708371/how-to-run-github-workflow-on-every-commit-of-a-push
|
||||
# 202312: ignore this if it fails, it may be not worth the hassle
|
||||
env:
|
||||
BEFORE: ${{ github.event.before }}
|
||||
# NUM: 5
|
||||
shell: bash
|
||||
run: |
|
||||
RANGE=${BEFORE:-origin/master}..${GITHUB_HEAD_REF:-}
|
||||
|
||||
echo "debug: last 10 commits:"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -10)"
|
||||
echo "debug: origin/master:"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -1 origin/master)"
|
||||
echo "debug: BEFORE=$BEFORE"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -1 $BEFORE)"
|
||||
echo "debug: GITHUB_HEAD_REF=$GITHUB_HEAD_REF"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -1 $GITHUB_HEAD_REF)"
|
||||
echo "debug: RANGE=$RANGE"
|
||||
echo "debug: commits to check:"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' --abbrev-commit --date=relative --date-order $RANGE)"
|
||||
|
||||
if git rev-list --quiet $RANGE
|
||||
then
|
||||
tools/commitlint $RANGE || echo "commit lint failed, ignoring"
|
||||
else
|
||||
# echo "could not identify commits, checking last $NUM instead:"; tools/commitlint -$NUM
|
||||
echo "could not identify commits, not checking them" # XXX
|
||||
fi
|
||||
|
||||
- name: Skip remaining steps if the last commit message begins with ;
|
||||
shell: bash
|
||||
run: |
|
||||
echo "git log -1 --pretty='%s' ${GITHUB_HEAD_REF:+origin/$GITHUB_HEAD_REF} >> $$.gitlog"
|
||||
(git log -1 --pretty='%s' ${GITHUB_HEAD_REF:+origin/$GITHUB_HEAD_REF} >> $$.gitlog \
|
||||
&& (grep -qE '^ *;' $$.gitlog || echo "do-all=true" >> $GITHUB_ENV)) \
|
||||
|| ( echo "could not identify commit range, continuing CI steps"; echo "do-all=true" >> $GITHUB_ENV )
|
||||
|
||||
|
||||
- name: Check embedded files
|
||||
run: |
|
||||
tools/checkembeddedfiles
|
||||
if: env.do-all
|
||||
|
||||
|
||||
# CACHES
|
||||
|
||||
# Remember, caches are immutable - created once and never updated.
|
||||
# If a cache is used, a new version of it won't be created.
|
||||
# It's probably right to use them for things which don't/needn't change between runs,
|
||||
# including:
|
||||
# - the package db containing the versions of our deps specified by the stackage snapshot
|
||||
# (or by the build plan found by the first cabal run, if using cabal)
|
||||
# - the local bin directory ? what's in there anyway ?
|
||||
# - the per-project and per-package .stack-work directories ? these probably change a little on each run.
|
||||
# presumably it's worthwhile to cache their first-run content, even if with every following run
|
||||
# we end up having to rebuild more of that. The alternative is to always rebuild all of it.
|
||||
|
||||
- name: Cache - stack global package db
|
||||
id: stack-global
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.stack
|
||||
# XXX if stack.yaml is a symlink, this fails with
|
||||
# Error: The template is not valid. .github/workflows/push.yml (Line: 103, Col: 14): hashFiles('**.yaml') failed.
|
||||
# Fail to hash files under directory '/home/runner/work/hledger/hledger'
|
||||
key: ${{ runner.os }}-x64-stack-global-${{ env.ghcid }}-${{ env.cachedate }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-global-${{ env.ghcid }}-${{ env.cachedate }}
|
||||
if: env.do-all
|
||||
|
||||
- name: Cache - stack-installed programs in ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-x64-stack-programs-${{ env.ghcid }}-${{ env.cachedate }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-programs-${{ env.ghcid }}-${{ env.cachedate }}
|
||||
if: env.do-all
|
||||
|
||||
- name: Cache - .stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-x64-stack-work-${{ env.ghcid }}-${{ env.cachedate }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-work-${{ env.ghcid }}-${{ env.cachedate }}
|
||||
if: env.do-all
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}-${{ env.cachedate }}-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}-${{ env.cachedate }}
|
||||
if: env.do-all
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}-${{ env.cachedate }}-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}-${{ env.cachedate }}
|
||||
if: env.do-all
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}-${{ env.cachedate }}-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}-${{ env.cachedate }}
|
||||
if: env.do-all
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}-${{ env.cachedate }}-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}-${{ env.cachedate }}
|
||||
if: env.do-all
|
||||
|
||||
# Ensure the ghc version we need is installed.
|
||||
# The following stack path commands require it, so let's install it first, quietly if possible.
|
||||
# Hopefully it will often be in our cached dirs, avoiding reinstall.
|
||||
# Don't rely on the preinstalled ghc, it's too variable.
|
||||
- name: Ensure ghc is installed
|
||||
run: |
|
||||
$stack setup --verbosity error
|
||||
if: env.do-all
|
||||
|
||||
# - name: Show stack directories
|
||||
# run: |
|
||||
# printf "stack-root: \t"; $stack path --stack-root # Global Stack root directory
|
||||
# printf "global-config: \t"; $stack path --global-config # Global Stack configuration file
|
||||
# printf "project-root: \t"; $stack path --project-root # Project root (derived from stack.yaml file)
|
||||
# printf "config-location: \t"; $stack path --config-location # Configuration location (where the stack.yaml file is)
|
||||
# printf "bin-path: \t"; $stack path --bin-path # PATH environment variable
|
||||
# printf "programs: \t"; $stack path --programs # Install location for GHC and other core tools (see 'stack ls tools' command)
|
||||
# printf "compiler-exe: \t"; $stack path --compiler-exe # Compiler binary (e.g. ghc)
|
||||
# printf "compiler-bin: \t"; $stack path --compiler-bin # Directory containing the compiler binary (e.g. ghc)
|
||||
# printf "compiler-tools-bin: \t"; $stack path --compiler-tools-bin # Directory containing binaries specific to a particular compiler
|
||||
# printf "local-bin: \t"; $stack path --local-bin # Directory where Stack installs executables (e.g. ~/.local/bin (Unix-like OSs) or %APPDATA%\local\bin (Windows))
|
||||
# printf "extra-include-dirs: \t"; $stack path --extra-include-dirs # Extra include directories
|
||||
# printf "extra-library-dirs: \t"; $stack path --extra-library-dirs # Extra library directories
|
||||
# printf "snapshot-pkg-db: \t"; $stack path --snapshot-pkg-db # Snapshot package database
|
||||
# printf "local-pkg-db: \t"; $stack path --local-pkg-db # Local project package database
|
||||
# printf "global-pkg-db: \t"; $stack path --global-pkg-db # Global package database
|
||||
# printf "ghc-package-path: \t"; $stack path --ghc-package-path # GHC_PACKAGE_PATH environment variable
|
||||
# printf "snapshot-install-root: \t"; $stack path --snapshot-install-root # Snapshot installation root
|
||||
# printf "local-install-root: \t"; $stack path --local-install-root # Local project installation root
|
||||
# printf "snapshot-doc-root: \t"; $stack path --snapshot-doc-root # Snapshot documentation root
|
||||
# printf "local-doc-root: \t"; $stack path --local-doc-root # Local project documentation root
|
||||
# printf "local-hoogle-root: \t"; $stack path --local-hoogle-root # Local project documentation root
|
||||
# printf "dist-dir: \t"; $stack path --dist-dir # Dist work directory, relative to package directory
|
||||
# printf "local-hpc-root: \t"; $stack path --local-hpc-root # Where HPC reports and tix files are stored
|
||||
# if: env.do-all
|
||||
# Example output:
|
||||
# stack-root: /home/runner/.stack
|
||||
# global-config: /home/runner/.stack/config.yaml
|
||||
# project-root: /home/runner/work/hledger/hledger
|
||||
# config-location: /home/runner/work/hledger/hledger/stack.yaml
|
||||
# bin-path: /home/runner/.stack/snapshots/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1/bin:/home/runner/.stack/compiler-tools/x86_64-linux-tinfo6/ghc-9.10.1/bin:/home/runner/.stack/programs/x86_64-linux/ghc-tinfo6-9.10.1/bin:/snap/bin:/home/runner/.local/bin:/opt/pipx_bin:/home/runner/.cargo/bin:/home/runner/.config/composer/vendor/bin:/usr/local/.ghcup/bin:/home/runner/.dotnet/tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
|
||||
# programs: /home/runner/.stack/programs/x86_64-linux
|
||||
# compiler-exe: /home/runner/.stack/programs/x86_64-linux/ghc-tinfo6-9.10.1/bin/ghc-9.10.1
|
||||
# compiler-bin: /home/runner/.stack/programs/x86_64-linux/ghc-tinfo6-9.10.1/bin
|
||||
# compiler-tools-bin: /home/runner/.stack/compiler-tools/x86_64-linux-tinfo6/ghc-9.10.1/bin
|
||||
# local-bin: /home/runner/.local/bin
|
||||
# extra-include-dirs:
|
||||
# extra-library-dirs:
|
||||
# snapshot-pkg-db: /home/runner/.stack/snapshots/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1/pkgdb
|
||||
# local-pkg-db: /home/runner/work/hledger/hledger/.stack-work/install/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1/pkgdb
|
||||
# global-pkg-db: /home/runner/.stack/programs/x86_64-linux/ghc-tinfo6-9.10.1/lib/ghc-9.10.1/lib/package.conf.d
|
||||
# ghc-package-path: /home/runner/work/hledger/hledger/.stack-work/install/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1/pkgdb:/home/runner/.stack/snapshots/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1/pkgdb:/home/runner/.stack/programs/x86_64-linux/ghc-tinfo6-9.10.1/lib/ghc-9.10.1/lib/package.conf.d
|
||||
# snapshot-install-root: /home/runner/.stack/snapshots/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1
|
||||
# local-install-root: /home/runner/work/hledger/hledger/.stack-work/install/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1
|
||||
# snapshot-doc-root: /home/runner/.stack/snapshots/x86_64-linux-tinfo6/a475558d986419ca16855615e08d0a95545a229cfbd26fe42e916bee9b2277d3/9.10.1/doc
|
||||
# local-doc-root: /home/runner/work/hledger/hledger/.stack-work/install/x86_64-linux-tinfo6/a475558d986419ca16855615e08d0a95545a229cfbd26fe42e916bee9b2277d3/9.10.1/doc
|
||||
# local-hoogle-root: /home/runner/work/hledger/hledger/.stack-work/hoogle/x86_64-linux-tinfo6/a475558d986419ca16855615e08d0a95545a229cfbd26fe42e916bee9b2277d3/9.10.1
|
||||
# dist-dir: .stack-work/dist/x86_64-linux-tinfo6/ghc-9.10.1
|
||||
# local-hpc-root: /home/runner/work/hledger/hledger/.stack-work/install/x86_64-linux-tinfo6/640e58090350012aaeacf3bb95988ba08dbaab0ce8ce8d2cb4b2ea0c5e7dd47b/9.10.1/hpc
|
||||
|
||||
|
||||
# ACTIONS
|
||||
# in modular steps for faster & more focussed failures
|
||||
|
||||
# XXX slow, I feel this should happen less often
|
||||
# - name: Update package index
|
||||
# run: |
|
||||
# $stack update
|
||||
# if: env.do-all
|
||||
|
||||
- name: Build deps of hledger-lib
|
||||
run: |
|
||||
$stack build --test --bench hledger-lib --only-dependencies
|
||||
if: env.do-all
|
||||
|
||||
- name: Build/test hledger-lib
|
||||
run: |
|
||||
$stack install --test --bench hledger-lib --fast --ghc-options=-Werror
|
||||
if: env.do-all
|
||||
|
||||
|
||||
- name: Build deps of hledger
|
||||
run: |
|
||||
$stack build --test --bench hledger --only-dependencies
|
||||
if: env.do-all
|
||||
|
||||
- name: Build/test hledger
|
||||
run: |
|
||||
$stack install --test --bench hledger --fast --ghc-options=-Werror
|
||||
if: env.do-all
|
||||
|
||||
|
||||
- name: Build deps of hledger-ui
|
||||
run: |
|
||||
$stack build --test --bench hledger-ui --only-dependencies
|
||||
if: env.do-all
|
||||
|
||||
- name: Build/test hledger-ui
|
||||
run: |
|
||||
$stack install --test --bench hledger-ui --fast --ghc-options=-Werror
|
||||
if: env.do-all
|
||||
|
||||
|
||||
- name: Build deps of hledger-web
|
||||
run: |
|
||||
$stack build --test --bench hledger-web --only-dependencies
|
||||
if: env.do-all
|
||||
|
||||
- name: Build/test hledger-web
|
||||
run: |
|
||||
$stack install --test --bench hledger-web --fast --ghc-options=-Werror
|
||||
if: env.do-all
|
||||
|
||||
|
||||
- name: Install shelltestrunner
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
# $stack update; $stack install --verbosity=error shelltestrunner-1.11
|
||||
if [[ ! -x ~/.local/bin/shelltest ]]; then $stack install --verbosity=error shelltestrunner-1.11; fi
|
||||
shelltest --version
|
||||
if: env.do-all
|
||||
|
||||
# Takes ~30s on a 2023 github worker.
|
||||
- name: Test functional tests (excluding addons)
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
COLUMNS=80 $stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons -x ledger-compat/ledger-baseline -x ledger-compat/ledger-regress -x ledger-compat/ledger-collected
|
||||
# XXX run the bin/ func tests corresponding to the GHC version enabled above, only
|
||||
if: env.do-all
|
||||
|
||||
# Takes 1m+ on a 2023 github worker.
|
||||
# Moved to binaries-mac-arm64 workflow instead;
|
||||
# haddock breakage might not be found until release time but it's easy to fix.
|
||||
# - name: Test haddock generation
|
||||
# env:
|
||||
# stack: ${{ matrix.plan.stack }}
|
||||
# run: |
|
||||
# printf "haddock version: "; haddock --version
|
||||
# time $stack build --fast --haddock --no-haddock-deps --no-haddock-hyperlink-source --haddock-arguments="--no-print-missing-docs" || echo "HADDOCK FAILED, IGNORING"
|
||||
# # --no-haddock-hyperlink-source is 25% faster
|
||||
# # --no-print-missing-docs is 600% quieter
|
||||
# if: env.do-all
|
||||
|
||||
# ARTIFACTS
|
||||
# not much needed, but relatively cheap to save and occasionally useful for troubleshooting ?
|
||||
|
||||
- name: Gather binaries
|
||||
id: exes
|
||||
run: |
|
||||
mkdir tmp
|
||||
cd tmp
|
||||
cp -P ~/.local/bin/hledger .
|
||||
cp -P ~/.local/bin/hledger-ui .
|
||||
cp -P ~/.local/bin/hledger-web .
|
||||
strip hledger
|
||||
strip hledger-ui
|
||||
strip hledger-web
|
||||
if: env.do-all
|
||||
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: hledger-linux-x64
|
||||
path: |
|
||||
tmp/hledger
|
||||
tmp/hledger-ui
|
||||
tmp/hledger-web
|
||||
if: env.do-all
|
||||
|
||||
|
||||
|
||||
# SNIPPETS
|
||||
|
||||
# how to set a context variable, and an attempt to make a nice artifact version suffix:
|
||||
# echo "::set-output name=version::$(git branch --show-current | sed 's/-.*//')-$(git rev-parse --short HEAD)"
|
||||
|
||||
# - name: show stuff
|
||||
# run: |
|
||||
# if [[ -e ~/.local/bin ]]; then ls -lFRa ~/.local/bin; fi
|
||||
|
||||
# inspect available context info, per
|
||||
# https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions.
|
||||
# sample output: https://github.com/simonmichael/hledger/runs/1619227104
|
||||
# - name: Dump GitHub context
|
||||
# env:
|
||||
# GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
# run: echo "$GITHUB_CONTEXT"
|
||||
# - name: Dump job context
|
||||
# env:
|
||||
# JOB_CONTEXT: ${{ toJson(job) }}
|
||||
# run: echo "$JOB_CONTEXT"
|
||||
# - name: Dump steps context
|
||||
# env:
|
||||
# STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
# run: echo "$STEPS_CONTEXT"
|
||||
# - name: Dump runner context
|
||||
# env:
|
||||
# RUNNER_CONTEXT: ${{ toJson(runner) }}
|
||||
# run: echo "$RUNNER_CONTEXT"
|
||||
# - name: Dump strategy context
|
||||
# env:
|
||||
# STRATEGY_CONTEXT: ${{ toJson(strategy) }}
|
||||
# run: echo "$STRATEGY_CONTEXT"
|
||||
# - name: Dump matrix context
|
||||
# env:
|
||||
# MATRIX_CONTEXT: ${{ toJson(matrix) }}
|
||||
# run: echo "$MATRIX_CONTEXT"
|
||||
46
.github/workflows/old/release.yml
vendored
Normal file
46
.github/workflows/old/release.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# Runs on push of a [0-9]* or r[0-9]* tag (to any branch ?)
|
||||
|
||||
# Creates a draft github release.
|
||||
# See https://github.com/actions/create-release, still pretty rough as of 20200609.
|
||||
# see also: https://github.com/marketplace/actions/tag-release-on-push-action
|
||||
|
||||
name: create release
|
||||
|
||||
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestbranchestags
|
||||
# also: "The action does not seem to work for tags created before the workflow."
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+'
|
||||
- '[0-9]+.[0-9]+-*'
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
- '[0-9]+.[0-9]+.[0-9]+-*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# - name: Create Release (actions/create-release)
|
||||
# id: create_release
|
||||
# uses: actions/create-release@v1
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||
# with:
|
||||
# tag_name: X.Y
|
||||
# release_name: X.Y
|
||||
# body: |
|
||||
# CHANGE 1; CHANGE 2.
|
||||
# https://hledger.org/release-notes.html#hledger-X-Y
|
||||
# draft: true
|
||||
# prerelease: true
|
||||
|
||||
- name: Create Release (softprops/action-gh-release)
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
154
.github/workflows/oldest.yml
vendored
154
.github/workflows/oldest.yml
vendored
@ -1,154 +0,0 @@
|
||||
# TRIGGER: Runs on any push to oldest branch.
|
||||
# ACTION: Builds and tests with stack and the oldest supported ghc.
|
||||
|
||||
name: oldest
|
||||
|
||||
on:
|
||||
# When there's a push to the oldest branch, it runs in that branch.
|
||||
push:
|
||||
branches: [ oldest ]
|
||||
# If manually triggered in github ui, it runs in master.
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
oldest:
|
||||
runs-on: ubuntu-24.04
|
||||
# arch: x64
|
||||
# image: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
|
||||
|
||||
env:
|
||||
stack: stack --stack-yaml=stack96.yaml
|
||||
ghcid: 9.6.6
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
# have to fetch everything for git describe for hledger's --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
# CACHES
|
||||
|
||||
- name: Cache - stack global package db
|
||||
id: stack-global
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.stack
|
||||
# XXX if stack.yaml is a symlink, this fails with
|
||||
# Error: The template is not valid. .github/workflows/push.yml (Line: 103, Col: 14): hashFiles('**.yaml') failed.
|
||||
# Fail to hash files under directory '/home/runner/work/hledger/hledger'
|
||||
key: ${{ runner.os }}-x64-stack-global-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-global-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - stack-installed programs in ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-x64-stack-programs-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-programs-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - .stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-x64-stack-work-${{ env.ghcid }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger-lib/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-lib-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger-ui/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-ui-stack-work-${{ env.ghcid }}
|
||||
|
||||
- name: Cache - hledger-web/.stack-work
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-x64-hledger-web-stack-work-${{ env.ghcid }}
|
||||
|
||||
|
||||
# ACTIONS
|
||||
# in modular steps for faster & more focussed failures
|
||||
|
||||
- name: Install GHC
|
||||
run: |
|
||||
$stack setup --install-ghc
|
||||
|
||||
|
||||
- name: Build deps of hledger-lib
|
||||
run: |
|
||||
$stack build --test --bench hledger-lib --only-dependencies
|
||||
|
||||
- name: Build/test hledger-lib
|
||||
run: |
|
||||
$stack install --test --bench hledger-lib --fast --ghc-options=-Werror
|
||||
|
||||
|
||||
- name: Build deps of hledger
|
||||
run: |
|
||||
$stack build --test --bench hledger --only-dependencies
|
||||
|
||||
- name: Build/test hledger
|
||||
run: |
|
||||
$stack install --test --bench hledger --fast --ghc-options=-Werror
|
||||
|
||||
|
||||
- name: Build deps of hledger-ui
|
||||
run: |
|
||||
$stack build --test --bench hledger-ui --only-dependencies
|
||||
|
||||
- name: Build/test hledger-ui
|
||||
run: |
|
||||
$stack install --test --bench hledger-ui --fast --ghc-options=-Werror
|
||||
|
||||
|
||||
- name: Build deps of hledger-web
|
||||
run: |
|
||||
$stack build --test --bench hledger-web --only-dependencies
|
||||
|
||||
- name: Build/test hledger-web
|
||||
run: |
|
||||
$stack install --test --bench hledger-web --fast --ghc-options=-Werror
|
||||
|
||||
# XXX disable until this is fixed: shelltest.hs:125:20: error:
|
||||
# shelltestrunner > Not in scope: ‘configFailFast’
|
||||
# shelltestrunner > Perhaps you meant ‘configFastFail’ (imported from Test.Hspec.Core.Runner)
|
||||
|
||||
# - name: Install shelltestrunner
|
||||
# run: |
|
||||
# export PATH=~/.local/bin:$PATH
|
||||
# $stack update; $stack install --verbosity=error shelltestrunner-1.11
|
||||
# if [[ ! -x ~/.local/bin/shelltest ]]; then $stack install --verbosity=error shelltestrunner-1.11; fi
|
||||
# shelltest --version
|
||||
|
||||
# - name: Test functional tests (excluding addons)
|
||||
# run: |
|
||||
# export PATH=~/.local/bin:$PATH
|
||||
# COLUMNS=80 $stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons -x ledger-compat/ledger-baseline -x ledger-compat/ledger-regress -x ledger-compat/ledger-collected
|
||||
# # XXX run the bin/ func tests corresponding to the GHC version enabled above, only
|
||||
228
.github/workflows/release.yml
vendored
228
.github/workflows/release.yml
vendored
@ -1,228 +0,0 @@
|
||||
# TRIGGER: Runs when a release tag like "1.*" is pushed to the repo.
|
||||
# XXX Triggers too much, eg for 1.x.99 dev tags; those releases must be deleted manually.
|
||||
# ACTION: Creates/updates a draft release with binaries from the latest successful binaries-* runs.
|
||||
# The main binaries* workflows should be completed before triggering this.
|
||||
|
||||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '1.*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get artifact from latest successful binaries-windows-x64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
# https://github.com/dawidd6/action-download-artifact v3.1.4, unverified so needs to be whitelisted in repo settings
|
||||
with:
|
||||
# all the settings, for reference. The other steps below will be more concise.
|
||||
#
|
||||
# Optional, GitHub token, a Personal Access Token with `public_repo` scope if needed
|
||||
# Required, if the artifact is from a different repo
|
||||
# Required, if the repo is private a Personal Access Token with `repo` scope is needed or GitHub token in a job where the permissions `action` scope set to `read`
|
||||
# github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
# Optional, workflow file name or ID
|
||||
# If not specified, will be inferred from run_id (if run_id is specified), or will be the current workflow
|
||||
workflow: binaries-windows-x64.yml
|
||||
# Optional, will use specified workflow run
|
||||
# use ${{ github.event.workflow_run.id }} when your action runs in a workflow_run event
|
||||
# and wants to download from the triggering workflow run
|
||||
# run_id: 1122334455
|
||||
# If no workflow is set and workflow_search set to true, then the most recent workflow matching
|
||||
# all other criteria will be looked up instead of using the current workflow
|
||||
workflow_search: false
|
||||
# Optional, the status or conclusion of a completed workflow to search for
|
||||
# Can be one of a workflow conclusion:
|
||||
# "failure", "success", "neutral", "cancelled", "skipped", "timed_out", "action_required"
|
||||
# Or a workflow status:
|
||||
# "completed", "in_progress", "queued"
|
||||
# Use the empty string ("") to ignore status or conclusion in the search
|
||||
workflow_conclusion: success
|
||||
# Optional, will get head commit SHA
|
||||
# pr: ${{github.event.pull_request.number}}
|
||||
# Optional, no need to specify if PR is
|
||||
# commit: ${{github.event.pull_request.head.sha}}
|
||||
# Optional, will use the specified branch. Defaults to all branches
|
||||
# branch: binaries-linux-x64
|
||||
# Optional, defaults to all types
|
||||
# event: push
|
||||
# Optional, run number from the workflow
|
||||
# run_number: 34
|
||||
# Optional, uploaded artifact name,
|
||||
# will download all artifacts if not specified
|
||||
# and extract them into respective subdirectories
|
||||
# https://github.com/actions/download-artifact#download-all-artifacts
|
||||
# is treated as a regular expression if input name_is_regexp is true
|
||||
# will download only those artifacts with a name that matches this regular expression
|
||||
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions
|
||||
# name: artifact_name
|
||||
# Optional, name is treated as a regular expression if set true
|
||||
# name_is_regexp: true
|
||||
# Optional, a directory where to extract artifact(s), defaults to the current directory
|
||||
path: artifacts
|
||||
# Optional, defaults to current repo
|
||||
# repo: ${{ github.repository }}
|
||||
# Optional, check the workflow run to whether it has an artifact
|
||||
# then will get the last available artifact from the previous workflow
|
||||
# default false, just try to download from the last one
|
||||
# check_artifacts: false
|
||||
# Optional, search for the last workflow run whose stored an artifact named as in `name` input
|
||||
# default false
|
||||
# search_artifacts: false
|
||||
# Optional, choose to skip unpacking the downloaded artifact(s)
|
||||
# default false
|
||||
# windows artifact is just zipped, no need to repack
|
||||
skip_unpack: true
|
||||
# Optional, choose how to exit the action if no artifact is found
|
||||
# can be one of:
|
||||
# "fail", "warn", "ignore"
|
||||
# default fail
|
||||
# if_no_artifact_found: fail
|
||||
# Optional, allow forks when searching for artifacts
|
||||
# default true
|
||||
allow_forks: false
|
||||
|
||||
- name: Get artifact from latest successful binaries-linux-x64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
with:
|
||||
workflow: binaries-linux-x64.yml
|
||||
allow_forks: false
|
||||
path: artifacts
|
||||
|
||||
- name: Get artifact from latest successful binaries-mac-arm64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
with:
|
||||
workflow: binaries-mac-arm64.yml
|
||||
allow_forks: false
|
||||
path: artifacts
|
||||
|
||||
- name: Get artifact from latest successful binaries-mac-x64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
with:
|
||||
workflow: binaries-mac-x64.yml
|
||||
allow_forks: false
|
||||
path: artifacts
|
||||
|
||||
- name: Inspect artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
ls -lRFh artifacts
|
||||
|
||||
# The unix files were
|
||||
# 1. tarred to protect their executable permissions,
|
||||
# 2. mandatorily zipped by actions/upload-artifact,
|
||||
# 3. unzipped by dawidd6/action-download-artifact.
|
||||
# Now we 4. gzip them - to be more unix-standard ?
|
||||
# And 5. softprops/action-gh-release will mandatorily zip them again.
|
||||
- name: Repack unix artifacts with gz
|
||||
shell: bash
|
||||
run: |
|
||||
cd artifacts
|
||||
mv */*.tar .
|
||||
gzip *.tar
|
||||
|
||||
- name: Inspect artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
ls -lRFh artifacts
|
||||
|
||||
- name: Generate github release notes
|
||||
# ghrelnotes's argument should be the release's main tag name, eg "1.40".
|
||||
# XXX Currently it is actually like "refs/tags/hledger-1.40.99", requiring manual fixup.
|
||||
run: |
|
||||
doc/ghrelnotes ${{ github.ref }} >ghrelnotes.md
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # https://github.com/softprops/action-gh-release 2.0.5
|
||||
# permissions:
|
||||
# contents: write
|
||||
with:
|
||||
# https://github.com/softprops/action-gh-release?tab=readme-ov-file#-customizing
|
||||
# body String Text communicating notable changes in this release
|
||||
# body_path String Path to load text communicating notable changes in this release
|
||||
# draft Boolean Indicator of whether or not this release is a draft
|
||||
# prerelease Boolean Indicator of whether or not is a prerelease
|
||||
# files String Newline-delimited globs of paths to assets to upload for release
|
||||
# name String Name of the release. defaults to tag name
|
||||
# tag_name String Name of a tag. defaults to github.ref
|
||||
# fail_on_unmatched_files Boolean Indicator of whether to fail if any of the files globs match nothing
|
||||
# repository String Name of a target repository in <owner>/<repo> format. Defaults to GITHUB_REPOSITORY env variable
|
||||
# target_commitish String Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Defaults to repository default branch.
|
||||
# token String Secret GitHub Personal Access Token. Defaults to ${{ github.token }}
|
||||
# discussion_category_name String If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see "Managing categories for discussions in your repository."
|
||||
# generate_release_notes Boolean Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes. See the GitHub docs for this feature for more information
|
||||
# append_body Boolean Append to existing body instead of overwriting it
|
||||
# make_latest String Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be true, false, or legacy. Uses GitHub api defaults if not provided
|
||||
#
|
||||
body_path: ghrelnotes.md
|
||||
files: |
|
||||
artifacts/*.zip
|
||||
artifacts/*.tar.gz
|
||||
fail_on_unmatched_files: true
|
||||
draft: true
|
||||
|
||||
|
||||
|
||||
# snippets
|
||||
|
||||
|
||||
# body: |
|
||||
# ${{ fromJSON(steps.<step-id>.outputs.assets)[0].browser_download_url }}
|
||||
|
||||
# if you intend to run workflows on the release event (on: { release: { types: [published] } }),
|
||||
# you need to use a personal access token for this action, as the default secrets.GITHUB_TOKEN does not trigger another workflow.
|
||||
|
||||
# - name: Make tarball
|
||||
# shell: bash
|
||||
# run: |
|
||||
# outdir="target/${{ matrix.target }}/release"
|
||||
# staging="jj-${{ github.event.release.tag_name }}-${{ matrix.target }}"
|
||||
# mkdir "$staging"
|
||||
# cp {README.md,LICENSE} "$staging/"
|
||||
# if [ "${{ matrix.os }}" = "windows-2022" ]; then
|
||||
# cp "$outdir/jj.exe" "$staging/"
|
||||
# cd "$staging"
|
||||
# 7z a "../$staging.zip" .
|
||||
# echo "ASSET=$staging.zip" >> $GITHUB_ENV
|
||||
# else
|
||||
# cp "$outdir/jj" "$staging/"
|
||||
# tar czf "$staging.tar.gz" -C "$staging" .
|
||||
# echo "ASSET=$staging.tar.gz" >> $GITHUB_ENV
|
||||
# fi
|
||||
|
||||
|
||||
# https://github.com/marketplace/actions/safe-download-workflow-artifact
|
||||
|
||||
# https://github.com/actions/upload-artifact/issues/89#issuecomment-1194408215
|
||||
|
||||
# https://www.eliostruyf.com/retrieving-artifact-previous-github-actions-workflow/
|
||||
|
||||
# We have two workflows, one for building and one for releasing built artifacts upon a tag release.
|
||||
# They're both summoned from one push event, and the release job waits for the other job:
|
||||
# https://github.com/dawidd6/action-download-artifact/issues/245
|
||||
|
||||
|
||||
# - name: version
|
||||
# run: echo "::set-output name=version::$(./bin/azblogfilter --version)"
|
||||
# id: version
|
||||
|
||||
# - name: release
|
||||
# uses: actions/create-release@v1
|
||||
# id: create_release
|
||||
# with:
|
||||
# draft: false
|
||||
# prerelease: false
|
||||
# release_name: ${{ steps.version.outputs.version }}
|
||||
# tag_name: ${{ github.ref }}
|
||||
# body_path: CHANGELOG.md
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ github.token }}
|
||||
330
.github/workflows/test-linux-x64.yml
vendored
Normal file
330
.github/workflows/test-linux-x64.yml
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
# The main hledger integration test workflow.
|
||||
# Builds warning free and runs unit/doc/functional/haddock/bench tests,
|
||||
# using the GHC version(s) enabled below.
|
||||
# It also uploads the binaries as a downloadable artifact for testers,
|
||||
# and because why not having done all the work.
|
||||
# Merging to master requires that this workflow's jobs ("86" at least) have passed.
|
||||
|
||||
name: test-linux-x64
|
||||
|
||||
# This workflow runs...
|
||||
on:
|
||||
# On master, when manually triggered.
|
||||
workflow_dispatch:
|
||||
|
||||
# On master, on this schedule:
|
||||
# schedule:
|
||||
# - cron: "0 07 * * 0" # sunday midnight pacific
|
||||
|
||||
# On these dev branches, when pushed.
|
||||
# To avoid double workflow execution, don't use these branches for pull requests.
|
||||
# (https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662/2)
|
||||
push:
|
||||
branches: [ simon, simon2 ]
|
||||
|
||||
# On pull request branches against these branches, when pushed.
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
# Uncomment to run it only for changes to these paths: (but that could prevent merging)
|
||||
# paths:
|
||||
# - '.github/workflows/pushpull.yml'
|
||||
# - 'stack*.yaml'
|
||||
# - 'hledger-lib/**'
|
||||
# - 'hledger/**'
|
||||
# - 'hledger-ui/**'
|
||||
# - 'hledger-web/**'
|
||||
# - 'bin/*.hs'
|
||||
# - 'examples/**'
|
||||
# Or to ignore certain paths:
|
||||
# # examples
|
||||
# - '!**.journal'
|
||||
# - '!**.j'
|
||||
# - '!**.ledger'
|
||||
# - '!**.csv'
|
||||
# # docs
|
||||
# - '!**.m4'
|
||||
# - '!**.md'
|
||||
# - '!**.1'
|
||||
# - '!**.5'
|
||||
# - '!**.info'
|
||||
# - '!**.txt'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
plan: # at least the check(s) required by master should be enabled
|
||||
- { ghc: "810", stack: "stack --stack-yaml=stack8.10.yaml" } # oldest supported ghc
|
||||
# - { ghc: "90" , stack: "stack --stack-yaml=stack.yaml" }
|
||||
# - { ghc: "92" , stack: "stack --stack-yaml=stack9.2.yaml" } # newest supported ghc
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out
|
||||
uses: actions/checkout@v2
|
||||
# have to fetch everything for git describe for --version
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Print debug output
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: |
|
||||
echo $GITHUB_CONTEXT
|
||||
# echo "$GITHUB_SHA"
|
||||
# echo "$GITHUB_REF"
|
||||
# echo "$GITHUB_HEAD_REF"
|
||||
# echo "$GITHUB_BASE_REF"
|
||||
# git log "$GITHUB_BASE_REF"..
|
||||
# tools/commitlint "$GITHUB_BASE_REF"..
|
||||
|
||||
# keep synced in all workflows which do this
|
||||
- name: Check commit messages
|
||||
# For a PR, the range will be: master..origin/$GITHUB_HEAD_REF
|
||||
# For a push it will be: $BEFORE..
|
||||
# For a force push, BEFORE is the previous HEAD, and on github (though not locally) this is an "invalid revision range".
|
||||
# In this and any case where the range is invalid, we'll just skip the check, to avoid false positives
|
||||
# related: https://stackoverflow.com/questions/64708371/how-to-run-github-workflow-on-every-commit-of-a-push
|
||||
env:
|
||||
BEFORE: ${{ github.event.before }}
|
||||
# NUM: 5
|
||||
shell: bash
|
||||
run: |
|
||||
RANGE=${BEFORE:-origin/master}..${GITHUB_HEAD_REF:-}
|
||||
|
||||
echo "debug: last 10 commits:"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -10)"
|
||||
echo "debug: origin/master:"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -1 origin/master)"
|
||||
echo "debug: BEFORE=$BEFORE"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -1 $BEFORE)"
|
||||
echo "debug: GITHUB_HEAD_REF=$GITHUB_HEAD_REF"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' -1 $GITHUB_HEAD_REF)"
|
||||
echo "debug: RANGE=$RANGE"
|
||||
echo "debug: commits to check:"
|
||||
echo "$(git log --format='%h -%d %s (%an, %ci)' --abbrev-commit --date=relative --date-order $RANGE)"
|
||||
|
||||
if git rev-list --quiet $RANGE
|
||||
then tools/commitlint $RANGE
|
||||
else echo "could not identify commits, not checking them"
|
||||
# echo "could not identify commits, checking last $NUM instead:"
|
||||
# tools/commitlint -$NUM
|
||||
fi
|
||||
|
||||
- name: Skip remaining steps if last commit message begins with ;
|
||||
shell: bash
|
||||
run: |
|
||||
echo "git log -1 --pretty='%s' ${GITHUB_HEAD_REF:+origin/$GITHUB_HEAD_REF} >> $$.gitlog"
|
||||
(git log -1 --pretty='%s' ${GITHUB_HEAD_REF:+origin/$GITHUB_HEAD_REF} >> $$.gitlog \
|
||||
&& (grep -qE '^ *;' $$.gitlog || echo "CONTINUE=true" >> $GITHUB_ENV)) \
|
||||
|| ( echo "could not identify commit range, continuing CI steps"; echo "CONTINUE=true" >> $GITHUB_ENV )
|
||||
|
||||
# things to be cached/restored:
|
||||
|
||||
- name: Cache stack global package db
|
||||
id: stack-global
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.stack
|
||||
# XXX if stack.yaml is a symlink, this fails with
|
||||
# Error: The template is not valid. .github/workflows/push.yml (Line: 103, Col: 14): hashFiles('**.yaml') failed.
|
||||
# Fail to hash files under directory '/home/runner/work/hledger/hledger'
|
||||
key: ${{ runner.os }}-stack-global-${{ matrix.plan.ghc }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-global-${{ matrix.plan.ghc }}
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache stack-installed programs in ~/.local/bin
|
||||
id: stack-programs
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.local/bin
|
||||
key: ${{ runner.os }}-stack-programs-${{ matrix.plan.ghc }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-programs-${{ matrix.plan.ghc }}
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache .stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .stack-work
|
||||
key: ${{ runner.os }}-stack-work-${{ matrix.plan.ghc }}-${{ hashFiles('**.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-work-${{ matrix.plan.ghc }}
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache hledger-lib/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-lib/.stack-work
|
||||
key: ${{ runner.os }}-hledger-lib-stack-work-${{ matrix.plan.ghc }}-${{ hashFiles('hledger-lib/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-lib-stack-work-${{ matrix.plan.ghc }}
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache hledger/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger/.stack-work
|
||||
key: ${{ runner.os }}-hledger-stack-work-${{ matrix.plan.ghc }}-${{ hashFiles('hledger/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-stack-work-${{ matrix.plan.ghc }}
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache hledger-ui/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-ui/.stack-work
|
||||
key: ${{ runner.os }}-hledger-ui-stack-work-${{ matrix.plan.ghc }}-${{ hashFiles('hledger-ui/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-ui-stack-work-${{ matrix.plan.ghc }}
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Cache hledger-web/.stack-work
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: hledger-web/.stack-work
|
||||
key: ${{ runner.os }}-hledger-web-stack-work-${{ matrix.plan.ghc }}-${{ hashFiles('hledger-web/package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-hledger-web-stack-work-${{ matrix.plan.ghc }}
|
||||
if: env.CONTINUE
|
||||
|
||||
# actions:
|
||||
|
||||
- name: Install stack
|
||||
run: |
|
||||
mkdir -p ~/.local/bin
|
||||
export PATH=~/.local/bin:$PATH
|
||||
# curl -sL https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack
|
||||
if [[ ! -x ~/.local/bin/stack ]]; then curl -sL https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'; chmod a+x ~/.local/bin/stack; fi
|
||||
stack --version
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Install GHC
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
$stack setup --install-ghc
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Install haskell deps
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
$stack build --test --bench --only-dependencies --dry-run
|
||||
$stack build --test --bench --only-dependencies
|
||||
if: env.CONTINUE
|
||||
|
||||
# - name: Build all hledger modules warning free, optimised and minimised, run unit/doc/bench tests
|
||||
# env:
|
||||
# stack: ${{ matrix.plan.stack }}
|
||||
# run: |
|
||||
# $stack install --test --bench --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror --ghc-options=-split-sections --no-terminal
|
||||
# # build quicker when tweaking ci: $stack install --ghc-options=-Werror --ghc-options=-split-sections --no-terminal
|
||||
# # -split-sections shrinks binaries by 30% on average here
|
||||
# # --pedantic --no-run-benchmarks
|
||||
# if: env.CONTINUE
|
||||
|
||||
# Packages are built one at a time to fail faster on error.
|
||||
# Note: doctests won't run if using GHC 9.0, see hledger-lib/package.yaml
|
||||
- name: Build all hledger modules fast, warning free, run unit/doc/bench tests
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
$stack install --fast --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror --test --bench hledger-lib
|
||||
$stack install --fast --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror --test --bench hledger
|
||||
$stack install --fast --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror --test --bench hledger-ui
|
||||
$stack install --fast --force-dirty --ghc-options=-fforce-recomp --ghc-options=-Werror --test --bench hledger-web
|
||||
# --ghc-options=-split-sections --no-terminal
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Install shelltestrunner
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
if [[ ! -x ~/.local/bin/shelltest ]]; then $stack install shelltestrunner-1.9; fi
|
||||
shelltest --version
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Test functional tests (excluding addons)
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
export PATH=~/.local/bin:$PATH
|
||||
COLUMNS=80 $stack exec -- shelltest --execdir -j16 hledger/test -x /_ -x /addons
|
||||
# XXX run the bin/ func tests corresponding to the GHC version enabled above, only
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Test haddock generation
|
||||
env:
|
||||
stack: ${{ matrix.plan.stack }}
|
||||
run: |
|
||||
time $stack build --fast --haddock --no-haddock-deps --no-haddock-hyperlink-source --haddock-arguments="--no-print-missing-docs"
|
||||
# --no-haddock-hyperlink-source is 25% faster
|
||||
# --no-print-missing-docs is 600% quieter
|
||||
if: env.CONTINUE
|
||||
|
||||
- name: Gather binaries
|
||||
id: exes
|
||||
run: |
|
||||
mkdir tmp
|
||||
cd tmp
|
||||
cp -P ~/.local/bin/hledger .
|
||||
cp -P ~/.local/bin/hledger-ui .
|
||||
cp -P ~/.local/bin/hledger-web .
|
||||
strip hledger
|
||||
strip hledger-ui
|
||||
strip hledger-web
|
||||
tar cvf hledger-linux-x64.tar hledger hledger-ui hledger-web
|
||||
if: env.CONTINUE
|
||||
|
||||
# how to set a context variable, and an attempt to make a nice artifact version suffix:
|
||||
# echo "::set-output name=version::$(git branch --show-current | sed 's/-.*//')-$(git rev-parse --short HEAD)"
|
||||
|
||||
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
|
||||
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
|
||||
# Unfortunately it means users must both unzip and untar.
|
||||
- name: Upload binaries artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: hledger-linux-x64
|
||||
path: tmp/hledger-linux-x64.tar
|
||||
if: env.CONTINUE
|
||||
|
||||
|
||||
|
||||
|
||||
# - name: show stuff
|
||||
# run: |
|
||||
# if [[ -e ~/.local/bin ]]; then ls -lFRa ~/.local/bin; fi
|
||||
|
||||
# inspect available context info, per
|
||||
# https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions.
|
||||
# sample output: https://github.com/simonmichael/hledger/runs/1619227104
|
||||
# - name: Dump GitHub context
|
||||
# env:
|
||||
# GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
# run: echo "$GITHUB_CONTEXT"
|
||||
# - name: Dump job context
|
||||
# env:
|
||||
# JOB_CONTEXT: ${{ toJson(job) }}
|
||||
# run: echo "$JOB_CONTEXT"
|
||||
# - name: Dump steps context
|
||||
# env:
|
||||
# STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
# run: echo "$STEPS_CONTEXT"
|
||||
# - name: Dump runner context
|
||||
# env:
|
||||
# RUNNER_CONTEXT: ${{ toJson(runner) }}
|
||||
# run: echo "$RUNNER_CONTEXT"
|
||||
# - name: Dump strategy context
|
||||
# env:
|
||||
# STRATEGY_CONTEXT: ${{ toJson(strategy) }}
|
||||
# run: echo "$STRATEGY_CONTEXT"
|
||||
# - name: Dump matrix context
|
||||
# env:
|
||||
# MATRIX_CONTEXT: ${{ toJson(matrix) }}
|
||||
# run: echo "$MATRIX_CONTEXT"
|
||||
162
.github/workflows/testbin.yml
vendored
162
.github/workflows/testbin.yml
vendored
@ -1,162 +0,0 @@
|
||||
# TRIGGER: Runs when triggered manually.
|
||||
# ACTION: Uploads binaries from the latest successful binaries-* runs to the current "testbin" prerelease.
|
||||
# Should not change anything else about the prerelease.
|
||||
|
||||
name: testbin
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# push:
|
||||
|
||||
jobs:
|
||||
publish-binaries:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Alternative:
|
||||
# just ghruns-download
|
||||
- name: Get artifact from latest successful binaries-windows-x64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
# https://github.com/dawidd6/action-download-artifact v3.1.4, unverified so needs to be whitelisted in repo settings
|
||||
with:
|
||||
workflow: binaries-windows-x64.yml
|
||||
# Optional, will use specified workflow run
|
||||
# use ${{ github.event.workflow_run.id }} when your action runs in a workflow_run event
|
||||
# and wants to download from the triggering workflow run
|
||||
# run_id: 1122334455
|
||||
# If no workflow is set and workflow_search set to true, then the most recent workflow matching
|
||||
# all other criteria will be looked up instead of using the current workflow
|
||||
workflow_search: false
|
||||
# Optional, the status or conclusion of a completed workflow to search for
|
||||
# Can be one of a workflow conclusion:
|
||||
# "failure", "success", "neutral", "cancelled", "skipped", "timed_out", "action_required"
|
||||
# Or a workflow status:
|
||||
# "completed", "in_progress", "queued"
|
||||
# Use the empty string ("") to ignore status or conclusion in the search
|
||||
workflow_conclusion: success
|
||||
# Optional, will get head commit SHA
|
||||
# pr: ${{github.event.pull_request.number}}
|
||||
# Optional, no need to specify if PR is
|
||||
# commit: ${{github.event.pull_request.head.sha}}
|
||||
# Optional, will use the specified branch. Defaults to all branches
|
||||
# branch: binaries-linux-x64
|
||||
# Optional, defaults to all types
|
||||
# event: push
|
||||
# Optional, run number from the workflow
|
||||
# run_number: 34
|
||||
# Optional, uploaded artifact name,
|
||||
# will download all artifacts if not specified
|
||||
# and extract them into respective subdirectories
|
||||
# https://github.com/actions/download-artifact#download-all-artifacts
|
||||
# is treated as a regular expression if input name_is_regexp is true
|
||||
# will download only those artifacts with a name that matches this regular expression
|
||||
# https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions
|
||||
# name: artifact_name
|
||||
# Optional, name is treated as a regular expression if set true
|
||||
# name_is_regexp: true
|
||||
# Optional, a directory where to extract artifact(s), defaults to the current directory
|
||||
path: artifacts
|
||||
# Optional, defaults to current repo
|
||||
# repo: ${{ github.repository }}
|
||||
# Optional, check the workflow run to whether it has an artifact
|
||||
# then will get the last available artifact from the previous workflow
|
||||
# default false, just try to download from the last one
|
||||
# check_artifacts: false
|
||||
# Optional, search for the last workflow run whose stored an artifact named as in `name` input
|
||||
# default false
|
||||
# search_artifacts: false
|
||||
# Optional, choose to skip unpacking the downloaded artifact(s)
|
||||
# default false
|
||||
# windows artifact is just zipped, no need to repack
|
||||
skip_unpack: true
|
||||
# Optional, choose how to exit the action if no artifact is found
|
||||
# can be one of:
|
||||
# "fail", "warn", "ignore"
|
||||
# default fail
|
||||
# if_no_artifact_found: fail
|
||||
# Optional, allow forks when searching for artifacts
|
||||
# default true
|
||||
allow_forks: false
|
||||
|
||||
- name: Get artifact from latest successful binaries-linux-x64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
with:
|
||||
workflow: binaries-linux-x64.yml
|
||||
allow_forks: false
|
||||
path: artifacts
|
||||
|
||||
- name: Get artifact from latest successful binaries-mac-arm64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
with:
|
||||
workflow: binaries-mac-arm64.yml
|
||||
allow_forks: false
|
||||
path: artifacts
|
||||
|
||||
- name: Get artifact from latest successful binaries-mac-x64 run
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe
|
||||
with:
|
||||
workflow: binaries-mac-x64.yml
|
||||
allow_forks: false
|
||||
path: artifacts
|
||||
|
||||
- name: Inspect artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
ls -lRFh artifacts
|
||||
|
||||
# The unix files were
|
||||
# 1. tarred to protect their executable permissions,
|
||||
# 2. mandatorily zipped by actions/upload-artifact,
|
||||
# 3. unzipped by dawidd6/action-download-artifact.
|
||||
# Now we 4. gzip them.
|
||||
- name: Gzip unix tarballs
|
||||
shell: bash
|
||||
run: |
|
||||
cd artifacts
|
||||
mv */*.tar .
|
||||
gzip *.tar
|
||||
|
||||
- name: Inspect artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
ls -lRFh artifacts
|
||||
|
||||
# The testbin prerelease should already exist; this should only update its artifacts.
|
||||
# Alternative:
|
||||
# gh release upload {{ VER }} tmp/hledger-linux-x64.tar.gz
|
||||
# gh release upload {{ VER }} tmp/hledger-mac-arm64.tar.gz
|
||||
# gh release upload {{ VER }} tmp/hledger-mac-x64.tar.gz
|
||||
# gh release upload {{ VER }} tmp/hledger-windows-x64.zip
|
||||
- name: Upload artifacts to testbin prerelease
|
||||
uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # https://github.com/softprops/action-gh-release 2.0.5
|
||||
# permissions:
|
||||
# contents: write
|
||||
with:
|
||||
tag_name: testbin
|
||||
files: |
|
||||
artifacts/*.zip
|
||||
artifacts/*.tar.gz
|
||||
fail_on_unmatched_files: true
|
||||
prerelease: true
|
||||
# body_path: ghrelnotes-nightly.md
|
||||
#
|
||||
# https://github.com/softprops/action-gh-release?tab=readme-ov-file#-customizing
|
||||
# body String Text communicating notable changes in this release
|
||||
# body_path String Path to load text communicating notable changes in this release
|
||||
# draft Boolean Indicator of whether or not this release is a draft
|
||||
# prerelease Boolean Indicator of whether or not is a prerelease
|
||||
# files String Newline-delimited globs of paths to assets to upload for release
|
||||
# name String Name of the release. defaults to tag name
|
||||
# tag_name String Name of a tag. defaults to github.ref
|
||||
# fail_on_unmatched_files Boolean Indicator of whether to fail if any of the files globs match nothing
|
||||
# repository String Name of a target repository in <owner>/<repo> format. Defaults to GITHUB_REPOSITORY env variable
|
||||
# target_commitish String Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Defaults to repository default branch.
|
||||
# token String Secret GitHub Personal Access Token. Defaults to ${{ github.token }}
|
||||
# discussion_category_name String If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see "Managing categories for discussions in your repository."
|
||||
# generate_release_notes Boolean Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes. See the GitHub docs for this feature for more information
|
||||
# append_body Boolean Append to existing body instead of overwriting it
|
||||
# make_latest String Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be true, false, or legacy. Uses GitHub api defaults if not provided
|
||||
130
.gitignore
vendored
130
.gitignore
vendored
@ -1,14 +1,9 @@
|
||||
# For troubleshooting: git check-ignore -v --no-index PATHS
|
||||
|
||||
# misc stuff
|
||||
_*
|
||||
*~
|
||||
*.o
|
||||
\#*
|
||||
.\#*
|
||||
.trash
|
||||
*.gz
|
||||
*.zip
|
||||
|
||||
# dev stuff
|
||||
.build
|
||||
@ -19,9 +14,30 @@ _*
|
||||
.vscode
|
||||
tags
|
||||
TAGS
|
||||
.obsidian
|
||||
stylish-haskell.yaml
|
||||
*.m4-e
|
||||
/debug.log
|
||||
/tools/pandoc-demote-headers
|
||||
/tools/pandoc-drop-html-blocks
|
||||
/tools/pandoc-drop-html-inlines
|
||||
/tools/pandoc-drop-links
|
||||
/tools/pandoc-drop-notes
|
||||
/tools/pandoc-drop-toc
|
||||
/tools/generatetimeclock
|
||||
|
||||
# Tricksy rules ignoring some typical temp files.
|
||||
# For troubleshooting: git check-ignore --verbose PATHS...
|
||||
# 1- or 2-character filenames, maybe with an extension; but not directories
|
||||
[a-z0-9]
|
||||
[a-z0-9].*
|
||||
[a-z0-9][a-z0-9]
|
||||
[a-z0-9][a-z0-9].*
|
||||
![a-z0-9]/
|
||||
![a-z0-9].*/
|
||||
![a-z0-9][a-z0-9]/
|
||||
![a-z0-9][a-z0-9].*/
|
||||
# files/directories beginning with a number
|
||||
/[0-9]*
|
||||
*.j
|
||||
*.sw[op]
|
||||
|
||||
# haskell stuff
|
||||
*.dyn_hi
|
||||
@ -29,7 +45,6 @@ stylish-haskell.yaml
|
||||
*.hi
|
||||
*.p_o
|
||||
*.hp
|
||||
*.prof
|
||||
package.yaml-e
|
||||
.cabal-sandbox/
|
||||
cabal-dev*
|
||||
@ -38,35 +53,31 @@ cabal.sandbox.config
|
||||
dist/
|
||||
dist-newstyle/
|
||||
.ghc.environment.*
|
||||
stack*.yaml.lock
|
||||
.stack-work/
|
||||
/Shake
|
||||
/.shake.html
|
||||
.stack-work/
|
||||
/lsp/
|
||||
Setup
|
||||
modules*.svg
|
||||
packages*.svg
|
||||
/*.packages
|
||||
/headroom-templates
|
||||
.headroom.yaml
|
||||
|
||||
# ignore typical test file names (but not dirs)
|
||||
|
||||
/[0-9]*
|
||||
!/[0-9]*/
|
||||
|
||||
[a-z0-9]
|
||||
![a-z0-9]/
|
||||
|
||||
[a-z0-9][a-z0-9]
|
||||
![a-z0-9][a-z0-9]/
|
||||
|
||||
/[a-z0-9].*
|
||||
![a-z0-9].*/
|
||||
|
||||
/[a-z0-9][a-z0-9].*/
|
||||
![a-z0-9][a-z0-9].*/
|
||||
|
||||
/test*
|
||||
# hledger stuff
|
||||
old
|
||||
/.old
|
||||
/log
|
||||
/profs/*
|
||||
/*.prof.*
|
||||
/bin/**
|
||||
!/bin/*.hs
|
||||
!/bin/*.sh
|
||||
!/bin/*.md
|
||||
/.latest.*
|
||||
hledger/test/addons/hledger-*
|
||||
tools/generatejournal
|
||||
tools/simplebench
|
||||
/examples/[1-9]0*.journal
|
||||
*.webmanual.md
|
||||
*.m4-e
|
||||
stack*.yaml.lock
|
||||
bench
|
||||
|
||||
# hledger-web stuff
|
||||
/config
|
||||
@ -76,48 +87,15 @@ packages*.svg
|
||||
hledger-web/static/tmp/
|
||||
hledger-web/yesod-devel/
|
||||
.hledger-web_client_session_key.aes
|
||||
/hledger-web/demo/
|
||||
|
||||
# hledger stuff
|
||||
#*.webmanual.md
|
||||
old
|
||||
.old
|
||||
/log
|
||||
*.log
|
||||
/profs/*
|
||||
/*.prof.*
|
||||
/tmp
|
||||
/bench*
|
||||
# sandstorm stuff
|
||||
.vagrant
|
||||
*.spk
|
||||
|
||||
#/bin - see bin/.gitignore
|
||||
|
||||
/examples
|
||||
#/examples/[1-9]*.journal
|
||||
|
||||
/hledger/test/cli/addons
|
||||
/hledger/hledger.md
|
||||
/hledger-ui/hledger-ui.md
|
||||
/hledger-web/hledger-web.md
|
||||
/tools/generatejournal
|
||||
/tools/relnotes
|
||||
/tools/simplebench
|
||||
/tools/pandoc-demote-headers
|
||||
/tools/pandoc-drop-html-blocks
|
||||
/tools/pandoc-drop-html-inlines
|
||||
/tools/pandoc-drop-links
|
||||
/tools/pandoc-drop-notes
|
||||
/tools/pandoc-drop-toc
|
||||
/tools/generatetimeclock
|
||||
/hledger-lib/test/doctests
|
||||
/examples/edk-hledger-ui-mobile.gif
|
||||
/examples/tty-ui-1.gif
|
||||
/site/**
|
||||
!/site/src/*.md
|
||||
/finance
|
||||
/examples/demo/
|
||||
/doc/ghrelnotes.md
|
||||
/doc/RELEASING2.md
|
||||
# recent stuff
|
||||
/commands
|
||||
/.obsidian
|
||||
/.github/workflows/README
|
||||
/checks
|
||||
/tools/docshelltest
|
||||
.latest.*
|
||||
.github/workflows/ci-arm.yml
|
||||
/headroom-templates
|
||||
.headroom.yaml
|
||||
|
||||
174
.mailmap
174
.mailmap
@ -1,170 +1,14 @@
|
||||
# sort -f
|
||||
Aerex <nanaus13@yahoo.com>
|
||||
afarrow <afarrow@users.noreply.github.com>
|
||||
agander <agander@gmail.com>
|
||||
Aiken Cairncross <acairncross@gmail.com>
|
||||
Alan Young <harleypig@harleypig.com>
|
||||
Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
Aleksandar Dimitrov <git@aleks.bg>
|
||||
Alex Chen <awchen@ucalgary.ca>
|
||||
Alex Hirzel <alex@hirzel.us>
|
||||
Alvaro Fernando García <alvarofernandogarcia@gmail.com>
|
||||
Amarandus <carl.schneider+github@ruhr-uni-bochum.de>
|
||||
Amitai Burstein <amitai@gizra.com>
|
||||
Andreas Pauley <andreas@pauley.org.za>
|
||||
Andrew Jones <ascjones@gmail.com>
|
||||
Andrew Lelechenko <andrew.lelechenko@gmail.com>
|
||||
Andriy Mykhaylyk <erp.lsf@gmail.com>
|
||||
aragaer <aragaer@gmail.com>
|
||||
Arjen Langebaerd <alangebaerd@gmail.com>
|
||||
Arnout Engelen <arnout@bzzt.net>
|
||||
Arsen Arsenović <arsen@aarsen.me>
|
||||
awjchen <awjchen@users.noreply.github.com>
|
||||
Ben Boeckel <mathstuf@gmail.com>
|
||||
Ben Creasy <ben@bencreasy.com>
|
||||
bobobo1618 <bobobo1618@users.noreply.github.com>
|
||||
Boyd Kelly <bkelly@coastsystems.net>
|
||||
Brian Scott <briananthonyscott@gmail.com>
|
||||
Brian Wignall <brianwignall@gmail.com>
|
||||
Bryan Richter <bryan.richter@gmail.com>
|
||||
Caleb Maclennan <caleb@alerque.com>
|
||||
Carel Fellinger <cfellinger@users.noreply.github.com>
|
||||
Carl Richard Theodor Schneider <carl.schneider@ruhr-uni-bochum.de>
|
||||
Carlos Lopez-Camey <c.lopez@kmels.net>
|
||||
Charlie Ambrose <C.Ambrose@iinet.net.au>
|
||||
Charlotte Van Petegem <charlotte.vanpetegem@ugent.be>
|
||||
charukiewicz <charukiewicz@protonmail.com>
|
||||
Chris Lemaire <c.lemaire@student.tudelft.nl>
|
||||
Christian G. Warden <cwarden@xerus.org>
|
||||
Christoph Nicolai <mail@christoph-nicolai.de>
|
||||
Clint Adams <clint@debian.org> <clint@softwarefreedom.org>
|
||||
Colin Woodbury <colin@fosskers.ca>
|
||||
crocket <748856+crocket@users.noreply.github.com>
|
||||
Damien Cassou <damien@cassou.me>
|
||||
Daniel Gröber <dxld@darkboxed.org>
|
||||
David D Lowe <daviddlowe.flimm@gmail.com>
|
||||
David Reaver <johndreaver@gmail.com>
|
||||
David Zhang <crispgm@gmail.com>
|
||||
Dmitry Astapov <dastapov@gmail.com>
|
||||
Dominik Süß <dominik.suess@outlook.at>
|
||||
Doug Goldstein <cardoe@cardoe.com>
|
||||
Eli Flanagan <eli@typedspace.com>
|
||||
Elijah Caine <elijahcainemv@gmail.com>
|
||||
Eric Kow <eric.kow@gmail.com>
|
||||
Eric Mertens <emertens@galois.com> <emertens@gmail.com>
|
||||
Everett Hildenbrandt <hildenb2@illinois.edu>
|
||||
Evilham <cvs@evilham.com>
|
||||
Felix Van der Jeugt <felix.vanderjeugt@posteo.net>
|
||||
Felix Yan <felixonmars@archlinux.org>
|
||||
flip111 <flip101@gmail.com>
|
||||
Fun Ilrys (Nissar Chababy) <contact@funilrys.com>
|
||||
Gabriel Ebner <gebner@gebner.org>
|
||||
Gaith Hallak <gaithhallak@gmail.com>
|
||||
Garret McGraw <jetaimed@gmail.com>
|
||||
Gergely Risko <errge@nilcons.com>
|
||||
gwern <gwern@gwern.net> <gwern0@gmail.com>
|
||||
Hans-Peter Deifel <hpd@hpdeifel.de>
|
||||
Henning Thielemann <git@henning-thielemann.de>
|
||||
Ilja Kocken <i.j.kocken@uu.nl>
|
||||
Imuli <i@imu.li>
|
||||
J. B. Rainsberger <me@jbrains.ca>
|
||||
Jacek Generowicz <jacg@my-post-office.net>
|
||||
Jacob Weisz <inbox@jacobweisz.com>
|
||||
Jakob Schöttl <jschoett@gmail.com>
|
||||
Jakub Zárybnický <kubaz@inuits.eu> <jakub.zarybnicky@inuits.eu>
|
||||
Jan Zerebecki <jan@zerebecki.de>
|
||||
Jay Neubrand <jneubrand@users.noreply.github.com>
|
||||
Jeff Richards <jeff@jrichards.ca>
|
||||
Jesse Rosenthal <jrosenthal@jhu.edu>
|
||||
Joachim Breitner <mail@joachim-breitner.de>
|
||||
Joaquin "Florius" Azcarate <j@florius.com.ar>
|
||||
Joe Horsnell <github@joehorsnell.com>
|
||||
Johann Klähn <kljohann@gmail.com>
|
||||
Johannes Gerer <oss@johannesgerer.com>
|
||||
John Wiegley <johnw@newartisans.com>
|
||||
Jonathan Dowland <jon@dow.land>
|
||||
Joseph Weston <joseph@weston.cloud>
|
||||
Joshua Chia <joshchia@gmail.com>
|
||||
Joshua Kehn <josh@kehn.us>
|
||||
Judah Jacobson <judah.jacobson@gmail.com>
|
||||
Julien Moutinho <julm+hledger@autogeree.net>
|
||||
jungle-boogie <sean@jungleboogie.me>
|
||||
Justin Le <mstksg@gmail.com> <justin@jle.im>
|
||||
Kyle Marek-Spartz <kyle.marekspartz@govdelivery.com>
|
||||
Lawrence Wu <lawrencejwu@gmail.com>
|
||||
legrostdg <gueux+github@gueux.org>
|
||||
Luca Molteni <volothamp@gmail.com>
|
||||
Léo Gaspard <leo@gaspard.io>
|
||||
M Parker <mparker17@users.noreply.github.com>
|
||||
Malte Brandy <malte.brandy@maralorn.de>
|
||||
Mark Hansen <mark@markhansen.co.nz>
|
||||
Marko Kocić <marko@euptera.com>
|
||||
Marko Kocić <marko@euptera.com> marko.kocic <marko.kocic@gmail.com>
|
||||
Martin Michlmayr <tbm@cyrius.com>
|
||||
Mateus Furquim <mfurquim@users.noreply.github.com>
|
||||
Matthias Kauer <mk.software@zuez.org>
|
||||
Max Bolingbroke <batterseapower@hotmail.com>
|
||||
Max Thomas <max@maxthomas.io>
|
||||
Michael Grünewald <mail@michaelgruenewald.eu>
|
||||
Michael Kainer <kaini@pushrax.com>
|
||||
Clint Adams <clint@softwarefreedom.org> <clint@debian.org>
|
||||
Marko Kocić <marko.kocic@gmail.com>
|
||||
Marko Kocić <marko.kocic@gmail.com> <marko@euptera.com>
|
||||
Michael Snoyman <michael@snoyman.com>
|
||||
Michael Walker <mike@barrucadu.co.uk>
|
||||
Mick Dekkers <mickdekkersnl@gmail.com>
|
||||
Mitchell Rosen <mitchellwrosen@gmail.com>
|
||||
Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
|
||||
Mykola Orliuk <virkony@gmail.com>
|
||||
Nadrieril <nadrieril@gmail.com>
|
||||
Nicholas Niro <blowfist@xroutine.net>
|
||||
Nick Ingolia <nick@ingolia.org>
|
||||
Nicolas Wavrant <nicolas.wavrant@gmail.com>
|
||||
Nikhil Jha <nikhiljha@users.noreply.github.com>
|
||||
Nissar Chababy <contact@funilrys.com>
|
||||
Nolan Darilek <nolan@thewordnerd.info>
|
||||
ob <ob@obraun.net>
|
||||
Omari Norman <omari@smileystation.com>
|
||||
Patrick Fiaux <patrick@fiaux.dev>
|
||||
Patrik Keller <git@pkel.dev>
|
||||
Pavan Rikhi <pavan.rikhi@gmail.com>
|
||||
Pavlo Kerestey <pavlo@kerestey.net>
|
||||
Peter Sagerson <psagers@ignorare.net>
|
||||
Peter Simons <simons@cryp.to>
|
||||
Philipp Klocke <Phil_K97@gmx.de>
|
||||
Pia Mancini <piamancini@gmail.com>
|
||||
Pranesh Prakash <the.solipsist@gmail.com>
|
||||
Rick Lupton <r.lupton@gmail.com>
|
||||
Robert Nielsen <32415800+RobertNielsen1@users.noreply.github.com>
|
||||
Roman Cheplyaka <roma@ro-che.info>
|
||||
Rui Chen <chenrui333@gmail.com>
|
||||
Ryan Desfosses <rdesfo@users.noreply.github.com>
|
||||
Ryan Desfosses <ryan@desfo.org>
|
||||
S. Zeid <s@zeid.me>
|
||||
Sam Doshi <sam@metal-fish.co.uk>
|
||||
Sam Jeeves <sam.jeeves@live.com>
|
||||
Sam Jeeves <sam.jeeves@live.com>
|
||||
Samuel May <ag.eitilt@gmail.com>
|
||||
Sergei Trofimovich <slyfox@community.haskell.org> <siarheit@google.com>
|
||||
Sergey Astanin <s.astanin@gmail.com>
|
||||
ShrykeWindgrace <shryke.windgrace@gmail.com>
|
||||
Shubham Lagwankar <shubhu105@gmail.com>
|
||||
Simon Hengel <sol@typeful.net>
|
||||
Sam Almahri <sam.salmahri@gmail.com>
|
||||
Simon Michael <simon@joyful.com> <azure-pipelines[bot]@users.noreply.github.com>
|
||||
Simon Michael <simon@joyful.com> <webmaster@joyful.com>
|
||||
SpicyCat <yanglingit@outlook.com>
|
||||
Stefano Rodighiero <stefano.rodighiero@gmail.com>
|
||||
Stephen Morgan <morgan.stephen99@gmail.com> <Xitian9@users.noreply.github.com>
|
||||
Steven R. Baker <steven@stevenrbaker.com>
|
||||
TANIGUCHI Kohei <cohey@taniguchikohei-MacBook-Air.local>
|
||||
Thomas R. Koll <tomk32@tomk32.de> <tomk32@gmail.com>
|
||||
Mykola Orliuk <virkony@gmail.com>
|
||||
Oliver Braun <ob@obraun.net>
|
||||
Ryan Desfosses <ryan@desfo.org> <rdesfo@users.noreply.github.com>
|
||||
Sergei Trofimovich <siarheit@google.com> <slyfox@community.haskell.org>
|
||||
Thomas R. Koll <tomk32@gmail.com> <tomk32@tomk32.de>
|
||||
Tim Docker <tim@dockerz.net>
|
||||
Timofey ZAKREVSKIY <timofey.zakrevskiy@3ds.com>
|
||||
toonn <toonn@toonn.io>
|
||||
Trevor Riles <trevor@riles.io>
|
||||
Trygve Laugstøl <trygvis@inamo.no>
|
||||
Vladimir Sorokin <vsorokin87@gmail.com>
|
||||
Vladimir Zhelezov <zhelezov@gmail.com>
|
||||
Wad <wad209@users.noreply.github.com>
|
||||
Xinruo Sun <xiaoruoruo@gmail.com>
|
||||
Yann Büchau <nobodyinperson@posteo.de>
|
||||
Yehoshua Pesach Wallach <yehoshuapw@gmail.com>
|
||||
zieone <42358507+zieone@users.noreply.github.com>
|
||||
gwern <gwern@gwern.net> <gwern0@gmail.com>
|
||||
|
||||
@ -7,6 +7,6 @@
|
||||
- Navigate your terminal to your local hledger repository folder
|
||||
- Run `vagrant-spk vm up`
|
||||
- Run `vagrant-spk dev` to run the app in Sandstorm dev mode
|
||||
- Visit http://local.sandstorm.io:6090 in your browser to see changes and test
|
||||
- Visit http://local.sandstorm.io:6080 in your browser to see changes and test
|
||||
- Press Ctrl-C to exit dev mode
|
||||
- Run `vagrant-spk pack hledger.spk` to create the Sandstorm package file
|
||||
28
.sandstorm/Vagrantfile
vendored
28
.sandstorm/Vagrantfile
vendored
@ -1,8 +1,6 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# CAUTION: DO NOT MAKE CHANGES TO THIS FILE. The vagrant-spk upgradevm process will overwrite it.
|
||||
|
||||
# Guess at a reasonable name for the VM based on the folder vagrant-spk is
|
||||
# run from. The timestamp is there to avoid conflicts if you have multiple
|
||||
# folders with the same name.
|
||||
@ -19,10 +17,9 @@ unless Vagrant::DEFAULT_SERVER_URL.frozen?
|
||||
end
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
# Base on a 64-bit Debian box with vboxsf support (ex. contrib-buster64, bullseye64)
|
||||
config.vm.box = "debian/bookworm64"
|
||||
config.vm.post_up_message = "Your virtual server is running at: http://local.sandstorm.io:6090"
|
||||
|
||||
# Base on the Sandstorm snapshots of the official Debian 9 (stretch) box with vboxsf support.
|
||||
config.vm.box = "debian/contrib-stretch64"
|
||||
config.vm.box_version = "9.3.0"
|
||||
|
||||
if Vagrant.has_plugin?("vagrant-vbguest") then
|
||||
# vagrant-vbguest is a Vagrant plugin that upgrades
|
||||
@ -31,13 +28,12 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
# needs to know how to compile kernel modules, etc., and so
|
||||
# we give it this hint about operating system type.
|
||||
config.vm.guest = "debian"
|
||||
config.vbguest.auto_update = false
|
||||
end
|
||||
|
||||
# We forward port 6090, the vagrant-spk web port, so that developers can
|
||||
# visit their Sandstorm app from their browser as local.sandstorm.io:6090
|
||||
# (aka 127.0.0.1:6090).
|
||||
config.vm.network :forwarded_port, guest: 6090, host: 6090, host_ip: "127.0.0.1"
|
||||
# We forward port 6080, the Sandstorm web port, so that developers can
|
||||
# visit their sandstorm app from their browser as local.sandstorm.io:6080
|
||||
# (aka 127.0.0.1:6080).
|
||||
config.vm.network :forwarded_port, guest: 6080, host: 6080, host_ip: "127.0.0.1"
|
||||
|
||||
# Use a shell script to "provision" the box. This installs Sandstorm using
|
||||
# the bundled installer.
|
||||
@ -62,8 +58,12 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
cpus = `nproc`.to_i
|
||||
total_kB_ram = `grep MemTotal /proc/meminfo | awk '{print $2}'`.to_i
|
||||
elsif host =~ /mingw/
|
||||
# powershell may not be available on Windows XP and Vista, so wrap this in a rescue block
|
||||
begin
|
||||
cpus = `powershell -Command "(Get-WmiObject Win32_Processor -Property NumberOfLogicalProcessors | Select-Object -Property NumberOfLogicalProcessors | Measure-Object NumberOfLogicalProcessors -Sum).Sum"`.to_i
|
||||
total_kB_ram = `powershell -Command "[math]::Round((Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory)"`.to_i / 1024
|
||||
total_kB_ram = `powershell -Command "Get-CimInstance -class cim_physicalmemory | % $_.Capacity}"`.to_i / 1024
|
||||
rescue
|
||||
end
|
||||
end
|
||||
# Use the same number of CPUs within Vagrant as the system, with 1
|
||||
# as a default.
|
||||
@ -80,7 +80,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
if total_kB_ram.nil? or total_kB_ram < 2048000
|
||||
assign_ram_mb = 512
|
||||
else
|
||||
assign_ram_mb = (total_kB_ram / 1024 / 4)
|
||||
assign_ram_mb = (total_kB_ram / 1024 / 2)
|
||||
end
|
||||
# Actually apply these CPU/memory values to the providers.
|
||||
config.vm.provider :virtualbox do |vb, override|
|
||||
@ -91,7 +91,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
|
||||
# /opt/app and /host-dot-sandstorm are used by vagrant-spk
|
||||
override.vm.synced_folder "..", "/opt/app"
|
||||
override.vm.synced_folder ENV["HOME"] + "/.sandstorm", "/host-dot-sandstorm", mount_options: ["x-systemd.automount"]
|
||||
override.vm.synced_folder ENV["HOME"] + "/.sandstorm", "/host-dot-sandstorm"
|
||||
# /vagrant is not used by vagrant-spk; we need this line so it gets disabled; if we removed the
|
||||
# line, vagrant would automatically insert a synced folder in /vagrant, which is not what we want.
|
||||
override.vm.synced_folder "..", "/vagrant", disabled: true
|
||||
|
||||
@ -1,8 +1,3 @@
|
||||
# V1.31 (2023-10-20)
|
||||
|
||||
* Upgrade to HLedger 1.31
|
||||
* Add support for sharing permissions
|
||||
|
||||
# V1.9.2 (2018-06-05)
|
||||
|
||||
* Upgrade to HLedger 1.9.2
|
||||
|
||||
@ -2,4 +2,4 @@ hledger (http://hledger.org) is a dependable, precise, cross-platform program fo
|
||||
|
||||
In double-entry accounting, each transaction must be balanced: An equal amount added to one account must be subtracted from another. You may wish to consult hledger documentation or other tutorials on the web to learn how to use double-entry accounting.
|
||||
|
||||
We welcome bug reports with more detail (http://bugs.hledger.org/new), general hledger-web improvements, backers and sponsors (http://hledger.org).
|
||||
Sandstorm users, thanks for your feedback. hledger's web UI is a simple one to fit current development resources, and I'm sorry that Sandstorm integration is lacking. Your help is needed. We have an open issue for this where you can add a bounty or contribute patches (https://github.com/simonmichael/hledger/issues/425). We also welcome bug reports with more detail (http://bugs.hledger.org/new), general hledger-web improvements, backers and sponsors (http://hledger.org).
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# CAUTION: DO NOT MAKE CHANGES TO THIS FILE. The vagrant-spk upgradevm process will overwrite it.
|
||||
# App-specific setup should be done in the setup.sh file.
|
||||
|
||||
# Set options for curl. Since we only want to show errors from these curl commands, we also use
|
||||
# 'cat' to buffer the output; for more information:
|
||||
# https://github.com/sandstorm-io/vagrant-spk/issues/158
|
||||
@ -12,13 +9,9 @@ CURL_OPTS="--silent --show-error"
|
||||
echo localhost > /etc/hostname
|
||||
hostname localhost
|
||||
|
||||
# Grub updates don't silent install well
|
||||
apt-mark hold grub-pc
|
||||
# Install curl that is needed below.
|
||||
apt-get update
|
||||
apt-get upgrade -y
|
||||
|
||||
# Install curl needed below, and gnupg for package signing
|
||||
apt-get install -y curl gnupg
|
||||
apt-get install -y curl
|
||||
|
||||
# The following line copies stderr through stderr to cat without accidentally leaving it in the
|
||||
# output file. Be careful when changing. See: https://github.com/sandstorm-io/vagrant-spk/pull/159
|
||||
@ -34,7 +27,7 @@ if [[ ! -f /host-dot-sandstorm/caches/$SANDSTORM_PACKAGE ]] ; then
|
||||
fi
|
||||
if [ ! -e /opt/sandstorm/latest/sandstorm ] ; then
|
||||
echo -n "Installing Sandstorm version ${SANDSTORM_CURRENT_VERSION}..."
|
||||
bash /host-dot-sandstorm/caches/install.sh -d -e -p 6090 "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE" >/dev/null
|
||||
bash /host-dot-sandstorm/caches/install.sh -d -e "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE" >/dev/null
|
||||
echo "...done."
|
||||
fi
|
||||
modprobe ip_tables
|
||||
@ -45,10 +38,6 @@ usermod -a -G 'sandstorm' 'vagrant'
|
||||
sudo sed --in-place='' \
|
||||
--expression='s/^BIND_IP=.*/BIND_IP=0.0.0.0/' \
|
||||
/opt/sandstorm/sandstorm.conf
|
||||
|
||||
# Force vagrant-spk to use the strict CSP, see sandstorm#3424 for details.
|
||||
echo 'ALLOW_LEGACY_RELAXED_CSP=false' >> /opt/sandstorm/sandstorm.conf
|
||||
|
||||
sudo service sandstorm restart
|
||||
# Enable apt-cacher-ng proxy to make things faster if one appears to be running on the gateway IP
|
||||
GATEWAY_IP=$(ip route | grep ^default | cut -d ' ' -f 3)
|
||||
|
||||
@ -29,4 +29,4 @@ set -euo pipefail
|
||||
mkdir -p /var/lib/hledger
|
||||
touch /var/lib/hledger/Ledger
|
||||
cd /var
|
||||
hledger-web --allow=sandstorm --serve --base-url='' -f /var/lib/hledger/Ledger --port 8000
|
||||
hledger-web --capabilities-header=X-Sandstorm-Permissions --serve --base-url='' -f /var/lib/hledger/Ledger --port 8000
|
||||
|
||||
@ -2,37 +2,56 @@
|
||||
# This file is automatically updated and rewritten in sorted order every time
|
||||
# the app runs in dev mode. You may manually add or remove files, but don't
|
||||
# expect comments or ordering to be retained.
|
||||
bin
|
||||
bin/bash
|
||||
bin/mkdir
|
||||
bin/touch
|
||||
etc/gai.conf
|
||||
etc/ld.so.cache
|
||||
etc/localtime
|
||||
lib
|
||||
lib64
|
||||
lib/terminfo/d/dumb
|
||||
lib/x86_64-linux-gnu/ld-2.24.so
|
||||
lib/x86_64-linux-gnu/libc-2.24.so
|
||||
lib/x86_64-linux-gnu/libc.so.6
|
||||
lib/x86_64-linux-gnu/libdl-2.24.so
|
||||
lib/x86_64-linux-gnu/libdl.so.2
|
||||
lib/x86_64-linux-gnu/libgcc_s.so.1
|
||||
lib/x86_64-linux-gnu/libm-2.24.so
|
||||
lib/x86_64-linux-gnu/libm.so.6
|
||||
lib/x86_64-linux-gnu/libncurses.so.5
|
||||
lib/x86_64-linux-gnu/libncurses.so.5.9
|
||||
lib/x86_64-linux-gnu/libnsl-2.24.so
|
||||
lib/x86_64-linux-gnu/libnsl.so.1
|
||||
lib/x86_64-linux-gnu/libnss_compat-2.24.so
|
||||
lib/x86_64-linux-gnu/libnss_compat.so.2
|
||||
lib/x86_64-linux-gnu/libnss_files-2.24.so
|
||||
lib/x86_64-linux-gnu/libnss_files.so.2
|
||||
lib/x86_64-linux-gnu/libnss_nis-2.24.so
|
||||
lib/x86_64-linux-gnu/libnss_nis.so.2
|
||||
lib/x86_64-linux-gnu/libpcre.so.3
|
||||
lib/x86_64-linux-gnu/libpcre.so.3.13.3
|
||||
lib/x86_64-linux-gnu/libpthread-2.24.so
|
||||
lib/x86_64-linux-gnu/libpthread.so.0
|
||||
lib/x86_64-linux-gnu/librt-2.24.so
|
||||
lib/x86_64-linux-gnu/librt.so.1
|
||||
lib/x86_64-linux-gnu/libselinux.so.1
|
||||
lib/x86_64-linux-gnu/libtinfo.so.5
|
||||
lib/x86_64-linux-gnu/libtinfo.so.5.9
|
||||
lib/x86_64-linux-gnu/libutil-2.24.so
|
||||
lib/x86_64-linux-gnu/libutil.so.1
|
||||
lib/x86_64-linux-gnu/libz.so.1
|
||||
lib/x86_64-linux-gnu/libz.so.1.2.8
|
||||
lib64/ld-linux-x86-64.so.2
|
||||
opt/app/.sandstorm/launcher.sh
|
||||
proc/cpuinfo
|
||||
sandstorm-http-bridge
|
||||
sandstorm-http-bridge-config
|
||||
sandstorm-manifest
|
||||
usr/bin/bash
|
||||
usr/bin/mkdir
|
||||
usr/bin/touch
|
||||
usr/lib/terminfo/d/dumb
|
||||
usr/lib/x86_64-linux-gnu/gconv/UTF-32.so
|
||||
usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
|
||||
usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
|
||||
usr/lib/x86_64-linux-gnu/libc.so.6
|
||||
usr/lib/x86_64-linux-gnu/libffi.so.6
|
||||
usr/lib/x86_64-linux-gnu/libgmp.so.10
|
||||
usr/lib/x86_64-linux-gnu/libgmp.so.10.4.1
|
||||
usr/lib/x86_64-linux-gnu/libm.so.6
|
||||
usr/lib/x86_64-linux-gnu/libpcre2-8.so.0
|
||||
usr/lib/x86_64-linux-gnu/libpcre2-8.so.0.11.2
|
||||
usr/lib/x86_64-linux-gnu/libselinux.so.1
|
||||
usr/lib/x86_64-linux-gnu/libtinfo.so.6
|
||||
usr/lib/x86_64-linux-gnu/libtinfo.so.6.4
|
||||
usr/lib/x86_64-linux-gnu/libz.so.1
|
||||
usr/lib/x86_64-linux-gnu/libz.so.1.2.13
|
||||
usr/lib64/ld-linux-x86-64.so.2
|
||||
usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2
|
||||
usr/local/bin/hledger-web
|
||||
usr/share/zoneinfo/Etc/UTC
|
||||
usr/share/zoneinfo/GMT
|
||||
usr/share/zoneinfo/GMT+0
|
||||
|
||||
@ -17,11 +17,11 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# This manifest is included in your app package to tell Sandstorm
|
||||
# about your app.
|
||||
|
||||
appTitle = (defaultText = "Hledger Web"),
|
||||
appTitle = (defaultText = "HLedger Web"),
|
||||
|
||||
appVersion = 5, # Increment this for every release.
|
||||
appVersion = 3, # Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "1.31"),
|
||||
appMarketingVersion = (defaultText = "1.9.2"),
|
||||
# Human-readable representation of appVersion. Should match the way you
|
||||
# identify versions of your app in documentation and marketing.
|
||||
|
||||
@ -48,14 +48,13 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# https://github.com/sandstorm-io/sandstorm/blob/master/src/sandstorm/package.capnp
|
||||
icons = (
|
||||
# Various icons to represent the app in various contexts.
|
||||
# XXX better to use the coins image from https://hledger.org probably. Must it be svg ?
|
||||
appGrid = (svg = embed "appGrid.svg"),
|
||||
grain = (svg = embed "grain.svg"),
|
||||
market = (svg = embed "market.svg"),
|
||||
#marketBig = (svg = embed "path/to/market-big-300x300.svg"),
|
||||
),
|
||||
|
||||
website = "https://hledger.org",
|
||||
website = "http://hledger.org",
|
||||
# This should be the app's main website url.
|
||||
|
||||
codeUrl = "https://github.com/simonmichael/hledger",
|
||||
@ -93,7 +92,7 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# Further details including how to set up GPG and how to use keybase.io can be found
|
||||
# at https://docs.sandstorm.io/en/latest/developing/publishing-apps/#verify-your-identity
|
||||
|
||||
upstreamAuthor = "Hledger Team",
|
||||
upstreamAuthor = "HLedger Team",
|
||||
# Name of the original primary author of this app, if it is different from the person who
|
||||
# produced the Sandstorm package. Setting this implies that the author connected to the PGP
|
||||
# signature only "packaged" the app for Sandstorm, rather than developing the app.
|
||||
@ -205,38 +204,41 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
description = (defaultText = "grants ability to append transactions to the ledger"),
|
||||
),
|
||||
(
|
||||
name = "edit",
|
||||
title = (defaultText = "edit"),
|
||||
description = (defaultText = "grants ability to modify transactions and directives or erase the entire ledger"),
|
||||
name = "manage",
|
||||
title = (defaultText = "manage"),
|
||||
description = (defaultText = "grants ability to modify or replace the entire ledger"),
|
||||
),
|
||||
],
|
||||
roles = [
|
||||
# Roles are logical collections of permissions. For instance, your app may have
|
||||
# a "viewer" role and an "editor" role
|
||||
(
|
||||
title = (defaultText = "manager"),
|
||||
# Name of the role. Shown in the Sandstorm UI to indicate which users have which roles.
|
||||
title = (defaultText = "viewer"),
|
||||
|
||||
permissions = [true, true, true],
|
||||
# An array indicating which permissions this role carries.
|
||||
# It should be the same length as the permissions array in
|
||||
# viewInfo, and the order of the lists must match.
|
||||
permissions = [true, false, false],
|
||||
|
||||
verbPhrase = (defaultText = "has full access to the ledger"),
|
||||
# Brief explanatory text to show in the sharing UI indicating
|
||||
# what a user assigned this role will be able to do with the grain.
|
||||
verbPhrase = (defaultText = "can view the ledger"),
|
||||
|
||||
description = (defaultText = "managers can modify the ledger in any way."),
|
||||
# Prose describing what this role means, suitable for a tool tip or similar help text.
|
||||
description = (defaultText = "viewers can only view the ledger."),
|
||||
),
|
||||
(
|
||||
title = (defaultText = "adder"),
|
||||
permissions = [true, true, false],
|
||||
verbPhrase = (defaultText = "can append new transactions"),
|
||||
description = (defaultText = "adders can view the ledger and add new transactions to it."),
|
||||
),
|
||||
(
|
||||
title = (defaultText = "editor"),
|
||||
permissions = [true, true, true],
|
||||
verbPhrase = (defaultText = "has full access to the ledger"),
|
||||
description = (defaultText = "editors can change or erase transactions and directives."),
|
||||
permissions = [true, true, false],
|
||||
verbPhrase = (defaultText = "can append new transactions"),
|
||||
description = (defaultText = "editors can view the ledger or append new transactions to it."),
|
||||
),
|
||||
(
|
||||
title = (defaultText = "viewer"),
|
||||
permissions = [true, false, false],
|
||||
verbPhrase = (defaultText = "can view the ledger"),
|
||||
description = (defaultText = "viewers can only view the ledger."),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -254,7 +256,6 @@ const myCommand :Spk.Manifest.Command = (
|
||||
environ = [
|
||||
# Note that this defines the *entire* environment seen by your app.
|
||||
(key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
|
||||
(key = "HOME", value = "/var/lib/hledger"),
|
||||
(key = "SANDSTORM", value = "1"),
|
||||
# Export SANDSTORM=1 into the environment, so that apps running within Sandstorm
|
||||
# can detect if $SANDSTORM="1" at runtime, switching UI and/or backend to use
|
||||
|
||||
@ -22,4 +22,4 @@ set -euo pipefail
|
||||
# By default, this script does nothing. You'll have to modify it as
|
||||
# appropriate for your application.
|
||||
apt-get install -y libtinfo-dev
|
||||
curl -ssl -L https://get.haskellstack.org/ | sh
|
||||
curl -ssl https://get.haskellstack.org/ | sh
|
||||
|
||||
2
.vscode/notebooks/README.md
vendored
2
.vscode/notebooks/README.md
vendored
@ -1,2 +0,0 @@
|
||||
Some VS Code notebooks. Viewing these requires VS Code and extensions
|
||||
GitHub Issue Notebooks, REST Book.
|
||||
1
.vscode/notebooks/hledger-web.restbook
vendored
1
.vscode/notebooks/hledger-web.restbook
vendored
File diff suppressed because one or more lines are too long
57
.vscode/notebooks/issues.github-issues
vendored
57
.vscode/notebooks/issues.github-issues
vendored
@ -1,57 +0,0 @@
|
||||
[
|
||||
{
|
||||
"kind": 1,
|
||||
"language": "markdown",
|
||||
"value": "# hledger issues notebook\n\n- https://hledger.org/ISSUES.html\n\n<!-- -->\n- https://github.com/microsoft/vscode-github-issue-notebooks#readme\n- https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests\n- https://docs.github.com/en/search-github/getting-started-with-searching-on-github/sorting-search-results"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
"language": "markdown",
|
||||
"value": "## hledger repo"
|
||||
},
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repo=repo:simonmichael/hledger\n$repo is:open sort:created-desc"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
"language": "markdown",
|
||||
"value": "## hledger_site repo"
|
||||
},
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "repo:simonmichael/hledger_site is:open sort:created-desc"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
"language": "markdown",
|
||||
"value": "## hledger_finance repo"
|
||||
},
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "repo:simonmichael/hledger_finance is:open sort:created-desc"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
"language": "markdown",
|
||||
"value": "## hledger mentions in other projects"
|
||||
},
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "-repo:simonmichael/hledger -repo:simonmichael/hledger_site -repo:simonmichael/hledger_finance hledger is:open sort:created-desc"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
"language": "markdown",
|
||||
"value": "## other plaintextaccounting mentions in other projects\n(should exclude things already found by \"hledger\", doesn't)"
|
||||
},
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "-repo:simonmichael/hledger -repo:simonmichael/hledger_site -repo:simonmichael/hledger_finance plaintextaccounting -hledger -repo:commercialhaskell/stack is:open sort:created-desc"
|
||||
}
|
||||
]
|
||||
33
ACHIEVEMENTS.md
Normal file
33
ACHIEVEMENTS.md
Normal file
@ -0,0 +1,33 @@
|
||||
## Achievements
|
||||
|
||||
Some project achievements to unlock!
|
||||
|
||||
> *Being a software maintainer means unending toil in mostly-obscurity, so you've got to seek out the fun where you can!*
|
||||
<!-- https://www.reddit.com/r/haskell/comments/eddwbu/top_nonprogrammingrelated_haskell_apps -->
|
||||
|
||||
- ~~1.0 release~~
|
||||
- ~~packaged in major distros, binaries available~~
|
||||
- ~~pretty good reference docs~~
|
||||
- ~~100 committers~~
|
||||
- ~~1k github stars~~
|
||||
- ~~among top 50 starred haskell projects on github~~
|
||||
- ~~discussed on Hacker News~~
|
||||
- ~~match ledger IRC channel size~~
|
||||
- ~~mentioned in "what good Haskell software exists" discussions~~
|
||||
- ~~among top 40 starred haskell projects on github~~
|
||||
- ~~multiple people providing support~~
|
||||
- ~~pretty good tutorial docs~~
|
||||
- ~~pretty good cookbook docs~~
|
||||
- ~~100 IRC chatters~~
|
||||
- ~~2k github stars~~
|
||||
- **in top 30 github starred haskell projects**
|
||||
- **match ledger speed**
|
||||
- **match ledger committers**
|
||||
- **200 committers**
|
||||
- **[best in class for investment tracking](https://github.com/simonmichael/hledger/issues/1015)**
|
||||
- **2.0 release**
|
||||
- **in top 20 github starred haskell projects**
|
||||
- **match ledger stars**
|
||||
- **match beancount mail list**
|
||||
- **match ledger mail list**
|
||||
- **in top 10 github starred haskell projects**
|
||||
365
BACKLOG.org
Normal file
365
BACKLOG.org
Normal file
@ -0,0 +1,365 @@
|
||||
* BACKLOG.org
|
||||
#+OPTIONS: -:nil \n:t H:9
|
||||
|
||||
An efficient public store of tasks/changes/design notes, mostly from
|
||||
SM's private backlog; things that I/we feel would be nice to have, or
|
||||
investigate further.
|
||||
Here, they all compost nicely in the sun.
|
||||
Some items are out of date and just need to be re-tested and discarded.
|
||||
All help is welcome.
|
||||
|
||||
See also:
|
||||
- http://wishes.hledger.org and http://bugs.hledger.org
|
||||
- https://hledger.org/mockups.html
|
||||
- https://hledger.org/ROADMAP.html
|
||||
|
||||
Some items may render best when viewed in Emacs org mode.
|
||||
|
||||
# Dummy second level heading to ensure only the topics appear in site's page TOC:
|
||||
** Topics:
|
||||
*** wip
|
||||
**** move items here from SM's private backlog
|
||||
*** cli
|
||||
**** help: clarify/improve the various kinds of command line help
|
||||
***** survey/describe
|
||||
Most of these are long, and best viewed with a pager, eg: hledger -h | less
|
||||
|
||||
****** Quick command line help:
|
||||
#+begin_example
|
||||
hledger -h|--help
|
||||
hledger-ui -h|--help
|
||||
hledger-web -h|--help
|
||||
General usage and command line flags for the main hledger UIs.
|
||||
|
||||
hledger
|
||||
hledger CLI's commands list.
|
||||
|
||||
hledger COMMAND -h|--help
|
||||
COMMAND's usage, flags, and manual section.
|
||||
|
||||
#+end_example
|
||||
|
||||
****** User manuals:
|
||||
|
||||
#+begin_example
|
||||
hledger help [-i|-m|-p] [TOPIC]
|
||||
View hledger user manual with info, man or pager, positioned at TOPIC.
|
||||
Good for jumping to a known (or guessed) topic.
|
||||
Good for viewing the manual if you don't have info or man.
|
||||
This is the main manual, covering the CLI, file formats, and concepts.
|
||||
|
||||
hledger --info
|
||||
hledger-ui --info
|
||||
hledger-web --info
|
||||
hledger, hledger-ui or hledger-web's builtin user manual, viewed with info.
|
||||
Best for exploring the topic tree.
|
||||
|
||||
hledger --man
|
||||
hledger-ui --man
|
||||
hledger-web --man
|
||||
hledger, hledger-ui or hledger-web's builtin user manual, viewed with man.
|
||||
Quick and searchable.
|
||||
|
||||
info hledger, man hledger
|
||||
info hledger-ui, man hledger-ui
|
||||
info hledger-web, man hledger-web
|
||||
hledger, hledger-ui, or hledger-web installed user manuals.
|
||||
Same as above, if the manuals are properly installed on your system.
|
||||
|
||||
https://hledger.org/hledger.html
|
||||
https://hledger.org/hledger-ui.html
|
||||
https://hledger.org/hledger-web.html
|
||||
hledger, hledger-ui and hledger-web manuals, viewed on the web.
|
||||
Best for comfortable viewing and navigation when online.
|
||||
|
||||
#+end_example
|
||||
|
||||
**** help improvements
|
||||
***** auto pager
|
||||
***** colour
|
||||
***** show commands to get more detailed help
|
||||
***** list output formats
|
||||
***** list input formats
|
||||
***** list runtime-detected input formats
|
||||
***** more intro/manual in the main --help
|
||||
***** commands list updates
|
||||
Financial reports:
|
||||
aregister (areg) show an account's transactions and running balance
|
||||
register (reg) show postings in all/matched accounts and their total
|
||||
balancesheet (bs) show assets, liabilities and net worth
|
||||
balancesheetequity (bse) show assets, liabilities and equity
|
||||
cashflow (cf) show changes in liquid assets
|
||||
incomestatement (is) show revenues and expenses
|
||||
balance (bal) show custom balance reports, budgets, gains..
|
||||
roi show a return on investment report
|
||||
***** --pivot: list possible arguments in help
|
||||
**** --version: include latest commit date
|
||||
**** --version: include git branch name if not master ?
|
||||
**** disable colors when writing to .txt file ?
|
||||
**** trailing colon makes alias ineffective
|
||||
`--alias expenses:personal:=expenses:`
|
||||
**** unclear error if a trailing slash is written after file name
|
||||
shell completion might wrongly add a trailing slash, eg as with this symlink,
|
||||
resulting in this unclear error:
|
||||
~/notes$ stats -f current.journal/
|
||||
hledger: SourcePos {sourceName = "/Users/simon/.sm/notes/current.journal/", sourceLine = Pos 9, sourceColumn = Pos 1} reading /Users/simon/.sm/notes/current.journal/2018.prices:
|
||||
/Users/simon/current.journal/2018.prices: openFile: inappropriate type (Not a directory)
|
||||
**** -h/--help should work even with unrecognised flags/missing args
|
||||
***** hledger --help ui --watch
|
||||
***** hledger ui --watch --help
|
||||
***** hledger --nosuchflag --help
|
||||
***** hledger nosuchcommand --help
|
||||
****** not expected to work; hledger --help nosuchcommand does work
|
||||
****** unify hledger --help & hledger COMMAND --help more ?
|
||||
**** @ does not expand file names, eg @~/somefile
|
||||
**** bad --width parse error
|
||||
$ hledger -f examples/sample.journal reg -w 80,-1
|
||||
hledger: could not parse width option: ParseErrorBundle {bundleErrors = TrivialError 3 (Just (Tokens ('-' :| ""))) (fromList [Label ('d' :| "igit")]) :| [], bundlePosState = PosState {pstateInput = "80,-1", pstateOffset = 0, pstateSourcePos = SourcePos {sourceName = "(unknown)", sourceLine = Pos 1, sourceColumn = Pos 1}, pstateTabWidth = Pos 8, pstateLinePrefix = ""}} (use -h to see usage)
|
||||
**** balance assertion error shows ugly transaction
|
||||
hledger: balance assertion error in "/Users/simon/notes/2018.journal" (line 4949, column 54):
|
||||
in transaction:
|
||||
Transaction {tindex = 976, tsourcepos = JournalSourcePos "/Users/simon/notes/2018.journal" (4948,4950), tdate = 2018-09-01, tdate2 = Nothing, tstatus = *, tcode = "5VN72122C99690620", tdescription = "add funds to paypal", tcomment = "for:, time:06:53:51, type:Bank Deposit to PP Account , status:Pending, balance:6.99, gross:6.99, fee:0.00\n", ttags = [("for",""),("time","06:53:51"),("type","Bank Deposit to PP Account"),("status","Pending"),("balance","6.99"),("gross","6.99"),("fee","0.00")], tpostings = [PostingPP {pdate="Nothing", pdate2="Nothing", pstatus="", paccount="assets:personal:online:paypal", pamount=Mixed [Amount {acommodity = "$", aquantity = 6.99, aprice = NoPrice, astyle = AmountStylePP "L False 2 Just '.' Nothing..", amultiplier = False}], pcomment="", ptype=RegularPosting, ptags=[], pbalanceassertion=Just (Amount {acommodity = "$", aquantity = 6.99, aprice = NoPrice, astyle = AmountStylePP "L False 2 Just '.' Nothing..", amultiplier = False},GenericSourcePos "/Users/simon/notes/2018.journal" 4949 54), ptransaction=Just "<txn>", porigin=Nothing},PostingPP {pdate="Nothing", pdate2="Nothing", pstatus="", paccount="assets:personal:bank:wf:checking", pamount=Mixed [Amount {acommodity = "$", aquantity = -6.99, aprice = NoPrice, astyle = AmountStylePP "L False 2 Just '.' Nothing..", amultiplier = False}], pcomment="", ptype=RegularPosting, ptags=[], pbalanceassertion=Nothing, ptransaction=Just "<txn>", porigin=Nothing}], tpreceding_comment_lines = ""}
|
||||
after posting:
|
||||
assets:personal:online:paypal $6.99
|
||||
balance assertion details:
|
||||
date: 2018/09/01
|
||||
account: assets:personal:online:paypal
|
||||
commodity: $
|
||||
calculated: $-93.01
|
||||
asserted: $6.99 (difference: +$100.00)
|
||||
**** color support like stack's (still a few things remaining)
|
||||
***** http://no-color.org/ color should not be added by default if the `NO_COLOR` environment variable is present.
|
||||
***** Existing global option `--color=WHEN` is now also available as a
|
||||
non-project-specific yaml configuration parameter `color:`.
|
||||
***** Adopt the standard proposed at http://no-color.org/, that color should
|
||||
not be
|
||||
added by default if the `NO_COLOR` environment variable is present.
|
||||
***** New command `stack ls stack-colors` lists the styles and the associated
|
||||
'ANSI'
|
||||
control character sequences that stack uses to color some of its output.
|
||||
See
|
||||
`stack ls stack-colors --help` for more information.
|
||||
***** New global option `--stack-colors=STYLES`, also available as a
|
||||
non-project-specific yaml configuration parameter, allows a stack user to
|
||||
redefine the default styles that stack uses to color some of its output.
|
||||
See
|
||||
`stack --help` for more information.
|
||||
***** British English spelling of 'color' (colour) accepted as an alias for
|
||||
`--color`, `--stack-colors`, `stack ls stack-colors` at the command line
|
||||
and
|
||||
for `color:` and `stack-colors:` in yaml configuration files.
|
||||
**** generate commands list more dynamically from command docs
|
||||
***** names, aliases, descriptions
|
||||
|
||||
**** inconsistent repeated options behaviour: -b 1/1 -b 2/1 should use the last date & be documented
|
||||
**** pass -- -h/--help through to tasty
|
||||
**** underquoted $ gives "empty list" error
|
||||
$ bal --budget ^sm:exp date:jan -M cur:\$ --tree
|
||||
Budget performance in 2019/01:
|
||||
|
||||
hledger: Prelude.maximum: empty list
|
||||
**** 1275 drop/depth error message followup
|
||||
Two commands:
|
||||
|
||||
$ hledger bal --drop '-999999999999999'
|
||||
$ hledger bal --drop='-999999999999999'
|
||||
|
||||
Current output:
|
||||
hledger: could not parse drop number: --depth=999999999999999 (use -h to see usage)
|
||||
hledger: argument to drop must lie in the range 0 to 9223372036854775807, but is -999999999999999 (use -h to see usage)
|
||||
|
||||
My proposal would look like:
|
||||
hledger: drop's argument '--depth=999999999999999' must be a positive integer less than 9223372036854775807
|
||||
hledger: drop's argument '-999999999999999' must be a positive integer less than 9223372036854775807
|
||||
|
||||
Variations:
|
||||
hledger: drop's argument '-999999999999999' must be a positive integer less than 2^63
|
||||
hledger: drop's argument '-999999999999999' must between 0 and 2^63
|
||||
hledger: drop's argument '-999999999999999' should be 0 <= N < 2^63
|
||||
**
|
||||
**** do recompile stack script addon if source is newer
|
||||
ie, change:
|
||||
$ hledger check-tag-files # compiles if there's no compiled version
|
||||
**** drop abbreviation uniqueness requirement ?
|
||||
**** get actions from https://medium.com/@jdxcode/12-factor-cli-apps-dd3c227a0e46
|
||||
**** group common options as in CliOptions.reportflags
|
||||
**** hledger: "date:monday-" gave a date parse error ()
|
||||
**** http://neilmitchell.blogspot.com/2020/07/automatic-uis-for-command-lines-with.html
|
||||
**** improve error message:
|
||||
hledger: balance assignments cannot be used with accounts which are
|
||||
posted to by transaction modifier rules (auto postings).
|
||||
Please write the posting amount explicitly, or remove the rule.
|
||||
**** red color is bad on powershell navy background
|
||||
```
|
||||
Guest72
|
||||
Hi, does anybody know how to change the negative value color in powershell. It's drakred and almost not readable on the dark blue background
|
||||
f-a
|
||||
not sure, but meanwhile using --color=never could help
|
||||
Guest72
|
||||
better than dark red ;)
|
||||
```
|
||||
**** show an extra newline after txt reports, for better display when showing one after another
|
||||
**** show name of reader responsible for a parse error
|
||||
**** ugly --alias parse error
|
||||
$ bal --alias a
|
||||
hledger: parse error at ParseErrorBundle {bundleErrors = TrivialError 1 (Just EndOfInput) (fromList [Tokens ('=' :| "")]) :| [], bundlePosState = PosState {pstateInput = "a", pstateOffset = 0, pstateSourcePos = SourcePos {sourceName = "--alias a", sourceLine = Pos 1, sourceColumn = Pos 1}, pstateTabWidth = Pos 8, pstateLinePrefix = ""}}
|
||||
**** ugly parse error from malformed --width argument
|
||||
ghci> :main areg sm.*foo -w 350,50,50
|
||||
Transactions in sm:assets:foo and subaccounts:
|
||||
2020-01-01 *** Exception: could not parse width option: ParseErrorBundle {bundleErrors = TrivialError 6 (Just (Tokens (',' :| ""))) (fromList [Label ('d' :| "igit"),EndOfInput]) :| [], bundlePosState = PosState {pstateInput = "350,50,50", pstateOffset = 0, pstateSourcePos = SourcePos {sourceName = "(unknown)", sourceLine = Pos 1, sourceColumn = Pos 1}, pstateTabWidth = Pos 8, pstateLinePrefix = ""}} (use -h to see usage)
|
||||
**** non-empty standard input activates -f- if there is no explicit -f ?
|
||||
**** --invert should be supported by all commands
|
||||
**** --positive flips signs of normally negative accounts (liabilities, revenues, equity)
|
||||
so eg both revenues and expenses sections of income statement are positive
|
||||
**** --pivot should work with all hledger tools (ui, web, api..)
|
||||
**** warn about missing command rather than "unknown flag"
|
||||
~$ hledger-0.27.1 -f src/hledger/data/sample.journal -D date:2008/01
|
||||
hledger-0.27.1: Unknown flag: -D
|
||||
**** balance assertion error improvements
|
||||
***** show assertions in transaction
|
||||
2016/04/01 * refill negative budget envelopes (personal)
|
||||
[assets:personal:bank:wf:checking:month:gifts] $69.56 = 0
|
||||
[assets:personal:bank:wf:checking:month:food] $97.58 = 0
|
||||
[assets:personal:bank:wf:checking:month:personal care] $80.00 = $1
|
||||
[assets:personal:bank:wf:checking:available] $-247.14
|
||||
***** show line/column number of assertion
|
||||
***** show indication inline
|
||||
2016/04/01 * refill negative budget envelopes (personal)
|
||||
[assets:personal:bank:wf:checking:month:gifts] $69.56 = 0
|
||||
[assets:personal:bank:wf:checking:month:food] $97.58 = 0 <- failed, calculated: $7.12 (difference: +$7.12)
|
||||
[assets:personal:bank:wf:checking:month:personal care] $80.00 = $1
|
||||
[assets:personal:bank:wf:checking:available] $-247.14
|
||||
**** consistent/more headings for options
|
||||
**** don't immediately convert auto-balancing amounts to the price's commodity
|
||||
***** discuss on #ledger
|
||||
***** example
|
||||
1/1
|
||||
a E4 @ $1
|
||||
b ; <- should fill in -E4 @ $1 instead of -$4
|
||||
**** ignore inapplicable common flags when harmless, eg --width
|
||||
**** --help, --info after +RTS and/or -- should be passed through
|
||||
**** --unreal opposite of --real
|
||||
**** --pivot cleanups
|
||||
https://github.com/simonmichael/hledger/pull/323#issuecomment-185631456
|
||||
***** add --pivot to add-on option lists
|
||||
***** move pivot example to its own section
|
||||
**** reports should indicate whether each item has hidden subitems (and possibly include them in the report)
|
||||
**** show abnormal-sign balances in red (rather than negative numbers)
|
||||
**** split up output formats by command
|
||||
**** html reports
|
||||
***** add html output to other reports
|
||||
****** register
|
||||
****** postings
|
||||
***** add --view to open browser ?
|
||||
***** add detailed mode or report generating register for each cell
|
||||
*** compat
|
||||
**** compat: support reading with beancount2ledger when in PATH
|
||||
**** compat: support reading with ledger2beancount & beancount2ledger when in PATH
|
||||
*** doc
|
||||
**** doc: quickstart: update download instructions, make maintainable
|
||||
**** CONTRIBUTING: a github API script to generate the open issues table with issue counts
|
||||
**** automate CREDITS updating
|
||||
***** ./Shake credits
|
||||
***** github commit links
|
||||
***** github issue links
|
||||
***** github images
|
||||
**** a nice HISTORY page (higher level view of commits)
|
||||
***** automate
|
||||
****** ./Shake history
|
||||
**** doc: house mortgage
|
||||
Chris Leyon, Ledger list 2021:
|
||||
|
||||
The entry for my house purchase looks like this:
|
||||
|
||||
2014-12-18 Buy house
|
||||
Assets:Fixed:House $445,000.00 ; Selling price of house
|
||||
Assets:Current:XYZ Bank:Checking $455.76
|
||||
Expenses:Interest:Mortgage Interest $390.60
|
||||
Expenses:Taxes:Property Tax $282.49 ; Current qtr taxes
|
||||
Expenses:Taxes:Property Tax $2,154.00 ; Next qtr taxes
|
||||
Expenses:Utilities:Sewer $18.45 ; Current qtr sewer
|
||||
Expenses:Utilities:Sewer $141.48 ; Next qtr sewer
|
||||
Expenses:House:Warranty $32.10
|
||||
Liabilities:Loans:Mortgage Principal $-427,750.00 ; PV of mortgage at t=0
|
||||
Assets:Current:XYZ Bank:Savings $-20,500.00 ; Down payment
|
||||
Assets:Current:AnAssetAccount $-5,001.37 ; More money down
|
||||
Assets:Current:Escrow $960.49
|
||||
Expenses:House:Settlement $440.00 ; Origination charges
|
||||
Expenses:House:Settlement $325.00 ; Appraisal fee
|
||||
Expenses:House:Settlement $75.00 ; Tax service
|
||||
Expenses:House:Settlement $50.00 ; Appraisal management
|
||||
Expenses:House:Settlement $2,301.00 ; Title services and lender's title insurance
|
||||
Expenses:House:Settlement $105.00 ; Owner's title insurance
|
||||
Expenses:House:Settlement $220.00 ; Government recording charge
|
||||
Expenses:House:Settlement $300.00 ; Survey
|
||||
|
||||
This establishes the "Liabilities:Loans:Mortgage Principal" account which tracks the loan balance. "Assets:Fixed:House" can be used to calculate your equity (as in home equity, not an equity account type). Various charges need to be paid at closing time: title fees, current and next quarter taxes, utility services, etc. It also categorizes "Expenses:Interest:Mortgage Interest" as a separate category from other types of interest, for tax purposes. Finally, it also seeds the "Assets:Current:Escrow" account which is the source account for paying all sorts of property tax and insurance expenses.
|
||||
|
||||
A monthly mortgage payment might look like this:
|
||||
|
||||
2015-03-23=2015-04-01 (1000) Loan Servicing Company
|
||||
Liabilities:Loans:Mortgage Principal $585.63
|
||||
Liabilities:Loans:Mortgage Principal $100.00 ; Pay a little extra principal every month
|
||||
Expenses:Interest:Mortgage Interest $909.08
|
||||
Assets:Current:Escrow $1,024.48
|
||||
Assets:Current:XYZ Bank:Checking $-2,619.19
|
||||
|
||||
This set up has tracked my mortgage payments and balances for several years, down to the penny.
|
||||
|
||||
**** hledger manual: toc: why are OUTPUT, PIVOTING not clickable ?
|
||||
*** entry
|
||||
**** entry command
|
||||
***** a convenient non-interactive version of hledger add; and an extension point for data entry validations/automations
|
||||
hledger entry [ONELINEENTRY]
|
||||
***** ONELINEENTRY is a single argument, in quotes: a journal entry using double-space instead of newlines
|
||||
hledger entry '2021-01-01 * (123) farmers market expenses:food $10 assets:checking ; date:1/3'
|
||||
***** or with no argument, each line from standard input generates a journal entry
|
||||
***** with -a|--add, appends to the journal, like add/import
|
||||
***** if entry does not begin with a date, uses today's date
|
||||
hledger entry 'farmers market expenses:food $10 assets:cash'
|
||||
***** if any other required parts are omitted, they are filled from similar past transactions, like add
|
||||
These will match the txn above, and make the postings shown:
|
||||
hledger entry 'farmers' # expenses:food $10, assets:cash -$10
|
||||
hledger entry 'farmers expenses:food $11' # expenses:food $11, assets:cash -$11
|
||||
hledger entry 'farmers $11' # same
|
||||
hledger entry 'farmers 11' # same
|
||||
hledger entry 'farmers expenses:food 6 expenses:snacks 5' # expenses:food $6, expenses:snacks $5, assets:cash -$11
|
||||
***** leaf names of known accounts will be expanded
|
||||
hledger entry 'farmers food 6 snacks 5' # same
|
||||
***** missing commodity symbol could also be inferred from source account's balance
|
||||
***** or with a flag, missing required parts will give an error
|
||||
****** --complete, --only, --standalone, --no-infer, --no-past, --no-journal
|
||||
***** entry can run validation checks, including fancy ones like "asset accounts may not go negative"
|
||||
*** ops
|
||||
**** new hledger.org vps
|
||||
*** pkg
|
||||
**** need build-tools section in our package.yaml files to avoid build errors with happy etc. ?
|
||||
cf https://github.com/haskell/cabal/issues/5867#issuecomment-967280170
|
||||
*** process
|
||||
**** refine RELEASING doc/process
|
||||
**** automate changelog finalisation
|
||||
**** automate release note generation
|
||||
****
|
||||
*** reports
|
||||
**** reports: allow -c '0.%' to set style of -%
|
||||
**** reports: relax the "whole subperiods" rule
|
||||
***** when there's only one ?
|
||||
bal -YH -e tomorrow would be titled with tomorrow's date instead of 12-31
|
||||
***** when there's multiple, but no transactions before the begin date or after the end date ?
|
||||
*** timeclock
|
||||
**** timeclock: improve error message
|
||||
hledger: clock-out time less than clock-in time in:
|
||||
2021-09-17 * 12:00-06:00
|
||||
(no-electronics) -6.00h
|
||||
|
||||
**** timeclock: ugly parse error
|
||||
hledger: line 6: expected timeclock code o but got i
|
||||
CallStack (from HasCallStack):
|
||||
error, called at ./Hledger/Data/Timeclock.hs:85:32 in hledger-lib-1.22.99-HCWXy7WanhBI3o1AfvBpXy:Hledger.Data.Timeclock
|
||||
*** timedot
|
||||
**** timedot: more flexible parsing
|
||||
***** ignore all preamble lines (before first date line)
|
||||
***** ignore all amountless lines
|
||||
***** ignore org list bullets/checkboxes
|
||||
***** check timedotstrict: disables ignoring preamble/amountless lines
|
||||
**** timedot: --alias doesn't work with timeclock, timedot ?
|
||||
@ -15,7 +15,7 @@ This installs haskell dependencies (but not system dependencies) and rebuilds as
|
||||
then runs [hledger/bench/bench.hs](https://github.com/simonmichael/hledger/blob/master/hledger/bench/bench.hs),
|
||||
which by default shows quick elapsed-time measurements for several operations on a standard data file:
|
||||
|
||||
```cli
|
||||
```shell
|
||||
$ stack bench hledger
|
||||
NOTE: the bench command is functionally equivalent to 'build --bench'
|
||||
...
|
||||
@ -35,7 +35,7 @@ Benchmark bench: FINISH
|
||||
bench.hs has some other modes, which you can use by compiling and running it directly.
|
||||
`--criterion` reports more detailed and dependable measurements, but takes longer:
|
||||
|
||||
```cli
|
||||
```shell
|
||||
$ cd hledger; stack exec -- ghc -ibench bench/bench && bench/bench --criterion
|
||||
...
|
||||
Linking bench/bench ...
|
||||
@ -80,7 +80,7 @@ variance introduced by outliers: 16% (moderately inflated)
|
||||
It can also show the results for multiple h/ledger executables side by side, if you tweak the bench.hs code.
|
||||
Unlike the other modes, it does not link with the hledger code directly, but runs the "hledger" executable found in $PATH (so ensure that's the one you intend to test).
|
||||
|
||||
```cli
|
||||
```shell
|
||||
$ cd hledger; stack exec -- ghc -ibench bench/bench && bench/bench --simplebench
|
||||
Benchmarking /Users/simon/.local/bin/hledger in /Users/simon/src/hledger/hledger with simplebench and shell
|
||||
Using bench/default.bench
|
||||
@ -107,12 +107,12 @@ simplebench.hs is a generic benchmarker of one or more executables (specified on
|
||||
It has a better command-line interface than bench.hs, so you may find it more convenient
|
||||
for comparing multiple hledger versions, or hledger and ledger. Eg:
|
||||
|
||||
```cli
|
||||
```shell
|
||||
$ stack exec -- ghc tools/simplebench
|
||||
[1 of 1] Compiling Main ( tools/simplebench.hs, tools/simplebench.o )
|
||||
Linking tools/simplebench ...
|
||||
```
|
||||
```cli
|
||||
```shell
|
||||
$ tools/simplebench -h
|
||||
tools/simplebench -h
|
||||
simplebench: at least one executable needed
|
||||
@ -133,7 +133,7 @@ Tips:
|
||||
- tests can be commented out with #
|
||||
- results are saved in benchresults.{html,txt}
|
||||
```
|
||||
```cli
|
||||
```shell
|
||||
cd hledger; $ ../tools/simplebench -f bench/default.bench hledger ledger
|
||||
Using bench/default.bench
|
||||
Running 4 tests 2 times with 2 executables at 2015-08-24 04:24:37.257068 UTC:
|
||||
@ -5,19 +5,22 @@
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
See also RELEASING.md.
|
||||
|
||||
## Update master changelogs often
|
||||
Before release, and preferably daily/weekly as well:
|
||||
- during normal development, do this only in master branch
|
||||
- during release preparation.. unclear; keep the other branch's changelog in mind, they need to be synced at some point. Prioritise \[minor] release branch's changelog ?
|
||||
- always first update changelogs in master branch, not in release branches
|
||||
- `./Shake changelogs`
|
||||
- edit the new changelog items
|
||||
- open the five changelogs
|
||||
- in emacs: `C-x d */CHANGES.md`, `(`, split into 5 columns, open each one, narrow from last release heading to top
|
||||
- in each changelog
|
||||
- paste section headings from top comment if needed
|
||||
- process new items, from top-most section heading upward
|
||||
- open changelogs
|
||||
- as VSC panes:
|
||||
- explorer
|
||||
- unfold hledger, hledger-lib, hledger-ui, hledger-web directories
|
||||
- filter list to CHANGES
|
||||
- click project CHANGES (last one in list)
|
||||
- click editor pane, split it, click rightmost editor pane
|
||||
- click hledger CHANGES
|
||||
- click rightmost editor pane, split it, ... etc.
|
||||
- in each changelog (first ui & web; then project, cli, lib)
|
||||
- process new items (starting above top-most section heading, working upward)
|
||||
- drop boring items (changes not visible to end/API users, followups to other new items, minor doc updates..)
|
||||
- drop duplicated items/content (mostly between cli and lib)
|
||||
- move to top of appropriate changelog & section (create section when needed; consider a second pane to reduce scrolling)
|
||||
@ -50,7 +53,8 @@ Before release, after cherry-picking changes from master to the release branch:
|
||||
|
||||
## Old notes
|
||||
|
||||
Changelogs started using markdown from 1.0 onward. Should make consistent.
|
||||
Changelogs are plain text, but started including some markdown formatting
|
||||
from 1.0. Should make consistent.
|
||||
|
||||
Changelogs started mentioning committer names from 2017/1,
|
||||
for hledger-ui-1.1.1 (because they won't appear on the release notes).
|
||||
2
CHANGES
2
CHANGES
@ -1,2 +0,0 @@
|
||||
General project changes are in doc/CHANGES.md.
|
||||
Package-specific changes are in hledger*/CHANGES.md.
|
||||
@ -5,630 +5,10 @@
|
||||
| |_) | | | (_) | | __/ (__| |_
|
||||
| .__/|_| \___// |\___|\___|\__|
|
||||
|_| |__/
|
||||
|
||||
Doc updates
|
||||
|
||||
Website
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
-->
|
||||
|
||||
General changes in the hledger project.
|
||||
For package-specific changes, see the hledger package changelogs.
|
||||
|
||||
|
||||
# 1.51.2 2026-01-08
|
||||
|
||||
# 1.51.1 2025-12-08
|
||||
|
||||
# 1.51 2025-12-05
|
||||
|
||||
Docs updated
|
||||
|
||||
- ACHIEVEMENTS
|
||||
- ANNOUNCE.short
|
||||
- AUTHORS
|
||||
- bin/README
|
||||
- CHANGES.md: move to doc/ for consistent paths
|
||||
- Contributing: mention translation (Lý Minh Nhật)
|
||||
- DECISIONS
|
||||
- dev
|
||||
- DOCS: document & diagram latest doc update procedures
|
||||
- ISSUES
|
||||
- REGRESSIONS
|
||||
- RELEASING
|
||||
- relnotes: more reliable changelog links
|
||||
- ROADMAP
|
||||
- tldr/README
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
- bump stack snapshots
|
||||
- Dockerfile fixed (probably)
|
||||
- drop the hledger-install script
|
||||
- just changelogs* update
|
||||
- just docupdatediag
|
||||
- just ghci-ui: :main (and :rmain) now works again
|
||||
- just ghnightly* -> nightly*
|
||||
- just oldest
|
||||
- just perftest: run performance tests, logged to perf.log
|
||||
- just releasediag update
|
||||
- just rels-major
|
||||
- just site-restart
|
||||
- just: devtag-push: simplify
|
||||
- just: ghrel-bin-upload
|
||||
- just: manuals, manuals-site
|
||||
- just: reltags: cleanup
|
||||
- just: ver, majorver
|
||||
- Justfile: less safari dependence
|
||||
- Justfile reorg, cleanups
|
||||
- release script updates
|
||||
- Shake: drop mandates target, update manual dates automatically
|
||||
- Shake manuals: more contributor instructions in the header comment [hledger_site#140]
|
||||
- stack92: add valid hashtables version
|
||||
- stack94: add valid hashtables version
|
||||
- stack96: add valid hashtables version
|
||||
- stack98: include valid hashtables version
|
||||
- stack98: restore needed encoding 0.10 extra dep
|
||||
- stop git ignoring site/src/, allowing web docs to be easily opened in vscode
|
||||
- tools/relnotes.hs update
|
||||
- use a nightly branch instead of a nightly tag on github, it's simpler
|
||||
- workflows: use shelltestrunner 1.11
|
||||
- workflows:binaries-mac-x64: switch to macos-15-intel
|
||||
|
||||
|
||||
# 1.50.5 2025-12-08
|
||||
|
||||
# 1.50.4 2025-12-04
|
||||
|
||||
# 1.50.3 2025-11-18
|
||||
|
||||
# 1.50.2 2025-09-26
|
||||
|
||||
# 1.50.1 2025-09-16
|
||||
|
||||
# 1.50 2025-09-03
|
||||
|
||||
Doc updates
|
||||
|
||||
- FINANCE
|
||||
- ISSUES
|
||||
- REGRESSIONS
|
||||
- RELEASING
|
||||
- SCHEDULE & `just schedule` script
|
||||
|
||||
Website
|
||||
|
||||
- fix the "edit this page" link
|
||||
- redirects: handle more old pages; fix some old redirects to #FMT-format; stop redirecting /timeclock, /timedot, /timedot.html
|
||||
- set up a github issue template clarifying this repo's scope
|
||||
- shortcut urls: release.hledger.org, nightly.hledger.org, regressions.hledger.org; readyprs.hledger.org excludes PRs with needs-* labels
|
||||
- sidebar: reorganise
|
||||
- sidebar: leave all links visible to avoid popping
|
||||
- sidebar: avoid duplicate links, they're no longer allowed
|
||||
- sidebar: link to the current release's manuals, not the dev version's
|
||||
- Beancount: edits, new conversion tips
|
||||
- Docs: consolidate all user docs onto a single Docs page
|
||||
- Editors: more vs code extensions, more emacs calc notes
|
||||
- Export: updates
|
||||
- FAQ: updates
|
||||
- Hledger By Example: start a new progressive "book", with 18 pages
|
||||
- Home: new, shorter home page content
|
||||
- Home: show a quote/testimonial, updating on the hour
|
||||
- Investments: fix link (#2436)
|
||||
- Invoicing: fix kairos link
|
||||
- Ledger: edits
|
||||
- Tutorial: hledger basics -> to Tutorial: hledger add
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
- hledger now requires at least GHC 9.6 (and base 4.18), to ease maintenance.
|
||||
- bump default build, tools to lts 24.8 / ghc 9.10.2
|
||||
- docker: sync Docker GHC version with Stack configuration, update dependencies, and replace deprecated Dockerfile syntax. (Lukas Fleischer)
|
||||
- github workflows improvements
|
||||
- tool updates: checkembeddedfiles, devtag, nightly-push, nightlytag, relver, test
|
||||
- update github issue templates
|
||||
|
||||
|
||||
# 1.43.2 2025-06-13
|
||||
|
||||
|
||||
# 1.43.1 2025-06-04
|
||||
|
||||
- tools:
|
||||
- Shake changelogs: fix missing blank lines around old heading
|
||||
- ghcruns-download: make tmp dir
|
||||
- docs:
|
||||
RELEASING
|
||||
|
||||
|
||||
# 1.43 2025-06-01
|
||||
|
||||
Docs
|
||||
|
||||
- Updated:
|
||||
FILES,
|
||||
FINANCE,
|
||||
ISSUES,
|
||||
PULLREQUESTS,
|
||||
REGRESSIONS,
|
||||
RELEASING,
|
||||
ghrelnotes,
|
||||
relnotes
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
- issue labels updates, `severity*` -> `annoyance*`, `impact*` -> `affects*`
|
||||
- new shortcut urls: assignedprs.hledger.org, unassignedprs.hledger.org
|
||||
- clean up LICENSE files, main module licensing headers, add AUTHORS.md, try to fix github license detection
|
||||
- cabal files now specify GPLv3+ exactly. [#2359]
|
||||
- building the hledger packages now requires at least Cabal 2.2+ or stack built with Cabal 2.2+ (was 1.12+).
|
||||
- avoid a ghci warning if :rmain is defined in user's config.
|
||||
- simplify stack yaml file names
|
||||
- workflows updates:
|
||||
- binaries\*: simplify, cleanup
|
||||
- binaries-linux-x64: install ghcup only if not cached; fix cache
|
||||
- windows: use preinstalled stack
|
||||
- docker: draft of a docker image build/publish workflow (Doug Goldstein, [#2002])
|
||||
- nightly: adds latest binaries to the "nightly" release
|
||||
- tools updated:
|
||||
binaries,
|
||||
devtag-push,
|
||||
ghnightly,
|
||||
ghnightly-bin,
|
||||
ghnightlynotes-push,
|
||||
ghrel,
|
||||
ghrelease-upload,
|
||||
ghrelnotes-push,
|
||||
ghrun,
|
||||
ghrun-id,
|
||||
ghrun-open,
|
||||
ghruns,
|
||||
ghruns-download,
|
||||
ghruns-open,
|
||||
hackageupload,
|
||||
nightly,
|
||||
nightlybin,
|
||||
nightlytag
|
||||
|
||||
|
||||
# 1.42.2 2025-05-16
|
||||
|
||||
Docs
|
||||
|
||||
- relnotes: fix links to hackage changelogs
|
||||
|
||||
|
||||
# 1.42.1 2025-03-12
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
- Tools updates
|
||||
|
||||
- Fix cabalfilestest: test all cabal files before any hackage upload.
|
||||
|
||||
|
||||
# 1.42 2025-03-07
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
- Unix bindists in github releases now include the man pages and info manuals. [#2309]
|
||||
|
||||
- Unix bindists in github releases are now normal .tar.gz files, without the extra zip compression. [#2299]
|
||||
|
||||
- Release notes and install instructions in github releases are now collapsed by default again.
|
||||
This makes the sequence of dates and releases clearer.
|
||||
Github automatically expands the assets of the latest release, so those will be visible by default.
|
||||
For a full text search of all release notes, use the https://hledger.org/relnotes.html page.
|
||||
|
||||
- hledger-install: if installing third party packages fails, it now tries again with bounds relaxed.
|
||||
This makes hledger-iadd and hledger-interest more likely to install successfully,
|
||||
even if their bounds have not yet been updated for a new hledger release.
|
||||
|
||||
- just functest now fails if there are warnings.
|
||||
(It does not force recompilation of already compiled modules,
|
||||
but even so this should help catch more warnings before pushing them to CI.)
|
||||
|
||||
- new/changed recipes/tools:
|
||||
bench*.sh,
|
||||
changelogs-catchup,
|
||||
changelogs-finalise,
|
||||
changelogs-reset,
|
||||
devtag,
|
||||
ghrelnotes,
|
||||
ghrelnotes-publish,
|
||||
log-headtail,
|
||||
log-push,
|
||||
log-save,
|
||||
modulediag,
|
||||
modulediags,
|
||||
modulediags-view,
|
||||
packagediags,
|
||||
packagediags-view,
|
||||
releasediag,
|
||||
relnotes
|
||||
relprep -> relbranch,
|
||||
reltags,
|
||||
reltags-push,
|
||||
showrelnotes,
|
||||
site-manuals-snapshot,
|
||||
site-watch,
|
||||
time,
|
||||
tldr-diff
|
||||
|
||||
- gitignore cleanups.
|
||||
|
||||
|
||||
# 1.41 2024-12-09
|
||||
|
||||
Docs
|
||||
|
||||
- REGRESSIONS: new table format; updates.
|
||||
- CODE: notes on the use of haddock [#2222]
|
||||
- Simplify github bug report template
|
||||
- Add man pages and info manuals to the release bindists on github
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- Fixed build errors in all bin/ scripts. (Dmitry Astapov)
|
||||
- hledger-install: fix installation of hledger-ui
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
- GHC 9.10 is now the default for dev builds and most github workflows.
|
||||
- Add consistent greppable summaries to all workflows; various other improvements
|
||||
- Add bash shell completion script to the release bindists ([#2223], gesh/hseg, Simon Michael)
|
||||
- tools/gtree: -u shows untracked files, -I adds ignored files.
|
||||
- just doctest: pass through doctest arg(s).
|
||||
|
||||
|
||||
# 1.40 2024-09-09
|
||||
|
||||
Docs
|
||||
|
||||
- In the hledger 1.29 release notes, Date adjustments has had some corrections.
|
||||
- Github release notes template cleanups; fix mac, linux install commands.
|
||||
- README: fixed contributors link.
|
||||
- RELEASING: updates
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- hledger-install: cleanups, bump versions, perhaps fix hledger-interest install
|
||||
- hledger-install: clarify some stack/cabal setup messages
|
||||
|
||||
Infrastructure/Misc
|
||||
|
||||
- Shake.hs: fix partial warnings
|
||||
- Shake cmdhelp: renamed to cmddocs, and it now also updates the options
|
||||
listed in the manuals, and shows progress output. It should be run (at
|
||||
some point) after changing commands' docs or options.
|
||||
- Shake txtmanuals: silence all but wide table warnings
|
||||
- just file cleanups; update to support just 1.28+
|
||||
- just twih: date fixes
|
||||
- just ghci: -fobject-code was a mistake, keep everything interpreted
|
||||
- just functest: try again to reduce rebuilding/slowdowns when testing
|
||||
- just installrel: update for .tar.gz
|
||||
- ci scripts: cleanup, fix a macos-ism
|
||||
|
||||
|
||||
# 1.34 2024-06-01
|
||||
|
||||
Docs
|
||||
|
||||
- move release notes from the hledger_site repo to the main hledger repo
|
||||
- github release notes: show the release notes, hide the install instructions by default
|
||||
- github release notes: improve windows install commands
|
||||
- github release notes: start mentioning github usernames, enabling the Contributors avatar list
|
||||
- dev docs: new Developer FAQ, Contributor Quick Start updates
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- `hledger-install.sh` now uses stackage nightly, and a failure on non-Windows platforms has been fixed.
|
||||
|
||||
Infrastructure/misc
|
||||
|
||||
- A new `release` workflow creates github releases, uploads release binaries and generates release notes.
|
||||
- There is a new `oldest` workflow for testing the oldest GHC we support (currently 8.10.7).
|
||||
- The `binaries-mac-x64` workflow has been bumped from GHC 9.4 to 9.8.
|
||||
- The master branch's `ci` workflow has been updated to Ubuntu 24.04
|
||||
and uses the preinstalled GHC & stack, saving some work.
|
||||
- `md-issue-refs` helps generate markdown issue links.
|
||||
- `relnotes.hs` helps generate release notes from changelogs.
|
||||
- The project `Makefile` has now been fully replaced by `Justfile`.
|
||||
|
||||
|
||||
# 1.33 2024-04-18
|
||||
|
||||
Misc
|
||||
|
||||
- Apple ARM binaries are now included in github releases.
|
||||
|
||||
Docs
|
||||
|
||||
- REGRESSIONS: we now split the bounty between finder and fixer
|
||||
- move Developer docs, MOCKUPS, investment-accounting-features to main repo
|
||||
- merge LINKS into dev docs page; cleanup
|
||||
- drop unused BACKLOG, TODO pages
|
||||
|
||||
|
||||
# 1.32.3 2024-01-28
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- bin/hledger-bar: Fix an error when NO_COLOR is not defined;
|
||||
allow color when NO_COLOR is defined but empty, per no-color spec;
|
||||
and fix shellcheck warnings.
|
||||
[#2159] (Colin Dean, Simon Michael)
|
||||
|
||||
- bin/hledger-simplebal: Fix shellcheck warnings. (Colin Dean)
|
||||
|
||||
[#2159]: https://github.com/simonmichael/hledger/issues/2159
|
||||
|
||||
# 1.32.2 2023-12-31
|
||||
|
||||
Docs
|
||||
|
||||
- Added:
|
||||
|
||||
- Updated: ISSUES.md, REGRESSIONS.md
|
||||
|
||||
- WORKFLOWS.md is renamed to DEVWORKFLOWS.md to avoid a name clash.
|
||||
|
||||
Examples
|
||||
|
||||
- New CSV rules examples for Wise, ING, Venmo, PayPal, FHB, N26, Triodos (Ilja Kocken)
|
||||
|
||||
Scripts/addons
|
||||
|
||||
Infrastructure
|
||||
|
||||
- Project scripts in `Makefile` and `bake` have been converted to a `Justfile`.
|
||||
After many years using `make` and shell for scripting, I find `just`
|
||||
better enough, and the goal of clean consolidated efficient project
|
||||
automation so valuable, that we will use it in the hledger project
|
||||
even though it usually is not installed by default.
|
||||
|
||||
- The `.mailmap` file has been updated to clean up committer info in git output.
|
||||
|
||||
- `tools/generatejournal` can now be run as a script.
|
||||
|
||||
- The "new issue" and "new PR" templates have had some cleanup.
|
||||
|
||||
- There are some new issue tracker labels intended for use with a new
|
||||
ISSUES.md > Prioritising scheme, and a few issues using them.
|
||||
|
||||
# 1.32 2023-12-01
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- hledger-install.sh: replaced hledger-stockquotes with pricehist
|
||||
|
||||
- added gsheet-csv.hs: fetch a google sheet as CSV
|
||||
|
||||
- added hledger-report1: an example custom compound report, with haskell and bash versions
|
||||
|
||||
- justfile: updated import, time report scripts
|
||||
|
||||
|
||||
Examples
|
||||
|
||||
- New:
|
||||
|
||||
- Fidelity CSV rules
|
||||
|
||||
- Updated:
|
||||
|
||||
- roi-unrealised.ledger (Charlie Ambrose)
|
||||
|
||||
Docs
|
||||
|
||||
- New:
|
||||
|
||||
- Started a weekly This Week In Hledger news post, inspired by Matrix.
|
||||
- There's now a News page, for This Week In Hledger etc.
|
||||
- hledgermatic, an up-to-date, simple journal-first workflow
|
||||
- How to record journal entries: added
|
||||
- Reporting version control stats: added
|
||||
- Moved regression bounty info from the issue tracker to Developer docs > REGRESSIONS.
|
||||
|
||||
- Updated:
|
||||
|
||||
- Checking for errors
|
||||
- Common workflows
|
||||
- Ledger
|
||||
- Simon's old setup
|
||||
- Videos
|
||||
- All docs now use the `cli` class instead of `shell` for command-line examples,
|
||||
avoiding inaccurate highlighting.
|
||||
|
||||
|
||||
Infrastructure
|
||||
|
||||
- hledger.org website:
|
||||
|
||||
- Fixed the webhook that was not updating the site on git push.
|
||||
|
||||
- Fixed a problem with cloudflare authentication that was preventing
|
||||
automatic TLS certificate renewal on hledger.org.
|
||||
|
||||
- Updated and committed hledger.org's caddy config and short urls (redirects)
|
||||
|
||||
- Enabled https for code.hledger.org and site.hledger.org short urls.
|
||||
|
||||
- Updated the stars.hledger.org redirect
|
||||
(we have reached the top 30 github-starred Haskell projects 🌟 🎉).
|
||||
|
||||
- Set up a self-hosted Sandstorm server, and a public hledger-web
|
||||
instance (sandbox.hledger.org) in it that is fully writable (until
|
||||
spammers find it). Use it as a pastebin for examples, eg.
|
||||
|
||||
- Github CI (continuous integration) workflows have been optimised somewhat:
|
||||
|
||||
- Scheduled weekly builds have been disabled, as they were propagating
|
||||
to forks and running wastefully there in some cases.
|
||||
|
||||
- Some repeated rebuilding of the hledger-lib and hledger packages
|
||||
that seems unnecessary has been stopped.
|
||||
|
||||
- hledger-ui no longer builds its modules twice.
|
||||
|
||||
- Haddock testing now done only at release time.
|
||||
|
||||
- renamed main CI workflow and branch to "ci"
|
||||
|
||||
- Tools:
|
||||
|
||||
- .ghci: added an :rmain alias, which is like :main but reloads first -
|
||||
saves typing, and is useful eg when changing --debug level.
|
||||
|
||||
- make haddock-watch is now fast
|
||||
|
||||
|
||||
Finance
|
||||
|
||||
- Updated project finance scripts, regenerated the journal with consistent precisions.
|
||||
|
||||
- Updated reports with the last few months of data from Open Collective.
|
||||
|
||||
|
||||
# 1.31 2023-09-03
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- ft, tt shell scripts for collecting financial and time reports
|
||||
|
||||
- A justfile implementation of ft and tt
|
||||
|
||||
Examples
|
||||
|
||||
- self-tracking
|
||||
|
||||
- RPG ledger (Eric Mertens)
|
||||
|
||||
Docs
|
||||
|
||||
Infrastructure
|
||||
|
||||
- tools, CI: checkembeddedfiles, checkversions
|
||||
|
||||
- Shake: avoid making empty commits
|
||||
|
||||
- make functest-PAT: runs a subset of functional tests
|
||||
|
||||
- Provide a ghc-tags.yaml file to make use of ghc-tags with Hledger easy.
|
||||
|
||||
ghc-tags is a standalone tool to replace the formerly-built-in
|
||||
":ctags" feature (and I presume ":etags") in GHCi. These walked over
|
||||
the source and produced a TAGS file (in vim-compatible ctags or
|
||||
Emacs-compatible etags format) that allows the relevant editors to
|
||||
quickly navigate around function definitions.
|
||||
|
||||
ghc-tags trips over some of the CPP used in Hledger. The solution
|
||||
is to provide ghc-tags with explicit CPP defines via a YAML file.
|
||||
However, if a YAML file is provided, one also must specify the source
|
||||
paths, as the tool XORs config file | paths-on-command-line.
|
||||
|
||||
See <https://github.com/arybczak/ghc-tags/issues/6> for more
|
||||
information.
|
||||
(Jonathan Dowland)
|
||||
|
||||
# 1.30 2023-06-01
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- hledger-bar: new script for making simple bar charts in the terminal
|
||||
|
||||
- hledger-install: also list cabal, stack, pip tool versions
|
||||
|
||||
Examples
|
||||
|
||||
- examples/csv: added a more up-to-date CSV makefile
|
||||
|
||||
- examples/i18: Added sample top level account and type declarations in several languages
|
||||
|
||||
Docs
|
||||
|
||||
- A shorter, more example-heavy home page on the website.
|
||||
|
||||
- Simplified website and FAQ structure.
|
||||
|
||||
# 1.29.2 2023-04-07
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- hledger-install: re-enable hledger-interest, hledger-iadd; add hledger-lots
|
||||
|
||||
# 1.29.1 2023-03-16
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- hledger-install: slight output cleanups
|
||||
|
||||
Docs
|
||||
|
||||
Infrastructure
|
||||
|
||||
- RELEASING: new release process diagram
|
||||
- update hie.yaml so HLS uses GHC 9.4
|
||||
|
||||
# 1.29 2023-03-11
|
||||
|
||||
Scripts/addons
|
||||
|
||||
- hledger-script-example.hs: rename/cleanup
|
||||
- sortandmergepostings: new, sorts postings and merges duplicates (Caleb Maclennan, Murukesh Mohanan)
|
||||
- hledger-register-max: new, prints the posting with largest historical balance
|
||||
- hledger-git: record shows better error output, no longer force-adds ignored files
|
||||
- hledger-git: status is fixed, also shows diffs
|
||||
- hledger-git: add short command aliases r, s, l
|
||||
- hledger-git: -h is fixed
|
||||
- hledger-git: pass unrecognised commands to git
|
||||
- hledger-install: also install hledger-edit, hledger-plot
|
||||
- hledger-install: add support for installing python packages
|
||||
- hledger-install: show quieter stack/cabal output
|
||||
- hledger-install: align install status list
|
||||
- hledger-install: don't list hledger-install.sh in PATH
|
||||
- hledger-install: drop hledger-iadd for now https://github.com/hpdeifel/hledger-iadd/issues/71
|
||||
|
||||
Docs
|
||||
|
||||
- move most dev docs to doc/
|
||||
- Scripting hledger: move plugin types table here
|
||||
- Scripts: add hledger-plot, hledger-edit, hledger-fifo (Yann Büchau, Simon Michael)
|
||||
- update lots mockups, move to Mockups page
|
||||
- split Contributor Guide into Contributor Quick Start, LINKS, ISSUES
|
||||
- add REPOS, FILES, DECISIONS
|
||||
- CREDITS: updates, link to github contributors list
|
||||
|
||||
Infrastructure
|
||||
|
||||
- pr template: mention COMMITS page and prefix convention (#1997)
|
||||
- make ghc 9.4 and current stackage nightly the default for dev builds
|
||||
- require megaparsec 9.3+ in dev builds, for its useful dbg tool
|
||||
- make site-watch: fix runaway recursion, be more verbose
|
||||
- new make rules: man-watch
|
||||
- new tools: ciwatch, push, pushdocs, gtree
|
||||
- misc process updates
|
||||
|
||||
# 1.28 2022-12-01
|
||||
|
||||
Docs
|
||||
|
||||
- Miscellaneous improvements.
|
||||
|
||||
Examples
|
||||
|
||||
- Indian National Pension Service CSV rules (Pranesh Prakash)
|
||||
|
||||
Infrastructure
|
||||
|
||||
- make site-watch: switch from entr to watchexec.
|
||||
|
||||
- make hoogle-setup, hoogle-serve: run a local hoogle on hledger code.
|
||||
|
||||
- make man-watch-PROG: watch a hledger program's man page as source files change.
|
||||
|
||||
# 1.27 2022-09-01
|
||||
|
||||
Docs
|
||||
@ -8,7 +8,7 @@
|
||||
hledger is a suite of applications, tools and libraries.
|
||||
The main hledger code repository is [github.com/simonmichael/hledger](https://github.com/simonmichael/hledger)
|
||||
(shortcut url `code.hledger.org`).
|
||||
There are also various hledger add-ons maintained as separate projects with their own repos.
|
||||
There are also various hledger addons maintained as separate projects with their own repos.
|
||||
|
||||
## hledger packages
|
||||
|
||||
@ -100,7 +100,7 @@ Try tracing the execution of a hledger command:
|
||||
1. [Hledger.Cli.Main:main](https://github.com/simonmichael/hledger/blob/master/hledger/Hledger/Cli/Main.hs#L302)
|
||||
parses the command line to select a command, then
|
||||
2. gives it to
|
||||
[Hledger.Cli.Utils:withJournal](https://github.com/simonmichael/hledger/blob/master/hledger/Hledger/Cli/Utils.hs#L73),
|
||||
[Hledger.Cli.Utils:withJournalDo](https://github.com/simonmichael/hledger/blob/master/hledger/Hledger/Cli/Utils.hs#L73),
|
||||
which runs it after doing all the initial parsing.
|
||||
3. Parsing code is under
|
||||
[hledger-lib:Hledger.Read](https://github.com/simonmichael/hledger/tree/master/hledger-lib/Hledger/Read.hs),
|
||||
@ -166,7 +166,7 @@ Here are some ways to run it during development:
|
||||
|
||||
- `yesod devel`: runs in developer mode, rebuilds automatically when config, template, static or haskell files change
|
||||
(but only files in the hledger-web package):
|
||||
```cli
|
||||
```shell
|
||||
$ (cd hledger-web; yesod devel)
|
||||
```
|
||||
|
||||
@ -176,16 +176,16 @@ $ (cd hledger-web; yesod devel)
|
||||
- `stack ghci`: runs the server in developer mode from GHCI.
|
||||
Changes to static files like hledger.js will be visible on page reload;
|
||||
to see other changes, restart it as shown.
|
||||
```cli
|
||||
```shell
|
||||
$ (cd hledger-web; stack ghci hledger-web)
|
||||
hledger-web> :main --serve # restart: ctrl-c, :r, enter, ctrl-p, ctrl-p, enter
|
||||
```
|
||||
|
||||
- `just ghci-web`: runs the server in developer mode from GHCI, also
|
||||
- `make ghci-web`: runs the server in developer mode from GHCI, also
|
||||
interprets the hledger-lib and hledger packages so that :reload picks
|
||||
up changes in those packages too:
|
||||
```cli
|
||||
$ just ghci-web
|
||||
```shell
|
||||
$ make ghci-web
|
||||
ghci> :main --serve
|
||||
```
|
||||
(This rule also creates symbolic links to hledger-web's `config`, `messages`, `static` and `templates`
|
||||
@ -195,12 +195,12 @@ directories, needed in developer mode, so it can run from the top directory. Thi
|
||||
|
||||
Relevant tools include:
|
||||
|
||||
- unit tests
|
||||
- functional tests
|
||||
- performance tests
|
||||
- documentation tests
|
||||
- unit tests (HUnit, make unittest)
|
||||
- functional tests (shelltestrunner, make functest)
|
||||
- performance tests (simplebench, make bench)
|
||||
- documentation tests (make haddocktest + manual)
|
||||
- ui tests (manual)
|
||||
- installation tests
|
||||
- installation tests (manual)
|
||||
- code reviews
|
||||
|
||||
## Code review
|
||||
@ -214,51 +214,3 @@ Relevant tools include:
|
||||
[log](https://ircbrowse.net/day/hledger/2015/10/11) -->
|
||||
|
||||
|
||||
## Code docs
|
||||
|
||||
Haddock comments are the standard way of attaching docs (and sometimes small tests)
|
||||
to a haskell definition. They are used pervasively in the hledger codebase.
|
||||
|
||||
From [#2222](https://github.com/simonmichael/hledger/pull/2222):
|
||||
|
||||
I tend to add a line of english description to most things.
|
||||
They can be a big help to someone else debugging/improving code later.
|
||||
|
||||
> *I use Haddock but I do not like to tell obvious things in Haddock comments.
|
||||
> (And if there are surprising things I try to eliminate the surprises instead.)*
|
||||
|
||||
I hear you! This is of course a recurring debate among programmers.
|
||||
|
||||
I agree that obviously redundant haddocks that add no value are to be avoided.
|
||||
|
||||
In the hledger codebase, there's no hard requirement for haddocks.
|
||||
And sometimes the bar can be lower, eg in single-purpose less-frequently-developed modules like FODS.hs.
|
||||
|
||||
But I believe it's always worth at least considering them when adding code, and it's something I consider when reviewing code.
|
||||
I'll give some reasons why I think so, for the record (and maybe they'll persuade you just a little).
|
||||
|
||||
Haddocks help guide and anchor the developer while writing or changing code.
|
||||
They are the cheapest kind of doc, spec and test suite.
|
||||
They also create a place to add actual doctests, now or later.
|
||||
|
||||
Haddocks can be helpful to contributors who are not expert haskellers, which happens quite often in the hledger project.
|
||||
The human language descriptions can complement the code, reducing cognitive effort and helping with mental chunking.
|
||||
I think people find the hledger's code, with its pervasive haddocks, above average in readability.
|
||||
(And I think we've had more successful contributions as a result.)
|
||||
|
||||
Haddocks can also help experienced developers move faster.
|
||||
Code which seems quite clear and obvious when you are writing it is often less obvious to oneself a few weeks or years later.
|
||||
And certainly it can be less obvious to others than we might think.
|
||||
When debugging or coding we are often mentally stretched and we would prefer to conserve brainpower for the main task.
|
||||
|
||||
In my experience debugging/writing/changing hledger code,
|
||||
|
||||
- Number of times I've regretted seeing a haddock comment attached to some code: almost zero.
|
||||
- Effort to remove an excessive haddock: almost zero.
|
||||
- Number of times I've been trying to understand some contributed code and haddocks would have saved my time: quite a few.
|
||||
- Number of times I've appreciated code haddocks and found them helpful: many.
|
||||
- Number of times I've found errors or staleness in haddocks: not often.
|
||||
- Effort to fix wrong haddocks, or to write new ones: usually very low. And if it's high, it's usually very worthwhile because it alerts me to a confusion in the code or clarifies my thinking.
|
||||
|
||||
hledger is a documentation-driven project, with docs in general being a top priority.
|
||||
I think this is one reason it has held together and kept improving over a long period.
|
||||
@ -20,7 +20,7 @@ Here's the typical format: <!-- keep synced with tools/commitlint -->
|
||||
More precisely:
|
||||
|
||||
- Commit messages must begin with one or more prefixes (colon-terminated words),
|
||||
indicating the type and/or [topic](ISSUES.md#topics).
|
||||
indicating the type and/or [topic](ISSUES.html#topics).
|
||||
- Commits causing user-visible changes must begin with `feat:`, `imp:` or `fix:`
|
||||
(feature, improvement, or bugfix). These will be used in release notes.
|
||||
If they are breaking/incompatible changes, use `feat!:`, `imp!:` or `fix!:`.
|
||||
@ -51,13 +51,13 @@ Some possible prefixes:
|
||||
- `doc` - documentation-related
|
||||
- `test` - tests-related
|
||||
- `ci` - continuous integration-related
|
||||
- Any of the standard [labels](ISSUES.md#labels) used in the issue tracker.
|
||||
- Any of the standard [topics](ISSUES.html#topics) used in the issue tracker.
|
||||
|
||||
## How to check commits
|
||||
|
||||
Before committing, pushing, or merging, run `tools/commitlint` to check recent commit messages.
|
||||
(See the script for more ways to select commits.) You can configure your local working copy
|
||||
to do this automatically, by running `just installcommithook`.
|
||||
to do this automatically, by running `make installcommithook`.
|
||||
|
||||
commitlint also runs automatically on Github to check pull requests.
|
||||
|
||||
248
CONTRIBUTING.md
Normal file
248
CONTRIBUTING.md
Normal file
@ -0,0 +1,248 @@
|
||||
# Contributor Guide
|
||||
|
||||
<div class=pagetoc>
|
||||
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
This doc is intended to become a focussed guide for new contributors.
|
||||
|
||||
If you are unexpectedly seeing this page after following a link,
|
||||
the content probably moved to a separate page:
|
||||
see the [Developer docs](dev.md).
|
||||
|
||||
## Quick Links
|
||||
|
||||
| | |
|
||||
|-------------------------------|----------------------------------------------------------------------------
|
||||
| Chat, Mail, Twitter, HN etc. | <https://hledger.org/support.html>
|
||||
| hledger-web demo | [demo.hledger.org](https://demo.hledger.org)
|
||||
| hledger GHCJS demo | <https://hledger.alhur.es>
|
||||
| Trello | [old wishlist planning board](https://trello.hledger.org)
|
||||
| Github | [simonmichael/hledger](https://github.com/simonmichael/hledger) (shortcut: code.hledger.org)<br> [commits](https://github.com/simonmichael/hledger/commits), <!-- [unreleased commits](https://github.com/simonmichael/hledger/compare/0.23...master), [release branch commits](https://github.com/simonmichael/hledger/compare/master...0.23), --> [COMMITS!](https://starlogs.net/#simonmichael/hledger) <br> [ci.hledger.org](http://ci.hledger.org) <br> [open bugs](http://bugs.hledger.org), [open wishes](http://wishes.hledger.org), [open unknowns](https://github.com/simonmichael/hledger/issues?utf8=✓&q=is%3Aissue%20is%3Aopen%20-label%3A%22A%20BUG%22%20-label%3A%22A%20WISH%22%20), [open pull requests](http://prs.hledger.org), [draft open pull requests](http://draftprs.hledger.org), [ready open pull requests](http://readyprs.hledger.org), [all issues](https://github.com/simonmichael/hledger/issues?q=) <br> [issues with bounty tag](https://github.com/simonmichael/hledger/issues?q=label:bounty), [bountysource bounties](https://github.com/simonmichael/hledger/issues?q=%22Add%20to%20the%20bounty%20at%20Bountysource%22%20OR%20%22claim%20the%20bounty%20on%20Bountysource%22%20OR%20%22bounty%20on%20this%20issue%20has%20been%20claimed%20at%20Bountysource%22%20), [codemill bounties](https://github.com/simonmichael/hledger/issues?q=codemill), [codefund bounties](https://github.com/simonmichael/hledger/issues?utf8=✓&q=codefund) <br> [projects.hledger.org](http://projects.hledger.org) <br> [stars.hledger.org](http://stars.hledger.org): <a class="github-button" href="https://github.com/simonmichael/hledger" data-icon="octicon-star" data-count-href="/simonmichael/hledger/stargazers" data-count-api="/repos/simonmichael/hledger#stargazers_count" data-count-aria-label="# stargazers on GitHub" aria-label="Star simonmichael/hledger on GitHub"></a> our rank among starred haskell projects:<br>2016: #71, 2017: #54, 2018: #53, 2020: #36, 2022: #34
|
||||
| Hackage | <a name=hackage></a>packages: [hledger-lib](https://hackage.haskell.org/package/hledger-lib), [hledger](https://hackage.haskell.org/package/hledger), [hledger-ui](https://hackage.haskell.org/package/hledger-ui), [hledger-web](https://hackage.haskell.org/package/hledger-web), [hledger-diff](https://hackage.haskell.org/package/hledger-diff), [hledger-iadd](https://hackage.haskell.org/package/hledger-iadd), [hledger-interest](https://hackage.haskell.org/package/hledger-interest), [hledger-irr](https://hackage.haskell.org/package/hledger-irr), [\*hledger\*](https://hackage.haskell.org/packages/search?terms=hledger) <!-- [](https://hackage.haskell.org/package/hledger) --> <br> diffs: [hledger-lib](https://hdiff.luite.com/cgit/hledger-lib/diff), [hledger](https://hdiff.luite.com/cgit/hledger/diff), [hledger-ui](https://hdiff.luite.com/cgit/hledger-ui/diff), [hledger-web](https://hdiff.luite.com/cgit/hledger-web/diff) <br> build status: [hledger-lib](https://matrix.hackage.haskell.org/package/hledger-lib), [hledger](https://matrix.hackage.haskell.org/package/hledger), [hledger-ui](https://matrix.hackage.haskell.org/package/hledger-ui), [hledger-web](https://matrix.hackage.haskell.org/package/hledger-web) <br> reverse deps: [hledger-lib](https://packdeps.haskellers.com/reverse/hledger-lib), [hledger](https://packdeps.haskellers.com/reverse/hledger), [hledger-ui](https://packdeps.haskellers.com/reverse/hledger-ui), [hledger-web](https://packdeps.haskellers.com/reverse/hledger-web) <br> [](https://hackage.haskell.org/package/hledger) <br> [](https://packdeps.haskellers.com/feed?needle=hledger-lib) [](https://packdeps.haskellers.com/feed?needle=hledger) <br> [](https://packdeps.haskellers.com/feed?needle=hledger-ui) [](https://packdeps.haskellers.com/feed?needle=hledger-web)
|
||||
| Stackage | [build-constraints.yaml](https://github.com/fpco/stackage/blob/master/build-constraints.yaml) <br> [open hledger-related issues](https://github.com/fpco/stackage/search?q=hledger+is%3Aopen&type=Issues) <br> packages: [hledger-lib](https://www.stackage.org/package/hledger-lib), [hledger](https://www.stackage.org/package/hledger), [hledger-ui](https://www.stackage.org/package/hledger-ui), [hledger-web](https://www.stackage.org/package/hledger-web)<br> versions: [hledger-lib](https://www.stackage.org/package/hledger-lib/snapshots), [hledger](https://www.stackage.org/package/hledger/snapshots), [hledger-ui](https://www.stackage.org/package/hledger-ui/snapshots), [hledger-web](https://www.stackage.org/package/hledger-web/snapshots) <br> [](https://repology.org/metapackage/hledger) [](https://repology.org/metapackage/hledger)
|
||||
| Repology | [quick hledger packaging status](https://repology.org/metapackage/hledger/badges), [detailed hledger packaging status](https://repology.org/project/hledger/versions), [all \*hledger\* packages](https://repology.org/metapackages/?search=hledger)
|
||||
| Debian | source packages: [haskell-hledger-lib](https://tracker.debian.org/pkg/haskell-hledger-lib), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger-lib), [haskell-hledger](https://tracker.debian.org/pkg/haskell-hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger), [haskell-hledger-ui](https://tracker.debian.org/pkg/haskell-hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger-ui), [haskell-hledger-web](https://tracker.debian.org/pkg/haskell-hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=haskell-hledger-web) <br>stable: [hledger](https://packages.debian.org/stable/hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger;dist=stable), [hledger-ui](https://packages.debian.org/stable/hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-ui;dist=stable), [hledger-web](https://packages.debian.org/stable/hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-web;dist=stable) <br>testing: [hledger](https://packages.debian.org/testing/hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger;dist=testing), [hledger-ui](https://packages.debian.org/testing/hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-ui;dist=testing), [hledger-web](https://packages.debian.org/testing/hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-web;dist=testing) <br>unstable: [hledger](https://packages.debian.org/unstable/hledger), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger;dist=unstable), [hledger-ui](https://packages.debian.org/unstable/hledger-ui), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-ui;dist=unstable), [hledger-web](https://packages.debian.org/unstable/hledger-web), [bugs](https://bugs.debian.org/cgi-bin/pkgreport.cgi?package=hledger-web;dist=unstable) <br>all: [\*hledger\*](https://packages.debian.org/search?searchon=names&keywords=hledger) <br> popcon sampled install stats: [haskell-hledger](https://qa.debian.org/popcon.php?packages=haskell-hledger), [hledger](https://qa.debian.org/popcon.php?packages=hledger), [hledger-ui](https://qa.debian.org/popcon-graph.php?packages=hledger-ui), [hledger-web](https://qa.debian.org/popcon-graph.php?packages=hledger-web)
|
||||
| Ubuntu | source packages: [haskell-hledger-lib](https://launchpad.net/ubuntu/+source/haskell-hledger-lib), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger-lib), [haskell-hledger](https://launchpad.net/ubuntu/+source/haskell-hledger), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger), [haskell-hledger-ui](https://launchpad.net/ubuntu/+source/haskell-hledger-ui), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger-ui), [haskell-hledger-web](https://launchpad.net/ubuntu/+source/haskell-hledger-web), [bugs](https://bugs.launchpad.net/ubuntu/+source/haskell-hledger-web) <br> binary packages: [\*hledger\*](https://packages.ubuntu.com/search?suite=all&searchon=names&keywords=hledger)
|
||||
| Gentoo | [hledger](https://gpo.zugaina.org/dev-haskell/hledger), [hledger-web](https://gpo.zugaina.org/dev-haskell/hledger-web), [\*hledger\*](https://gpo.zugaina.org/Search?search=hledger)
|
||||
| Fedora | [hledger](https://apps.fedoraproject.org/packages/hledger), [\*hledger\*](https://apps.fedoraproject.org/packages/s/hledger), [hledger (package db)](https://admin.fedoraproject.org/pkgdb/package/hledger/), [Haskell SIG](https://fedoraproject.org/wiki/Haskell_SIG)
|
||||
| Void Linux | [package search](https://voidlinux.org/packages/) -> hledger
|
||||
| Nix | [\*hledger\*](https://hydra.nixos.org/search?query=hledger)
|
||||
| Homebrew | [hledger](https://formulae.brew.sh/formula/hledger) <br> our 1-year homebrew rank: <br>2020: [#1520 of 10000 on mac](https://formulae.brew.sh/analytics/install-on-request/365d), [#762 of 8288 on linux](https://formulae.brew.sh/analytics-linux/install-on-request/365d/)
|
||||
| Sandstorm | [hledger web app & reviews](https://apps.sandstorm.io/app/8x12h6p0x0nrzk73hfq6zh2jxtgyzzcty7qsatkg7jfg2mzw5n90), [issues](https://github.com/simonmichael/hledger/issues?utf8=✓&q=label%3A%22platform%3A%20sandstorm%22%20)
|
||||
| Reference | [fosskers GHC compatibility chart](https://www.fosskers.ca/en/blog/base)
|
||||
|
||||
<!-- | hledger-api demo | [api-demo.hledger.org/api/v1/accounts](https://api-demo.hledger.org/api/v1/accounts), [api-demo.hledger.org/swagger.json](https://api-demo.hledger.org/swagger.json), [in swagger editor](https://editor2.swagger.io/#/?import=api-demo.hledger.org/swagger.json&no-proxy) <br> [unfinished angular sample app](https://api-demo.hledger.org) ([code](https://github.com/simonmichael/hledger/tree/master/hledger-api/examples/angular)) -->
|
||||
<!--
|
||||
| Travis CI | [](https://travis-ci.org/simonmichael/hledger/builds)
|
||||
| Appveyor CI | [](https://ci.appveyor.com/project/simonmichael/hledger/history)
|
||||
| Azure CI | <a href="https://dev.azure.com/simonmic/hledger/_build"><img src="https://dev.azure.com/simonmic/hledger/_apis/build/status/simonmichael.hledger?branchName=master" alt="..."></a>
|
||||
-->
|
||||
|
||||
<!-- list the debian packages for clarity:
|
||||
3 source:
|
||||
haskell-hledger-lib
|
||||
haskell-hledger
|
||||
haskell-hledger-web
|
||||
8 binary:
|
||||
hledger
|
||||
hledger-web
|
||||
libghc-hledger-dev
|
||||
libghc-hledger-doc
|
||||
libghc-hledger-prof
|
||||
libghc-hledger-lib-dev
|
||||
libghc-hledger-lib-doc
|
||||
libghc-hledger-lib-prof
|
||||
-->
|
||||
|
||||
## Open issues
|
||||
|
||||
An overview of hledger's [issue tracker](https://github.com/simonmichael/hledger/issues).
|
||||
A good place to start looking for something to work on.
|
||||
|
||||
<!--
|
||||
This table doesn't have to be aligned, but it helps.
|
||||
Editing it may require editor support, search/replace etc.
|
||||
Syntax: https://www.pandoc.org/MANUAL.html#tables -> pipe_tables
|
||||
-->
|
||||
|
||||
| COMPONENT/TOPIC [*](#topics) | BUGS | WISHES | PRS | OTHER
|
||||
|----------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------
|
||||
| [all](https://github.com/simonmichael/hledger/issues?q=is:open) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22)
|
||||
| **Tools:**
|
||||
| [install](https://github.com/simonmichael/hledger/issues?q=is:open+label:install) (hledger-install.sh) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:install) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:install)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:install)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:install)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:install) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:install) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:install)
|
||||
| [cli](https://github.com/simonmichael/hledger/issues?q=is:open+label:cli) (hledger) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:cli) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:cli)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:cli)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:cli)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:cli) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:cli) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:cli)
|
||||
| [ui](https://github.com/simonmichael/hledger/issues?q=is:open+label:ui) (hledger-ui) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:ui) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:ui)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:ui)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:ui)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:ui) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:ui) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:ui)
|
||||
| [web](https://github.com/simonmichael/hledger/issues?q=is:open+label:web) (hledger-web) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:web) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:web)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:web)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:web)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:web) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:web) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:web)
|
||||
| **Input/Output Formats:**
|
||||
| [journal](https://github.com/simonmichael/hledger/issues?q=is:open+label:journal) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:journal) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:journal)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:journal)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:journal)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:journal) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:journal) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:journal)
|
||||
| [timeclock](https://github.com/simonmichael/hledger/issues?q=is:open+label:timeclock) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:timeclock) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:timeclock)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:timeclock)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:timeclock)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:timeclock) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:timeclock) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:timeclock)
|
||||
| [timedot](https://github.com/simonmichael/hledger/issues?q=is:open+label:timedot) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:timedot) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:timedot)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:timedot)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:timedot)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:timedot) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:timedot) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:timedot)
|
||||
| [csv](https://github.com/simonmichael/hledger/issues?q=is:open+label:csv) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:csv) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:csv)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:csv)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:csv)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:csv) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:csv) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:csv)
|
||||
| [json](https://github.com/simonmichael/hledger/issues?q=is:open+label:json) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:json) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:json)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:json)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:json)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:json) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:json) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:json)
|
||||
| [html](https://github.com/simonmichael/hledger/issues?q=is:open+label:html) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:html) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:html)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:html)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:html)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:html) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:html) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:html)
|
||||
| **Commands:**
|
||||
| [accounts](https://github.com/simonmichael/hledger/issues?q=is:open+label:accounts) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:accounts) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:accounts)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:accounts)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:accounts)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:accounts) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:accounts) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:accounts)
|
||||
| [activity](https://github.com/simonmichael/hledger/issues?q=is:open+label:activity) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:activity) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:activity)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:activity)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:activity)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:activity) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:activity) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:activity)
|
||||
| [add](https://github.com/simonmichael/hledger/issues?q=is:open+label:add) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:add) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:add)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:add)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:add)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:add) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:add) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:add)
|
||||
| [balcmds](https://github.com/simonmichael/hledger/issues?q=is:open+label:balcmds) (bal/bs/bse/cf/is/...) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:balcmds) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:balcmds)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:balcmds)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:balcmds)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:balcmds) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:balcmds) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:balcmds)
|
||||
| [balance](https://github.com/simonmichael/hledger/issues?q=is:open+label:balance) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:balance) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:balance)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:balance)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:balance)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:balance) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:balance) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:balance)
|
||||
| [balancesheet](https://github.com/simonmichael/hledger/issues?q=is:open+label:balancesheet) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:balancesheet) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:balancesheet)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:balancesheet)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:balancesheet)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:balancesheet) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:balancesheet) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:balancesheet)
|
||||
| [cashflow](https://github.com/simonmichael/hledger/issues?q=is:open+label:cashflow) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:cashflow) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:cashflow)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:cashflow)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:cashflow)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:cashflow) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:cashflow) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:cashflow)
|
||||
| [checkdates](https://github.com/simonmichael/hledger/issues?q=is:open+label:checkdates) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:checkdates) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:checkdates)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:checkdates)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:checkdates)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:checkdates) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:checkdates) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:checkdates)
|
||||
| [checkdupes](https://github.com/simonmichael/hledger/issues?q=is:open+label:checkdupes) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:checkdupes) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:checkdupes)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:checkdupes)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:checkdupes)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:checkdupes) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:checkdupes) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:checkdupes)
|
||||
| [close](https://github.com/simonmichael/hledger/issues?q=is:open+label:close) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:close) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:close)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:close)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:close)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:close) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:close) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:close)
|
||||
| [import](https://github.com/simonmichael/hledger/issues?q=is:open+label:import) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:import) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:import)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:import)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:import)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:import) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:import) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:import)
|
||||
| [incomestatement](https://github.com/simonmichael/hledger/issues?q=is:open+label:incomestatement) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:incomestatement) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:incomestatement)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:incomestatement)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:incomestatement)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:incomestatement) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:incomestatement) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:incomestatement)
|
||||
| [prices](https://github.com/simonmichael/hledger/issues?q=is:open+label:prices) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:prices) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:prices)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:prices)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:prices)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:prices) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:prices) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:prices)
|
||||
| [print](https://github.com/simonmichael/hledger/issues?q=is:open+label:print) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:print) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:print)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:print)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:print)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:print) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:print) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:print)
|
||||
| [printunique](https://github.com/simonmichael/hledger/issues?q=is:open+label:printunique) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:printunique) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:printunique)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:printunique)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:printunique)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:printunique) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:printunique) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:printunique)
|
||||
| [register](https://github.com/simonmichael/hledger/issues?q=is:open+label:register) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:register) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:register)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:register)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:register)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:register) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:register) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:register)
|
||||
| [registermatch](https://github.com/simonmichael/hledger/issues?q=is:open+label:registermatch) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:registermatch) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:registermatch)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:registermatch)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:registermatch)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:registermatch) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:registermatch) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:registermatch)
|
||||
| [rewrite](https://github.com/simonmichael/hledger/issues?q=is:open+label:rewrite) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:rewrite) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:rewrite)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:rewrite)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:rewrite)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:rewrite) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:rewrite) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:rewrite)
|
||||
| [roi](https://github.com/simonmichael/hledger/issues?q=is:open+label:roi) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:roi) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:roi)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:roi)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:roi)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:roi) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:roi) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:roi)
|
||||
| [stats](https://github.com/simonmichael/hledger/issues?q=is:open+label:stats) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:stats) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:stats)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:stats)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:stats)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:stats) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:stats) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:stats)
|
||||
| [tags](https://github.com/simonmichael/hledger/issues?q=is:open+label:tags) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:tags) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:tags)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:tags)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:tags)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:tags) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:tags) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:tags)
|
||||
| **Miscellaneous:**
|
||||
| [budget](https://github.com/simonmichael/hledger/issues?q=is:open+label:budget) (budgeting) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:budget) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:budget)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:budget)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:budget)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:budget) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:budget) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:budget)
|
||||
| [packaging](https://github.com/simonmichael/hledger/issues?q=is:open+label:deps) (packaging, dependencies) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:deps) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:deps)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:deps)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:deps)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:deps) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:deps) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:deps)
|
||||
| [doc](https://github.com/simonmichael/hledger/issues?q=is:open+label:doc) (documentation, help) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:doc) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:doc)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:doc)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:doc)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:doc) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:doc) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:doc)
|
||||
| [periodexpressions](https://github.com/simonmichael/hledger/issues?q=is:open+label:periodexpressions) (-b, -e, -p, date:) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:periodexpressions) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:periodexpressions)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:periodexpressions)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:periodexpressions)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:periodexpressions) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:periodexpressions) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:periodexpressions)
|
||||
| [site](https://github.com/simonmichael/hledger/issues?q=is:open+label:site) (website, web presence) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:site) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:site)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:site)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:site)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:site) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:site) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:site)
|
||||
| [tools](https://github.com/simonmichael/hledger/issues?q=is:open+label:tools) (dev tools, infrastructure) | [bugs](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:tools) ([first](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+label:%22good+first+issue%22+label:tools)/[easy](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+label:easy?+label:tools)/[neither](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+BUG%22+-label:%22good+first+issue%22+-label:easy?+label:tools)) | [wishes](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+label:%22A+WISH%22+label:tools) | [PRs](https://github.com/simonmichael/hledger/issues?q=is:open+is:pr+label:tools) | [other](https://github.com/simonmichael/hledger/issues?q=is:open+is:issue+-label:%22A+BUG%22+-label:%22A+WISH%22+label:tools)
|
||||
|
||||
|
||||
## About the project
|
||||
|
||||
### Mission
|
||||
|
||||
Why was hledger created ?
|
||||
|
||||
Mainly:
|
||||
|
||||
- to provide a more usable, robust, documented, cross-platform-installable version of Ledger for users
|
||||
- to provide a more maintainable and hackable version of Ledger for developers
|
||||
|
||||
Also:
|
||||
|
||||
- to provide a useful library and toolbox for finance-minded haskell programmers
|
||||
- to explore the suitability of Haskell for such applications
|
||||
- to experiment with building a successful time-and-money-solvent project in a thriving ecosystem of financial software projects
|
||||
|
||||
What is the hledger project's current mission ?
|
||||
|
||||
1. Provide peace of mind: bring clarity, relief, and peace of mind to folks stressed, confused, overwhelmed by finances.
|
||||
2. Educate and empower: help individuals and communities achieve clarity, accountability and mastery with money and time.
|
||||
|
||||
### Roles and activities
|
||||
|
||||
- newcomer/potential user
|
||||
- user
|
||||
- library user
|
||||
- field tester
|
||||
- bug wrangler
|
||||
- support
|
||||
- documentor
|
||||
- qa
|
||||
- developer
|
||||
- packager
|
||||
- communicator
|
||||
- project manager
|
||||
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
New contributors are always welcome in the hledger project.
|
||||
Jump in! Or [ask us](support.html) to help you find a task.
|
||||
|
||||
### Funder
|
||||
|
||||
Become a financial backer to
|
||||
sustain and grow this project,
|
||||
increase your influence,
|
||||
express gratitude,
|
||||
build prosperity consciousness,
|
||||
and help transform world finance!
|
||||
|
||||
- Use the donate links on the [home page](https://hledger.org)
|
||||
- Configure a recurring donation
|
||||
- Contribute or pledge bounties on issues you care about
|
||||
- Ask your organization to contribute
|
||||
- Work on project sustainability, accountability, fundraising
|
||||
|
||||
### Tester
|
||||
|
||||
- Test installation on platforms you have access to
|
||||
- Test examples, advice, and links in the docs
|
||||
- Run the latest release or developer build in daily use
|
||||
- Run [tests](#run-package-tests)
|
||||
- Run [benchmarks](#run-package-benchmarks)
|
||||
- Report packaging, documentation, UX, functional, performance issues
|
||||
- Report and help analyse problems via irc/mail list/bug tracker
|
||||
|
||||
When reporting bugs, don't forget to search the tracker for a similar bug report.
|
||||
Otherwise, open a new bug by clicking "New issue", or <http://bugs.hledger.org/new>.
|
||||
|
||||
Enhancement requests are sometimes added to the tracker,but for these consider using
|
||||
the IRC channel and mail list (see [Getting help](index.html#getting-help)).
|
||||
Both are archived and linkable, so the idea won't be lost.
|
||||
There is also a collection of wishes at the old [trello board](http://trello.hledger.org).
|
||||
|
||||
### Technical Writer
|
||||
|
||||
- get familiar with the website and documentation online, review and test
|
||||
- get familiar with the site/doc source files (see [Shake.hs](#shake))
|
||||
- get the latest hledger source
|
||||
- send patches with names prefixed with "doc: " (or "site: ")
|
||||
|
||||
### Graphics Designer
|
||||
|
||||
- more/better logos & graphics
|
||||
- illustrations and diagrams
|
||||
- web design mockups for home page, site, hledger-web UI
|
||||
|
||||
<!-- ### Product Designer -->
|
||||
### Communicator
|
||||
|
||||
Marketing and market understanding is vital.
|
||||
|
||||
- clarify project goals, value proposition, brand, mission, story
|
||||
- monitor product-market fit
|
||||
- identify new opportunities
|
||||
- influence developer priorities
|
||||
- spread the word!
|
||||
|
||||
### Maintainer
|
||||
|
||||
#### Help with issue management
|
||||
|
||||
- watch tracker activity, report status
|
||||
- apply/update labels where needed
|
||||
- follow up on dormant issues
|
||||
- facilitate a consistently good bug-reporting & PR-contributing experience
|
||||
|
||||
#### Help with packaging
|
||||
|
||||
- package hledger for linux distros, macports, etc.
|
||||
- develop mac/windows installers
|
||||
- find and assist distro packagers/installer developers
|
||||
|
||||
#### Help with project management
|
||||
|
||||
- clarify/update goals and principles
|
||||
- monitor, report on project progress and performance
|
||||
- research, compare and report on successful projects, related projects
|
||||
- identify collaboration opportunities
|
||||
- marketing, communication, outreach
|
||||
- release management, roadmap planning
|
||||
|
||||
### Developer
|
||||
|
||||
See [Developer workflows](WORKFLOWS.md#developer-workflows).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,114 +1,105 @@
|
||||
# CREDITS
|
||||
|
||||
hledger is brought to you by...\
|
||||
the Issue wranglers,
|
||||
Bug hunters,
|
||||
Design dreamers,
|
||||
Code slingers,
|
||||
Doc poets,
|
||||
Package marshals,
|
||||
Helping hands,
|
||||
Good news preachers,
|
||||
Bank rollers,
|
||||
Broom pushers,
|
||||
the pioneer John Wiegley,
|
||||
and innumerable other benefactors.
|
||||
hledger is brought to you by the
|
||||
|
||||
- Issue wranglers,
|
||||
- Bug hunters,
|
||||
- Design dreamers,
|
||||
- Code slingers,
|
||||
- Doc poets,
|
||||
- Package marshals,
|
||||
- Helping hands,
|
||||
- Good news preachers,
|
||||
- Bank rollers,
|
||||
- Broom pushers,
|
||||
|
||||
by the pioneering John Wiegley, who opened up this territory with [Ledger](https://ledger-cli.org),
|
||||
|
||||
and by the innumerable other benefactors making it all possible.
|
||||
|
||||
## Commit authors
|
||||
|
||||
<a href="https://github.com/simonmichael/hledger/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=simonmichael/hledger&max=9999" />
|
||||
</a>
|
||||
10080 commits in 14 years by 143 people as of 2021-08-29:
|
||||
|
||||
<https://github.com/simonmichael/hledger/graphs/contributors>
|
||||
|
||||
11231 commits in 16 years by 155 people as of 2022-12-21:
|
||||
|
||||
|
||||
<!-- year-end: update stats, just authors, replace table preserving notes (eg emacs macro), maybe fix root commits -->
|
||||
| Commits | Author | Notes ([chat](#footer) me with updates!) |
|
||||
|---------|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 9749 | Simon Michael | founder, project leader, lead developer |
|
||||
| 460 | Stephen Morgan | performance, code cleanup, runtime error removal, cli/ui output, periodic transactions, parsing, deps, valuation, --gain report, hlint, lensification |
|
||||
| 161 | Dmitry Astapov | roi, files commands; --transpose; merge/improve --budget; generalise --forecast/--auto; docker packaging; improved CSV parsing, balancing, periodic transactions, close, parsing, docs, tests |
|
||||
<!-- make showauthors, merge notes -->
|
||||
| Commits | Author | Notes ([chat](#footer) me with updates!)
|
||||
|---------|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 8748 | Simon Michael | founder, project leader, lead developer |
|
||||
| 334 | Stephen Morgan | performance, code cleanup, runtime error removal, cli/ui output, periodic transactions, parsing, deps, valuation, --gain report, hlint, lensification... |
|
||||
| 158 | Dmitry Astapov | roi, files commands; --transpose; merge/improve --budget; generalise --forecast/--auto; docker packaging; improved CSV parsing, balancing, periodic transactions, close, parsing, docs, tests...|
|
||||
| 81 | Vladimir Zhelezov | new bash shell completions |
|
||||
| 72 | Alex Chen | parsing improvements, code cleanups, better error messages; dep updates |
|
||||
| 52 | Mykola Orliuk | hledger-budget, hledger-prices add-ons; scientific number notation; print, hledger-equity, hledger-rewrite, --pivot, space, parsing improvements; code updates; GHC 8.0 support |
|
||||
| 51 | Jakob Schöttl | bash completions; register --invert; timeclock parsing improvements; code cleanups |
|
||||
| 52 | Mykola Orliuk | hledger-budget, hledger-prices addons; scientific number notation; print, hledger-equity, hledger-rewrite, --pivot, space, parsing improvements; code updates; GHC 8.0 support |
|
||||
| 50 | Jakob Schöttl | bash completions; register --invert; timeclock parsing improvements; code cleanups |
|
||||
| 40 | Everett Hildenbrandt | doc toolchain updates, switch from hakyll to pandoc; csv parser improvement |
|
||||
| 31 | Jakub Zárybnický | hledger-web, hledger-ui improvements |
|
||||
| 29 | Marko Kocić | build, hlint fixes; hledger-web improvement |
|
||||
| 26 | Justin Le | bs/cf/is improvements |
|
||||
| 26 | Dominik Süß | hledger-web layout improvements |
|
||||
| 26 | Justin Le | bs/cf/is improvements |
|
||||
| 24 | Thomas R. Koll | hledger-web improvements |
|
||||
| 17 | Peter Simons | build, dep fixes |
|
||||
| 17 | Joseph Weston | parsing improvements; test, dep updates |
|
||||
| 16 | Aleksandar Dimitrov | CSV separator rule |
|
||||
| 15 | Nolan Darilek | Sandstorm app |
|
||||
| 14 | Brian Wignall | output dates in YYYY-MM-DD format |
|
||||
| 12 | Tim Docker | parsing improvements; proper date support; P directive (first code contributor, 2008-11 |
|
||||
| 12 | Lawrence | --commodity-column; multi-day-of-week period expressions |
|
||||
| 11 | Trygve Laugstøl | hledger-web improvements; --format; CSV --rules-file, stdin support, separate in/out fields, interpolated description; test updates |
|
||||
| 12 | Tim Docker | parsing improvements; proper date support; P directive (first code contributor, 2008-11) |
|
||||
| 11 | Jesse Rosenthal | parsing improvementss |
|
||||
| 10 | Nick Ingolia | include directive, account directive; parsing improvements (second code contributor, 2008-12 |
|
||||
| 10 | Caleb Maclennan | payees/notes/descriptions commands; print improvement; doc, code, test updates |
|
||||
| 11 | Trygve Laugstøl | hledger-web improvements; --format; CSV --rules-file, stdin support, separate in/out fields, interpolated description; test updates |
|
||||
| 11 | Lawrence | --commodity-column; multi-day-of-week period expressions |
|
||||
| 10 | Julien Moutinho | print CSV output; hledger-equity, hledger-rewrite, hledger-web, parsing improvements; hledger-check-dates addon |
|
||||
| 10 | Nick Ingolia | include directive, account directive; parsing improvements (second code contributor, 2008-12) |
|
||||
| 10 | Henning Thielemann | hledger-web improvements, quarter periods, code cleanup |
|
||||
| 9 | Ryan Desfosses | warnings, docs, hledger-web fixes |
|
||||
| 10 | Caleb Maclennan | payees/notes/descriptions commands; print improvement; doc, code, test updates |
|
||||
| 9 | Eli Flanagan | hledger-web date picker; build, doc updates |
|
||||
| 9 | Ryan Desfosses | warnings, docs, hledger-web fixes |
|
||||
| 8 | Imuli | support multiple input files |
|
||||
| 8 | Felix Yan | dep updates; doc updates |
|
||||
| 8 | Nicholas Niro | balancesheetequity command; balance tests, fix |
|
||||
| 8 | Moritz Kiefer | --pretty-tables; dep updates; switch to megaparsec; cabal.project file; space leak fixes |
|
||||
| 7 | Jacob Weisz | Sandstorm app improvements |
|
||||
| 7 | Hans-Peter Deifel | dep updates; csv rules parsing fix; command line parsing improvements |
|
||||
| 6 | Clint Adams | CSV account2 setting; dep updates; cabal test suites |
|
||||
| 7 | Jacob Weisz | Sandstorm app improvements |
|
||||
| 7 | Felix Yan | dep updates; doc updates |
|
||||
| 6 | Roman Cheplyaka | chart command; hledger add improvements; --no-new-accounts |
|
||||
| 6 | Gaith Hallak | undo (<) in hledger add; command line parsing improvement |
|
||||
| 6 | Samuel May | multicommodity balance assertions |
|
||||
| 5 | Martin Michlmayr | doc updates |
|
||||
| 6 | Clint Adams | CSV account2 setting; dep updates; cabal test suites |
|
||||
| 5 | Jacek Generowicz | command line parsing fix |
|
||||
| 5 | Eric Mertens | --pretty-tables improvements; CSV whitespace fix |
|
||||
| 5 | Martin Michlmayr | doc updates |
|
||||
| 5 | Xinruo Sun | hledger-web --static-root; hledger-web autocomplete improvements; hledger print tag filtering |
|
||||
| 4 | Damien Cassou | payee directive, check improvements, info manual directory entries |
|
||||
| 5 | Eric Mertens | --pretty-tables improvements; CSV whitespace fix |
|
||||
| 4 | Michael Snoyman | hledger-web improvements |
|
||||
| 4 | Sergey Astanin | unicode support |
|
||||
| 3 | Michael Sanders | & (AND) operator in CSV if rules |
|
||||
| 3 | Christian G. Warden | cashflow tweaks; hledger-rewrite (auto postings) commodity substitution |
|
||||
| 4 | Damien Cassou | payee directive, check improvements, info manual directory entries |
|
||||
| 3 | Eric Kow | hledger add improvements |
|
||||
| 3 | toonn | PR template improvements |
|
||||
| 3 | Michael Sanders | & (AND) operator in CSV if rules |
|
||||
| 3 | Carlos Lopez-Camey | hledger-web add form improvements |
|
||||
| 3 | Christian G. Warden | cashflow tweaks; hledger-rewrite (auto postings) commodity substitution |
|
||||
| 3 | Johannes Gerer | balance assignments; generalise parser types |
|
||||
| 3 | Malte Brandy | --pivot, newline in CSV rule-generated comments |
|
||||
| 2 | Pavlo Kerestey | quoting fixes |
|
||||
| 2 | Alejandro García Montoro | hledger-web --cors |
|
||||
| 2 | Gergely Risko | comment directive |
|
||||
| 2 | aragaer | fix commodity checking fix; fix --drop with csv |
|
||||
| 2 | Stefano Rodighiero | hledger-dupes addon |
|
||||
| 2 | Arsen Arsenović | hledger-web XSS fix |
|
||||
| 2 | crocket | improve hledger-ui editor support |
|
||||
| 2 | Arnout Engelen | hledger-web register chart improvements |
|
||||
| 2 | gwern | whitespace, Haskell98 cleanups |
|
||||
| 2 | Arjen Langebaerd | -c/--commodity-style option |
|
||||
| 2 | jungle-boogie | tutorial updates |
|
||||
| 2 | Max Bolingbroke | unicode-aware regexes; csv date-format rule |
|
||||
| 2 | Matthias Kauer | investment doc improvements |
|
||||
| 2 | Elijah Caine | git/nix tweaks |
|
||||
| 2 | Judah Jacobson | readline editing, tab completion in hledger add |
|
||||
| 2 | Stefano Rodighiero | hledger-dupes addon |
|
||||
| 2 | Ben Creasy | doc updates |
|
||||
| 2 | Christoph Nicolai | doc updates |
|
||||
| 2 | Sergei Trofimovich | bounds, build updates |
|
||||
| 2 | Sam Jeeves | balance assertion line number reporting |
|
||||
| 2 | Alex Hirzel | doc updates |
|
||||
| 2 | Pranesh Prakash | doc updates |
|
||||
| 2 | Christoph Nicolai | doc updates |
|
||||
| 2 | aragaer | fix commodity checking fix; fix --drop with csv |
|
||||
| 2 | Judah Jacobson | readline editing, tab completion in hledger add |
|
||||
| 2 | Pavlo Kerestey | quoting fixes |
|
||||
| 2 | Gergely Risko | comment directive |
|
||||
| 2 | crocket | improve hledger-ui editor support |
|
||||
| 2 | Arsen Arsenović | hledger-web XSS fix |
|
||||
| 2 | Gwern Branwen | whitespace, Haskell98 cleanups |
|
||||
| 2 | Max Bolingbroke | unicode-aware regexes; csv date-format rule |
|
||||
| 2 | jungle-boogie | tutorial updates |
|
||||
| 2 | Arnout Engelen | hledger-web register chart improvements |
|
||||
| 2 | Matthias Kauer | investment doc improvements |
|
||||
| 2 | Alejandro García Montoro | hledger-web --cors |
|
||||
| 1 | azure-pipelines[bot] | |
|
||||
| 1 | charukiewicz | |
|
||||
| 1 | flip111 | |
|
||||
| 1 | jeevcat | |
|
||||
| 1 | legrostdg | |
|
||||
| 1 | max thomas | |
|
||||
| 1 | trevorriles | |
|
||||
| 1 | zieone | |
|
||||
| 1 | Aerex | |
|
||||
| 1 | ˌbodʲɪˈɡrʲim | |
|
||||
| 1 | zieone | |
|
||||
| 1 | Aiken Cairncross | |
|
||||
| 1 | Alan Young | |
|
||||
| 1 | Alvaro Fernando García | |
|
||||
@ -117,16 +108,15 @@ and innumerable other benefactors.
|
||||
| 1 | Andreas Pauley | |
|
||||
| 1 | Andrew Jones | |
|
||||
| 1 | Andriy Mykhaylyk | |
|
||||
| 1 | Arjen Langebaerd | |
|
||||
| 1 | Ben Boeckel | |
|
||||
| 1 | Boyd Kelly | |
|
||||
| 1 | Brian Scott | |
|
||||
| 1 | Bryan Richter | |
|
||||
| 1 | Carel Fellinger | |
|
||||
| 1 | Carl Richard Theodor Schneider | |
|
||||
| 1 | Charlotte Van Petegem | |
|
||||
| 1 | Carl Richard Theodor Schneider | |
|
||||
| 1 | Colin Woodbury | |
|
||||
| 1 | Daniel Gröber | |
|
||||
| 1 | David D Lowe | |
|
||||
| 1 | David Reaver | |
|
||||
| 1 | David Zhang | |
|
||||
| 1 | Doug Goldstein | |
|
||||
@ -138,7 +128,6 @@ and innumerable other benefactors.
|
||||
| 1 | Jan Zerebecki | |
|
||||
| 1 | Jeff Richards | |
|
||||
| 1 | Joachim Breitner | |
|
||||
| 1 | Joaquin "Florius" Azcarate | |
|
||||
| 1 | Joe Horsnell | |
|
||||
| 1 | Johann Klähn | |
|
||||
| 1 | John Wiegley | |
|
||||
@ -149,6 +138,7 @@ and innumerable other benefactors.
|
||||
| 1 | Luca Molteni | |
|
||||
| 1 | Léo Gaspard | |
|
||||
| 1 | M Parker | |
|
||||
| 1 | Malte Brandy | |
|
||||
| 1 | Mark Hansen | |
|
||||
| 1 | Mateus Furquim | |
|
||||
| 1 | Michael Kainer | |
|
||||
@ -161,14 +151,11 @@ and innumerable other benefactors.
|
||||
| 1 | Nissar Chababy | |
|
||||
| 1 | Oliver Braun | |
|
||||
| 1 | Omari Norman | |
|
||||
| 1 | Patrick Fiaux | |
|
||||
| 1 | Patrik Keller | |
|
||||
| 1 | Pavan Rikhi | |
|
||||
| 1 | Pia Mancini | |
|
||||
| 1 | Rick Lupton | |
|
||||
| 1 | Rui Chen | |
|
||||
| 1 | Sam Doshi | |
|
||||
| 1 | ShrykeWindgrace | |
|
||||
| 1 | Shubham Lagwankar | |
|
||||
| 1 | Simon Hengel | |
|
||||
| 1 | SpicyCat | |
|
||||
@ -180,5 +167,3 @@ and innumerable other benefactors.
|
||||
| 1 | afarrow | |
|
||||
| 1 | agander | |
|
||||
| 1 | awjchen | |
|
||||
| 1 | azure-pipelines[bot] | |
|
||||
| 1 | charukiewicz | |
|
||||
154
DOCS.md
Normal file
154
DOCS.md
Normal file
@ -0,0 +1,154 @@
|
||||
# Docs
|
||||
|
||||
<div class=pagetoc>
|
||||
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
## Four kinds of documentation
|
||||
|
||||
<div style="margin:1em 2em; font-style:italic;">
|
||||
"There is a secret that needs to be understood in order to write good
|
||||
software documentation: there isn’t one thing called documentation,
|
||||
there are four. They are: tutorials, how-to guides, explanation and
|
||||
technical reference. They represent four different purposes or
|
||||
functions, and require four different approaches to their creation."
|
||||
--[Daniele Procida] (https://news.ycombinator.com/item?id=21289832)
|
||||
</div>
|
||||
|
||||
## hledger's documentation structure
|
||||
|
||||
2019: out of date, needs update.
|
||||
|
||||
Project documentation lives in a number of places:
|
||||
|
||||
- `site/*.md` is the hledger.org website content, which is generated with hakyll[-std] and pandoc
|
||||
- haddock documentation in the code appears on Hackage
|
||||
- short blurbs: cabal files, module headers, HCAR, GSOC project, ..
|
||||
- `doc/notes.org` has some old developer notes
|
||||
- developer reports (profiles, benchmarks, coverage..) in doc/profs, sometimes published at hledger.org/profs
|
||||
- https://github.com/simonmichael/hledger/tree/master/doc
|
||||
|
||||
|
||||
site/ is now a symlink to the separate hledger_site repo.
|
||||
|
||||
See also Shake.hs.
|
||||
|
||||
hledger doc files can be divided into several groups:
|
||||
|
||||
1. Project admin/dev notes not published on the website.
|
||||
These are kept in this directory (doc/). They include:
|
||||
```
|
||||
doc/finance/ project finances
|
||||
doc/hcar/ Haskell Community and Activities Report entries
|
||||
doc/lib.m4 common macros used in package manuals
|
||||
doc/manpage.* misc. templates for rendering package manuals
|
||||
doc/mockups/ exploratory developer mockups
|
||||
doc/profs/ a place for long-term profiling/performance data
|
||||
```
|
||||
2. Project doc files required to be in the top directory:
|
||||
```
|
||||
README.md the main project readme, displayed on github
|
||||
LICENSE the default project license
|
||||
```
|
||||
3. Code/API docs in haskell source files as haddock comments:
|
||||
```
|
||||
hledger*/**/*.hs haddock module and function docs in most source files
|
||||
```
|
||||
4. Per-package descriptions, readmes, changelogs, and reference manuals.
|
||||
These are in the respective package directories:
|
||||
```
|
||||
hledger*/package.yaml source for package metadata (description, etc.)
|
||||
hledger*/README package readme, displayed on hackage
|
||||
hledger*/CHANGES package changelog, displayed on hackage
|
||||
hledger*/hledger*.m4.md package manual source file(s)
|
||||
```
|
||||
5. The project website and additional docs - home page, FAQ, tutorials,
|
||||
how-tos, developer guide, etc. These are in the site directory:
|
||||
```
|
||||
site/ hledger.org website content, templates, assets
|
||||
```
|
||||
|
||||
## Workflows
|
||||
|
||||
The manuals and website are rendered from the top directory,
|
||||
primarily using Shake. First, build Shake:
|
||||
|
||||
```
|
||||
$ make Shake
|
||||
```
|
||||
|
||||
Then render the per-package manuals from markdown-m4 source files (*.m4.md)
|
||||
to text, man, info, and markdown formats. This requires some unix tools
|
||||
such as m4:
|
||||
|
||||
```
|
||||
$ ./Shake manuals
|
||||
```
|
||||
|
||||
The text/man/info manuals are embedded in the hledger executable, so a
|
||||
rebuild of that now will pick up the latest manuals:
|
||||
|
||||
```
|
||||
$ stack build hledger
|
||||
```
|
||||
|
||||
The website uses the markdown manuals. This copies them into the
|
||||
website, edits them for web display, concatenates them to form the
|
||||
one-page manual, and runs pandoc to render everything as html,
|
||||
adding tables of contents and the site header/footer.
|
||||
|
||||
```
|
||||
$ ./Shake website
|
||||
```
|
||||
|
||||
## 201901 docs reorg (#920, WIP)
|
||||
|
||||
https://groups.google.com/forum/#!topic/hledger/t2nVr3zER8Q/discussion
|
||||
|
||||
> > On Oct 26, 2018, at 1:47 PM, Simon Michael <simon@joyful.com> wrote:
|
||||
> >
|
||||
> > A quick heads-up: I am feeling like stepping back from github wiki, and reorganising our docs like so:
|
||||
> >
|
||||
> > Two repos:
|
||||
> >
|
||||
> > 1. hledger - code and hard docs
|
||||
> >
|
||||
> > - code and code docs (haddock docs & doctest examples)
|
||||
> > - developer docs (READMEs in md or org format)
|
||||
> > - product manuals (hledger*/hledger*.m4.md)
|
||||
> > - release notes and announcements
|
||||
> > - HCAR entries
|
||||
> >
|
||||
> > 2. hledger-site - website and soft docs
|
||||
> >
|
||||
> > - hledger.org content, resources, site infrastructure
|
||||
> > - user cookbook, how-tos, articles
|
||||
> > - links to blog posts, discussions etc.
|
||||
> > - other resources relating to our web presence/marketing
|
||||
> >
|
||||
> > If you disagree, let's discuss. Some quick considerations:
|
||||
> >
|
||||
> > - moving docs to the wiki hasn't affected the contribution rate
|
||||
> > - using the wiki increases our dependence on github and makes our work less self-contained and future-proof
|
||||
> > - the wiki docs don't look great, aren't very flexible, & don't integrate well with our site & static docs
|
||||
> > - using two docs systems increases complexity
|
||||
> > - dev docs in the wiki are too far from the code, and compete with READMEs
|
||||
>
|
||||
> PS:
|
||||
>
|
||||
> - Why not go back to just one repo for everything ? Or if two repos, why not put all docs in one of them ?
|
||||
>
|
||||
> Dev docs are most discoverable and maintainable right there in the main repo, ie as READMEs. Likewise for API docs (haddocks) and the reference manuals (hledger*/hledger*m4.md). We want all of these updated in lock step with code/tooling changes.
|
||||
>
|
||||
> Other ("soft") docs are needed, but these have a more relaxed process, schedule, and scope (eg bookkeeping advice). They occasionally generate a lot of noise in the commit log, and I think it's a good to keep that out of the code history. The website (home and other pages, site design, site infrastructure) generates similar commit storms and is somewhat independent of code, so it goes in the soft docs repo too.
|
||||
>
|
||||
> These are my thoughts, but I have an open mind if you see a better way.
|
||||
>
|
||||
> me (Simon Michael (sm) change)
|
||||
> 10/27/18
|
||||
> Still plenty of time to discuss and reconsider, but see also
|
||||
> https://github.com/simonmichael/hledger/issues/920
|
||||
> https://github.com/simonmichael/hledger/issues/921
|
||||
>
|
||||
> I'll probably make a start on the first one (consolidating dev docs in main repo).
|
||||
@ -1,4 +1,4 @@
|
||||
FROM haskell:9.12.2 AS dev
|
||||
FROM haskell as dev
|
||||
|
||||
RUN mkdir /root/hledger
|
||||
WORKDIR /root/hledger
|
||||
@ -21,11 +21,11 @@ RUN stack install
|
||||
|
||||
FROM debian:stable-slim
|
||||
|
||||
RUN apt-get update && apt-get -y install libtinfo6 libgmp10 && rm -rf /var/lib/apt/lists
|
||||
RUN apt-get update && apt-get install libtinfo5 libgmp10 && rm -rf /var/lib/apt/lists
|
||||
|
||||
COPY --from=dev /root/.local/bin/hledger* /usr/bin/
|
||||
|
||||
ENV LC_ALL=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN mkdir /data && touch /data/hledger.journal
|
||||
VOLUME /data
|
||||
|
||||
@ -12,8 +12,8 @@ The numbers describe the number of transactions, number of accounts, and maximum
|
||||
They are generated by [`tools/generatejournal.hs`](https://github.com/simonmichael/hledger/blob/master/tools/generatejournal.hs).
|
||||
They should get built automatically as needed, if not you can use `make samplejournals`:
|
||||
|
||||
```cli
|
||||
$ just samplejournals
|
||||
```shell
|
||||
$ make samplejournals
|
||||
ghc tools/generatejournal.hs
|
||||
[1 of 1] Compiling Main ( tools/generatejournal.hs, tools/generatejournal.o )
|
||||
Linking tools/generatejournal ...
|
||||
61
FINANCE.md
Normal file
61
FINANCE.md
Normal file
@ -0,0 +1,61 @@
|
||||
# Finance
|
||||
|
||||
<div class=pagetoc>
|
||||
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
<https://hledger.org/finance> this page
|
||||
<https://github.com/simonmichael/hledger_finance> finance repo
|
||||
|
||||
Old:
|
||||
|
||||
## Funding
|
||||
|
||||
My vision for the hledger project has always been for it to be "accountable" and "self-sustaining", possibly through new forms of incentivisation.
|
||||
Classic non-monetary FOSS communities are a beautiful and precious thing.
|
||||
Adding money can change their dynamic.
|
||||
Yet, we would enjoy having a lot more issues resolved, and a faster rate of progress.
|
||||
So we experiment, gently.
|
||||
|
||||
Currently we use bounties as a way to encourage resolution of issues.
|
||||
There are a few ways to do this:
|
||||
|
||||
1. You or your organisation can offer a bounty simply by saying so on the issue.
|
||||
|
||||
2. You can use Bountysource. A few hledger bounties have been completed there.
|
||||
|
||||
3. You can use the new Open Collective process below.
|
||||
|
||||
Issues with bounties of any kind are marked with the `bounty` label.
|
||||
The Bounty Manager is @simonmichael.
|
||||
|
||||
## New bounty process
|
||||
|
||||
It currently looks like this, and will evolve:
|
||||
|
||||
- Issues are marked as bounties by @simonmichael. Feel free to suggest additional issues which should receive the bounty label.
|
||||
|
||||
- Bounties are paid from the hledger project's public Open Collective fund.
|
||||
By contributing to the fund as an individual or organisation, you enable more bounties.
|
||||
|
||||
- These OC bounties (unlike 1 and 2 above) have standard amounts.
|
||||
These may be adjusted over time, depending eg on the state of our funds.
|
||||
Our current bounty amounts are
|
||||
- level 1: 10 USD
|
||||
- level 2: 25 USD
|
||||
- level 3: 50 USD
|
||||
|
||||
- When you complete a bounty, submit an expense to Open Collective,
|
||||
for whichever of the above bounty amounts you think appropriate,
|
||||
based eg on time or expertise spent, how much you need it,
|
||||
how much remains in our fund for other bounties, etc.
|
||||
This will be reviewed by OC and (maybe ?) @simonmichael.
|
||||
Successful claims, like donations, will appear in our public OC ledger.
|
||||
|
||||
Our bounty amounts are small, and nothing like professional rates in most countries,
|
||||
but they still establish a principle of sustainability,
|
||||
and help us to experiment.
|
||||
You are encouraged to claim your bounties,
|
||||
though you can also choose to transfer them to a new issue of your choice.
|
||||
|
||||
97
ISSUES.md
Normal file
97
ISSUES.md
Normal file
@ -0,0 +1,97 @@
|
||||
# Issues
|
||||
|
||||
<div class=pagetoc>
|
||||
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
The hledger project\'s issue tracker is on github. It contains:
|
||||
|
||||
- BUG issues - failures in some part of the hledger project (the main
|
||||
hledger packages, docs, website..)
|
||||
- WISH issues - feature proposals, enhancement requests
|
||||
- uncategorised issues - we don\'t know what these are yet
|
||||
- pull requests - proposed changes to code and docs
|
||||
|
||||
Issues are also labelled according to their [topics](#topics), for organisation.
|
||||
|
||||
Some loose conventions:
|
||||
|
||||
- In bug titles, mention the hledger version in which the bug first appeared
|
||||
(and avoid mentioning version numbers otherwise).
|
||||
This allows searches like
|
||||
[new issues in 1.22](https://github.com/simonmichael/hledger/issues?q=in%3Atitle+1.22+)
|
||||
and
|
||||
[regressions in 1.22](https://github.com/simonmichael/hledger/issues?q=in%3Atitle+1.22+label%3Aregression%21)
|
||||
|
||||
|
||||
## Issue Urls
|
||||
|
||||
- <http://bugs.hledger.org> - show open BUG issues
|
||||
- <http://wishes.hledger.org> - show open WISH issues
|
||||
- <http://issues.hledger.org> - show all issues, open or closed
|
||||
- <http://prs.hledger.org> - show open pull requests
|
||||
- <http://bugs.hledger.org/new> - create a new issue
|
||||
|
||||
## Labels
|
||||
|
||||
Labels are used to categorise:
|
||||
|
||||
- the issue\'s type: \"A BUG\" or \"A WISH\", in shades of red (The A
|
||||
makes it appear as first label)
|
||||
- relevant subsystems/topics, in light blue. More about this below.
|
||||
- relevant platforms, in light purple
|
||||
- resolution if not fixed:
|
||||
\"closed:cant-reproduce/duplicate/invalid/wont-fix\", in dark grey
|
||||
- \"bounty\", in bright yellow: issues with bountysource funding
|
||||
- \"easy?\", in dim yellow: issues which are probably relatively easy
|
||||
to fix
|
||||
- \"imported\" etc., in white: miscellaneous information
|
||||
|
||||
## Topics
|
||||
|
||||
Short topic names, corresponding to hledger commands, input formats, output formats and other common themes,
|
||||
are used to organise things in the hledger project. In particular,
|
||||
|
||||
- They are used as space saving descriptive prefixes for [commit messages](#commit-messages)
|
||||
- They can be used as prefixes for issue/PR titles
|
||||
- Issues and PRs are labelled with them (the light blue labels).
|
||||
|
||||
A more or less complete list can be seen at [open issues](#open-issues)
|
||||
or in the issue tracker's labels list.
|
||||
|
||||
## Custodians
|
||||
|
||||
If you are interested in helping with a particular component for a
|
||||
while, please add yourself as a custodian in Open Issues table above.
|
||||
A custodian\'s job is to help manage the issues, rally the troops, and
|
||||
drive the open issue count towards zero. The more custodians, the
|
||||
better! By dividing up the work this way, we can scale and make forward
|
||||
progress.
|
||||
|
||||
## Milestones and Projects
|
||||
|
||||
Milestones are used a little bit to plan releases. In 2017 we
|
||||
experimented with projects, but in 2018 milestones are in favour again..
|
||||
|
||||
## Estimates
|
||||
|
||||
You might see some experiments in estimate tracking, where some issue
|
||||
names might have a suffix noting estimated and spent time. Basic format:
|
||||
\[ESTIMATEDTOTALTASKTIME\|TIMESPENTSOFAR\]. Examples: \`\`\` \[2\] two
|
||||
hours estimated, no time spent \[..\] half an hour estimated (a dot is
|
||||
\~a quarter hour, as in timedot format) \[1d\] one day estimated (a day
|
||||
is \~4 hours) \[1w\] one week estimated (a week is \~5 days or \~20
|
||||
hours) \[3\|2\] three hours estimated, about two hours spent so far
|
||||
\[1\|1w\|2d\] first estimate one hour, second estimate one week, about
|
||||
two days spent so far \`\`\` Estimates are always for the total time
|
||||
cost (not time remaining). Estimates are not usually changed, a new
|
||||
estimate is added instead. Numbers are very approximate, but better than
|
||||
nothing.
|
||||
|
||||
## Trello
|
||||
|
||||
The [trello board](http://trello.hledger.org) (trello.hledger.org) is an
|
||||
old collection of wishlist items. This should probably be considered
|
||||
deprecated.
|
||||
|
||||
8
LICENSE
8
LICENSE
@ -1,7 +1,7 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
40
MAKE.md
Normal file
40
MAKE.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Make
|
||||
|
||||
A Makefile is provided to make common developer tasks easy to remember,
|
||||
and to insulate us a little from the ever-evolving Haskell tools ecosystem.
|
||||
Using it is entirely optional, but recommended.
|
||||
You'll need [GNU Make](https://www.gnu.org/software/make) installed.
|
||||
|
||||
The Makefile contains a fair amount of obsolete cruft and needs cleanup. Some tasks (docs, website) are now handled by the [Shake](#shake) file instead.
|
||||
|
||||
The Makefile is self-documenting. Run `make` to see a list of the main make rules:
|
||||
|
||||
```shell
|
||||
$ make
|
||||
Makefile:37: -------------------- hledger make rules --------------------
|
||||
Makefile:39: make [help] -- list documented rules in this makefile. make -n RULE shows more detail.
|
||||
Makefile:204: (INSTALLING:)
|
||||
Makefile:206: make install -- download dependencies and install hledger executables to ~/.local/bin or equivalent (with stack)
|
||||
Makefile:231: (BUILDING:)
|
||||
Makefile:235: make build -- download dependencies and build hledger executables (with stack)
|
||||
Makefile:304: make hledgerdev -- quickly build the hledger executable (with ghc and -DDEVELOPMENT)
|
||||
...
|
||||
```
|
||||
|
||||
To see what a make rule will do without actually doing it, use the `-n` flag:
|
||||
|
||||
```shell
|
||||
$ make build -n
|
||||
stack build
|
||||
```
|
||||
```shell
|
||||
$ make test -n
|
||||
(stack test \
|
||||
&& echo pkgtest PASSED) || echo pkgtest FAILED
|
||||
(stack exec hledger test \
|
||||
&& echo builtintest PASSED) || echo builtintest FAILED
|
||||
(COLUMNS=80 PATH=`pwd`/bin:/home/simon/src/hledger/bin:/home/simon/.local/bin:/home/simon/.cabal/bin:/opt/ghc/7.10.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/var/lib/gems/1.9.1/bin stack exec -- shelltest --execdir -- -j16 --hide-successes tests \
|
||||
&& echo functest PASSED) || echo functest FAILED
|
||||
```
|
||||
|
||||
|
||||
@ -5,21 +5,6 @@
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
Shortcut urls:
|
||||
|
||||
- <http://prs.hledger.org>
|
||||
- <http://draftprs.hledger.org>
|
||||
- <http://readyprs.hledger.org>
|
||||
- <http://assignedprs.hledger.org>
|
||||
- <http://unassignedprs.hledger.org>
|
||||
|
||||
<!--
|
||||
Misc. PR queries:
|
||||
|
||||
- ...
|
||||
-->
|
||||
|
||||
|
||||
Most contributed hledger code (and some of the project maintainer's code)
|
||||
is submitted and reviewed via Github pull requests.
|
||||
Here are some tips for contributing PRs to hledger.
|
||||
@ -29,16 +14,15 @@ Here are some tips for contributing PRs to hledger.
|
||||
We aim to improve and sustain hledger's quality and maintainability over the long term.
|
||||
|
||||
Many PRs, especially small ones, and even some big ones, can be merged quickly.
|
||||
We love merging PRs quickly.
|
||||
We love merging good PRs quickly.
|
||||
|
||||
Some bigger or more risky PRs can require substantial review, discussion, changes, or re-submission.
|
||||
Sometimes this is a bigger task than the coding.
|
||||
Much valuable design, quality control, and knowledge sharing happens at this time.
|
||||
|
||||
Some PRs ultimately get rejected, but their discussion and exploration can still be a useful contribution.
|
||||
Some PRs get rejected, but their discussion and exploration can still be a useful contribution.
|
||||
We very much want to avoid wasted work, but it occasionally happens.
|
||||
Our process is evolving and imperfect.
|
||||
All of this is a normal part of software development.
|
||||
All of this is normal.
|
||||
|
||||
We hope you'll see it as a golden opportunity to collaborate with experts,
|
||||
share and receive knowledge, refine your design/documentation/code,
|
||||
@ -54,10 +38,6 @@ Smaller/more focussed PRs can be reviewed quicker and accepted (or rejected) qui
|
||||
|
||||
Consider showing a draft of documentation first (more on this below).
|
||||
|
||||
When you are not ready for the PR to be merged, please make it a Draft PR.
|
||||
(Non-draft means "I think this is ready, you can merge any time".)
|
||||
And use a normal PR title, ie don't write "WIP:" or "Draft:" in the title.
|
||||
|
||||
## The commit(s)
|
||||
|
||||
Commits should be easy to review.
|
||||
@ -90,10 +70,9 @@ Rebase your commits against latest master for easiest review. Especially if they
|
||||
|
||||
We like to use some conventions in commit messages when it makes sense. These aren't mandatory, but appreciated:
|
||||
|
||||
- prepend a [topic label](ISSUES.md#labels) prefix, eg `cli: ` or `journal: `, for clarity and to help with changelog production
|
||||
- prepend a semicolon (`;`) to indicate commits that
|
||||
- need not trigger a CI workflows, reducing wasteful carbon emissions
|
||||
- and probably need not be mentioned in changelogs/release notes
|
||||
- prepend a [topic](#topics) prefix, eg `cli: ` or `journal: `, for clarity and to help with changelog production
|
||||
- prepend a semicolon (`;`) to indicate commits that need not be mentioned in changelogs/release notes (as in the Emacs project)
|
||||
- append a final `[ci skip]` line to indicate commits that need not trigger a CI build, to reduce carbon emissions from Travis.
|
||||
|
||||
## The docs
|
||||
|
||||
47
README.md
47
README.md
@ -4,24 +4,9 @@
|
||||
[](https://hackage.haskell.org/package/hledger)
|
||||
[](https://repology.org/metapackage/hledger)
|
||||
[](https://repology.org/metapackage/hledger)
|
||||
\
|
||||
[](https://gitscope.dev/docs/badges)
|
||||
[](https://gitscope.dev/docs/badges)
|
||||
[](https://gitscope.dev/docs/badges)
|
||||
[](https://hledger.org/CREDITS.html)
|
||||
\
|
||||
[](https://hledger.org/doc.html)
|
||||
[](https://github.com/simonmichael/hledger/issues?q=is:issue+state:open)
|
||||
[](https://github.com/simonmichael/hledger/issues?q=is:issue+label:A-BUG+state:open)
|
||||
[](https://github.com/simonmichael/hledger/issues?q=is:issue+label:A-WISH+state:open)
|
||||
[](https://github.com/simonmichael/hledger/issues?q=is:issue+state:closed)
|
||||
[](http://bugs.hledger.org)
|
||||
|
||||
<!--
|
||||
[](https://hledger.org/CONTRIBUTING.html)
|
||||
[](https://hledger.org/ISSUES.html)
|
||||
-->
|
||||
|
||||
Welcome! This is a brief intro to hledger. For a more detailed version, see the home page: **<https://hledger.org>**
|
||||
Welcome! This a brief intro to hledger. For a more detailed version, see the home page: **<https://hledger.org>**
|
||||
|
||||
hledger is lightweight, cross platform, multi-currency, double-entry accounting software.
|
||||
It lets you track money, investments, cryptocurrencies, invoices, time, inventory and more,
|
||||
@ -49,7 +34,7 @@ More features:
|
||||
- Inspired by and partly compatible with Ledger CLI; interconvertible with Beancount
|
||||
- Scriptable by CLI, HTTP or API, with plenty of examples
|
||||
- Clean Haskell codebase, continually improved since 2007, with $100 regression bounties
|
||||
- Free software licensed under GNU General Public License v3.0 or later.
|
||||
- Free software licensed under GPLv3+.
|
||||
|
||||
## Examples
|
||||
|
||||
@ -128,7 +113,7 @@ More examples and screenshots: <https://hledger.org/#how-to-get-started>
|
||||
|
||||
hledger is brought to you by
|
||||
[Simon Michael](http://joyful.com),
|
||||
[140+ contributors](doc/CREDITS.md),
|
||||
[140+ contributors](CREDITS.md),
|
||||
and the generous financial sponsors below.
|
||||
|
||||
After enjoying some personal or organisational success with hledger,
|
||||
@ -159,17 +144,6 @@ It's easy! Please see <https://hledger.org/sponsor.html> for details.
|
||||
<a href="https://opencollective.com/hledger/organization/17/website"><img src="https://opencollective.com/hledger/organization/17/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/18/website"><img src="https://opencollective.com/hledger/organization/18/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/19/website"><img src="https://opencollective.com/hledger/organization/19/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/20/website"><img src="https://opencollective.com/hledger/organization/20/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/21/website"><img src="https://opencollective.com/hledger/organization/21/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/22/website"><img src="https://opencollective.com/hledger/organization/22/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/23/website"><img src="https://opencollective.com/hledger/organization/23/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/24/website"><img src="https://opencollective.com/hledger/organization/24/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/25/website"><img src="https://opencollective.com/hledger/organization/25/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/26/website"><img src="https://opencollective.com/hledger/organization/26/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/27/website"><img src="https://opencollective.com/hledger/organization/27/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/28/website"><img src="https://opencollective.com/hledger/organization/28/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/29/website"><img src="https://opencollective.com/hledger/organization/29/avatar.svg?avatarHeight=200"></a>
|
||||
<a href="https://opencollective.com/hledger/organization/30/website"><img src="https://opencollective.com/hledger/organization/30/avatar.svg?avatarHeight=200"></a>
|
||||
|
||||
### Individual sponsors
|
||||
|
||||
@ -213,16 +187,5 @@ It's easy! Please see <https://hledger.org/sponsor.html> for details.
|
||||
<a href="https://opencollective.com/hledger/individual/37/website"><img src="https://opencollective.com/hledger/individual/37/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/38/website"><img src="https://opencollective.com/hledger/individual/38/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/39/website"><img src="https://opencollective.com/hledger/individual/39/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/40/website"><img src="https://opencollective.com/hledger/individual/40/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/41/website"><img src="https://opencollective.com/hledger/individual/41/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/42/website"><img src="https://opencollective.com/hledger/individual/42/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/43/website"><img src="https://opencollective.com/hledger/individual/43/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/44/website"><img src="https://opencollective.com/hledger/individual/44/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/45/website"><img src="https://opencollective.com/hledger/individual/45/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/46/website"><img src="https://opencollective.com/hledger/individual/46/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/47/website"><img src="https://opencollective.com/hledger/individual/47/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/48/website"><img src="https://opencollective.com/hledger/individual/48/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/49/website"><img src="https://opencollective.com/hledger/individual/49/avatar.svg?avatarHeight=100"></a>
|
||||
<a href="https://opencollective.com/hledger/individual/50/website"><img src="https://opencollective.com/hledger/individual/50/avatar.svg?avatarHeight=100"></a>
|
||||
|
||||
<!-- (If your logo/avatar isn't appearing here, eg because you didn't use Open Collective, please [let me know](mailto:webmaster@hledger.org).) -->
|
||||
If your logo/avatar needs to be added, [let me know](mailto:webmaster@hledger.org)!
|
||||
|
||||
407
RELEASING.md
Normal file
407
RELEASING.md
Normal file
@ -0,0 +1,407 @@
|
||||
# Releasing
|
||||
|
||||
<div class=pagetoc>
|
||||
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
Notes for hledger release managers and maintainers.
|
||||
|
||||
## Goals
|
||||
|
||||
### 2022
|
||||
- Update/consolidate release process docs
|
||||
- Establish routine monthly release cadence
|
||||
- Make releasing easy
|
||||
|
||||
## Release types
|
||||
| | Major release<br>A.B | Bugfix release<br>A.B.C | Fixup release<br>A.B.C.D | Preview release<br>A.B.99.D |
|
||||
|-----------------------|--------------------------------|------------------------------|----------------------------------------------|------------------------------------------|
|
||||
| **Contains:** | New features, breaking changes | Only bug fixes | Trivial packaging fixes, no software changes | Early snapshot of the next major release |
|
||||
| **When:** | Third month of quarter: March, June, September, December | When needed | Never | First & second months of quarter |
|
||||
| | | | | |
|
||||
| **Deliverables:** | | | | |
|
||||
| Changelogs | ✓ | ✓ | ✓ | ✓ |
|
||||
| Github release | ✓ | ✓ | ✓ | ✓ |
|
||||
| Binaries | ✓ | ✓ | ✓ | ✓ |
|
||||
| Hackage release | ✓ | ✓ | ✓ | |
|
||||
| Install page | ✓ | ✓ | ✓ | |
|
||||
| hledger-install | ✓ | ✓ | ✓ | |
|
||||
| [Regression bounty] | ✓ | ✓ | ✓ | |
|
||||
| Release notes | ✓ | ✓ | | |
|
||||
| Web manuals | ✓ | | | |
|
||||
| Announcements | ✓ | | | |
|
||||
|
||||
[Regression bounty]: http://hledger.org/regressionbounty
|
||||
|
||||
hledger major releases happen in the third month of each quarter, normally at or close to the start of the month.
|
||||
Preview releases happen in the other months, if needed.
|
||||
Here's the ideal release schedule:
|
||||
|
||||
| Q1 | Q2 | Q3 | Q4 |
|
||||
|------------------|------------------|------------------|------------------|
|
||||
| Jan 1: preview 1 | Apr 1: preview 1 | Jul 1: preview 1 | Oct 1: preview 1 |
|
||||
| Feb 1: preview 2 | May 1: preview 2 | Aug 1: preview 2 | Nov 1: preview 2 |
|
||||
| Mar 1: major | Jun 1: major | Sep 1: major | Dec 1: major |
|
||||
|
||||
|
||||
## Glossary
|
||||
Here are some definitions, useful eg when executing or automating release procedures.
|
||||
|
||||
| | |
|
||||
|-------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| | **General concepts** |
|
||||
| *release* | A snapshot of the software and related artifacts like executable binaries, which is named, tagged, documented, announced, and usually picked up by packaging systems on various platforms. |
|
||||
| *version control system, VCS* | A tool used for storing and sharing and viewing the history and different lines of development of a software project, or other set of files. hledger uses Git. |
|
||||
| *repository, repo* | A set of files being stored and managed by a VCS. Often published on a *repository hosting service*, such as Github. |
|
||||
| *working copy, clone* | A local copy of a repository's files. Typically each developer has one or more of these, and can share changes easily with the official public repository. |
|
||||
| *branch* | Some VCS's, including Git, can store multiple branching lines of development within one repository. A working copy can be quickly switched to a different branch to show its content. |
|
||||
| *master, main* | The main branch in a repo, usually named `master` or `main`. Pull requests are usually relative to this. |
|
||||
| *pull request, PR* | A request to merge a development branch with master, and any related discussion. On Github, these are kept alongside issues in the issue tracker. |
|
||||
| *continuous integration, CI* | Automated actions that run when new code is pushed to a shared repo, such as running tests or producing binaries. On Github this is called Github Actions and action scripts are called *workflows*. |
|
||||
| | **hledger concepts** |
|
||||
| *package* | A releasable unit of Haskell software. hledger has several core packages usually released together: hledger-lib, hledger, hledger-ui, hledger-web. |
|
||||
| *hledger version number* | A 2-4 part dotted number naming a hledger release or hledger package version: `MA.JOR[.MINOR[.FIXUP]]` or `MA.JOR.99[.PREVIEW]` where 99 means "unreleased (MAJOR+1)". See examples below. |
|
||||
| *hledger version string* | A line of text describing a hledger binary, shown by `--version`. It contains program name, version number, commit hash and date, machine architecture etc. Eg: `hledger 1.24.1-g7799d526b-20211210, mac-x86_64` |
|
||||
| *Complete, partial, mixed releases* | A release of all the core hledger packages (hledger-lib, hledger, hledger-ui, hledger-web) is called *complete*. A release of only some of the core packages is called *partial*. A release where some packages have different versions (because of a previous partial release) is called *mixed*. Major and preview releases are always complete, bugfix and fixup releases can be partial and/or mixed. |
|
||||
| *changelog* | A CHANGES.md file listing the release history and the changes in each release. There is one for each hledger package and one for the hledger project as a whole. |
|
||||
| *release notes* | The Release Notes page on the hledger website: the combined release history of the core hledger packages, showing user visible changes only. |
|
||||
| | **hledger release/build types** |
|
||||
| *Major release* | Major releases include new features and incompatible API changes, and normally happen at the start of each quarter's third month (3/1, 6/1, 9/1, 12/1). Example version number: `1.25` |
|
||||
| *Bugfix release* | Bugfix releases include only bug fixes, without API changes. These happen when needed, to fix significant bugs in the previous major release. Example version number: `1.25.2` (*"second bugfix release for 1.25"*) |
|
||||
| *Fixup release* | Fixup releases fix packaging errors, with no changes to the hledger software. These should be rare. Example version number: `1.25.0.1` or `1.25.2.1` (*"first fixup release for 1.25 / 1.25.2"*) |
|
||||
| *Preview release* | A preview of the upcoming major release for testers/early adopters, and a test of the release process, published on Github. Not a formal hledger release, eg not published on Hackage, usually not packaged, no bugfix releases, no regression bounties, not shown in release notes. These typically appear in the quarter's first and second month if needed. Example version number: `1.25.99.1` (*"preview 1 of 1.26"*) |
|
||||
| *CI binaries* | Temporary downloadable binaries produced by a run of the `linux`/`mac`/`windows` workflows in the hledger repo. This may happen periodically, eg weekly. Downloading requires a Github login. |
|
||||
| *Dev build* | A local developer build of unreleased code. This is typically in `master` or a development/PR branch. Example version number: `1.25.99` (*"unreleased 1.26-dev"*) |
|
||||
| | **hledger repos and branches** |
|
||||
| *hledger repo* | The `hledger` git repository, containing the hledger software, reference manuals, and developer docs. <https://github.com/simonmichael/hledger> |
|
||||
| *site repo* | The `hledger_website` git repository, containing most of the hledger website which appears at <https://hledger.org>. Usually checked out under the hledger repo as `site/`. <https://github.com/simonmichael/hledger_website> |
|
||||
| *master* | The branch named `master` in the hledger repo; the main line of hledger development. Pull requests are usually relative to this. |
|
||||
| *release branch* | Branches named `MA.JOR-branch` in the hledger repo, eg `1.25-branch`. Releases and release previews are always made from a release branch. |
|
||||
|
||||
|
||||
## Activities
|
||||
Release manager activities/responsibilities include:
|
||||
- **Software** - selecting changes, packages, release dates; coordinating contributions; ensuring release readiness
|
||||
- **Branch Management** - coordinating main and release branch, local and remote repos, CI branches
|
||||
- **Version Bumping** - choosing and applying new version numbers and related things like tags, github releases, urls, ghc and dep versions, stackage resolvers, everywhere needed
|
||||
- **Docs** - command help, manuals, changelogs, release notes, github release notes, install page, install scripts, announcements, process docs
|
||||
- **Testing** - local testing, CI testing, extra release-specific testing
|
||||
- **Artifacts** - generating binaries, zip files, github releases etc.
|
||||
- **Publishing** - uploading, pushing, making visible, finalising
|
||||
- **Announcing** - various announcement stages and channels
|
||||
|
||||
These have complex interdependencies and sequencing constraints. Chunk, separate, routinise, document and automate them as far as possible.
|
||||
|
||||
## General tips
|
||||
- Update changelogs early and often, eg during/after a PR, to spread the work.
|
||||
See also [CHANGELOGS](CHANGELOGS.html).
|
||||
- Release (or practice releasing) often.
|
||||
- Follow RELEASING.md's procedures if helpful. Update a copy (RELEASING2.md) while releasing.
|
||||
- The release process continually evolves. Don't document procedures in too much detail / prematurely.
|
||||
- Make things a little better each time through: simpler, more reliable, better documented, more automated, easier, faster, cheaper, higher quality.
|
||||
- Make releases from a release branch, not from master. Use the tools/release script.
|
||||
- Before publishing a github release: prepare binaries, release notes, announcements, and tag.
|
||||
- Before tagging: make binaries for all platforms, from the same commit.
|
||||
- Before making binaries: do all possible pre-tagging steps and try to get everything finalised. (Binaries' --version shows their git hash, and this should match the release tag.)
|
||||
|
||||
## Procedures
|
||||
|
||||
### Do a release
|
||||
- save RELEASING.md as RELEASING2.md
|
||||
- [check release readiness](#check-release-readiness)
|
||||
- start making draft binaries: push to `origin/binaries`, resolve failures
|
||||
- update changelogs: see CHANGELOGS.md
|
||||
- [make release notes](#make-release-notes)
|
||||
- choose version: MA.JOR, MA.JOR.MINOR, or MA.JOR.MINOR.FIXUP
|
||||
- [prepare release branch](#prepare-release-branch) (preview/major release)
|
||||
or cherry pick changes from master (bugfix/fixup release)
|
||||
- [make new manuals](#make-new-manuals) (major release)
|
||||
- [update hledger-install](#update-hledger-install) (major/bugfix/fixup release)
|
||||
- [update install page](#update-install-page) (major/bugfix/fixup release)
|
||||
- [make announcement](#make-announcement) (major/bugfix release)
|
||||
- [tag the release](#tag-the-release)
|
||||
- [make release binaries](#make-release-binaries)
|
||||
- [make github release](#make-github-release) draft
|
||||
- upload to hackage: `make hackageupload` (major/bugfix/fixup release)
|
||||
- publish github release
|
||||
- publish website changes: manuals, release notes, install page
|
||||
- [announce release](#announce-release) (major/bugfix release)
|
||||
- move RELEASING2 updates back to RELEASING, commit
|
||||
- [cherry-pick release branch to master](#cherry-pick-release-branch-to-master)
|
||||
- bump master to next version: `./Shake setversion A.BB.99` (major release)
|
||||
|
||||
#### Check release readiness
|
||||
- master's changelogs are up to date (see [CHANGELOGS](CHANGELOGS.html))
|
||||
- master or release branch is ready for release
|
||||
- clean and synced working copy
|
||||
- no pending release-blocking issues/prs
|
||||
- tests pass
|
||||
- Shake is up to date
|
||||
- uses same resolver as stack.yaml
|
||||
- uses any required workarounds in stack.yaml
|
||||
- binary is up to date (`./Shake.hs`)
|
||||
- commit any changes (msg: `tools: shake`)
|
||||
- appropriate timing, release manager availability
|
||||
|
||||
#### Make release notes
|
||||
In site repo:
|
||||
|
||||
- update `src/release-notes.md`
|
||||
- copy template, uncomment
|
||||
- replace date
|
||||
- replace XX with NEW
|
||||
- add new changelog sections, excluding hledger-lib
|
||||
- remove any empty sections
|
||||
- add contributors, `git shortlog -sn OLD..NEW`
|
||||
- add summary (major release) or remove it (bugfix release)
|
||||
- check preview in vs code
|
||||
- commit: `relnotes: NEW`
|
||||
|
||||
#### Prepare release branch
|
||||
- `PAUSE=1 ECHO=1 tools/release prep MA.JOR[.99.PREVIEWNUM]` (eg 1.24.99.1 for 1.25 preview 1)
|
||||
(XXX seems to go wrong without PAUSE`)
|
||||
- cherry pick changes from master
|
||||
- list changes in three side-by-side magit windows
|
||||
- 1. NEW IN MASTER: `l o MAJORVER-branch..master`, `M-x magit-toggle-buffer-lock`, `M-x toggle-window-dedicated` (`C-c D`)
|
||||
- 2. HEAD: regular magit status view
|
||||
- 3. RELEASE BRANCH: `l o MAJORVER-branch`, `M-x magit-toggle-buffer-lock`, `M-x toggle-window-dedicated`
|
||||
- in master window, working from bottom upward, cherry-pick all non-conflicting changes
|
||||
- skip changes already in release branch
|
||||
- skip changelog, command help, and manuals updates
|
||||
- `./Shake cmdhelp -c`
|
||||
- `./Shake manuals -c`
|
||||
- update release changelogs (see [CHANGELOGS](CHANGELOGS.html))
|
||||
- release branch testing
|
||||
- `stack build --test`
|
||||
- `make functest`
|
||||
- `stack exec -- hledger --version`, check version
|
||||
- `stack exec -- hledger help | tail`, check version & date
|
||||
|
||||
#### Make new manuals
|
||||
In site repo:
|
||||
|
||||
- js/site.js: add NEW, update currentrelease
|
||||
- Makefile: add NEW, two places
|
||||
- make snapshot-NEW (after ensuring main repo has been release-tagged)
|
||||
- commit: `current, makefile, site.js: NEW`
|
||||
- push
|
||||
|
||||
#### Update hledger-install
|
||||
- update `hledger-install/hledger-install.sh`
|
||||
- HLEDGER_INSTALL_VERSION
|
||||
- RESOLVER
|
||||
- HLEDGER_*_VERSION
|
||||
- EXTRA_DEPS
|
||||
- test ? `cd; bash ~/src/hledger/hledger-install/hledger-install.sh`
|
||||
- commit: `install: NEW`
|
||||
|
||||
#### Update install page
|
||||
In site repo:
|
||||
|
||||
- update `install.md`
|
||||
- query-replace OLD -> NEW in
|
||||
- "current hledger release"
|
||||
- CI binaries badges/links, including linux-static-arm32v7 if built
|
||||
- "building from source"
|
||||
- stack install command
|
||||
- cabal install command
|
||||
- query-replace OLD-brightgreen -> OLD-red
|
||||
- only after release binaries are built (preferably after release is published):
|
||||
update --version outputs (search: hledger --version)
|
||||
- final output line from `hledger test` (run in terminal for normal speed)
|
||||
- Total count from `make functest`
|
||||
- commit: `download: NEW`
|
||||
|
||||
#### Make announcement
|
||||
In release branch:
|
||||
|
||||
- update `doc/ANNOUNCE` (major release)
|
||||
- summary, contributors from release notes
|
||||
- any other edits
|
||||
- commit: `;doc: announce`
|
||||
|
||||
#### Tag the release
|
||||
- `make tag`
|
||||
|
||||
#### Make release binaries
|
||||
- `tools/release bin`
|
||||
- get all platforms built on the same commit
|
||||
- download binary artifact zip files
|
||||
|
||||
#### Make github release
|
||||
- `git push origin MA.JOR-branch && git push --tags` (or magit `P p`, `P t`)
|
||||
- copy text from previous similar release, https://github.com/simonmichael/hledger/releases
|
||||
- create new release, https://github.com/simonmichael/hledger/releases/new
|
||||
- select release tag (MA.JOR[...])
|
||||
- set title (MA.JOR[...])
|
||||
- paste & replace with new release notes
|
||||
- upload CI binaries
|
||||
- save as draft
|
||||
- github release testing: preview on github, upload to hackage
|
||||
- publish
|
||||
|
||||
#### Announce release
|
||||
- pause; take a break afk; check time and energy
|
||||
- push main repo
|
||||
- push site repo
|
||||
- deploy site changes
|
||||
On hledger.org:
|
||||
- in /etc/caddy/hledger.org:
|
||||
- @oldmanpath: add `path` for NEW
|
||||
- @unversionedmanpath: update to NEW
|
||||
- `systemctl reload caddy`
|
||||
- in main repo, `./Shake webmanuals` to update dev manuals
|
||||
- in site repo, `make`
|
||||
- things to try if site doesn't seem to update ?
|
||||
- make clean all
|
||||
- purge cloudflare cache
|
||||
- browsers might still require shift-reload for a while to see new manuals (safari)
|
||||
- share release notes link and markdown content in #hledger chat
|
||||
- send ANNOUNCE as email announcement
|
||||
- major release: `ANN: hledger NEW` to hledger@googlegroups.com, haskell-cafe@googlegroups.com
|
||||
- bugfix release: brief announcement to hledger@googlegroups.com
|
||||
- condense & tweet at https://twitter.com/simonkwmichael
|
||||
- update last release date on plaintextaccounting.org
|
||||
<!-- - toot at https://fosstodon.org/web/accounts/106304084994827771 ? -->
|
||||
|
||||
#### Cherry-pick release branch to master
|
||||
- switch back to master
|
||||
- update master changelogs, merging final release changelog entries (see [CHANGELOGS](CHANGELOGS.html))
|
||||
- cherry-pick other useful changes, such as `;doc: ANNOUNCE`
|
||||
- after a major release: bump master to new dev version (`./Shake setversion -c A.B.99`)
|
||||
|
||||
### Do post-release followup
|
||||
- monitor packaging status, update install page
|
||||
- docker - expect/merge PR
|
||||
- homebrew - expect badge to update soon
|
||||
- nix - expect `make nix-hledger-version` to update after a few days, find and update to that commit hash
|
||||
- linux distros - once in a while, follow the links & search for newer versions, update
|
||||
- provide support, monitor issues
|
||||
- prepare followup releases if needed
|
||||
- update process docs and tools
|
||||
|
||||
### Update packaging
|
||||
|
||||
#### Update homebrew formula
|
||||
|
||||
1. ref
|
||||
|
||||
1. helpers: chenrui & stack issue commenters on github, Athas on
|
||||
#haskell
|
||||
|
||||
2. <https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request>
|
||||
|
||||
3. doc
|
||||
|
||||
If a URL is specified, the SHA-256 checksum of the new download
|
||||
should also be specified. A best effort to determine the SHA-256
|
||||
and formula name will be made if either or both values are not
|
||||
supplied by the user.
|
||||
|
||||
If a tag is specified, the Git commit revision corresponding to
|
||||
that tag must also be specified.
|
||||
|
||||
Note: this command cannot be used to transition a formula from a
|
||||
URL-and-SHA-256 style specification into a tag-and-revision
|
||||
style specifi- cation, nor vice versa. It must use whichever
|
||||
style specification the for- mula already uses.
|
||||
|
||||
2. update homebrew working copy
|
||||
|
||||
1. cd \~/src/DEVTOOLS/homebrew-core
|
||||
|
||||
2. git reset --hard HEAD\~1 && git fetch origin && git merge
|
||||
origin/master && git push -f
|
||||
|
||||
3. get release tarball checksums
|
||||
|
||||
export V=X.Y; for P in -lib \"\" -ui -web; do curl -sO
|
||||
<https://hackage.haskell.org/package/hledger$P-$V/hledger$P-$V.tar.gz>;
|
||||
done && shasum -a256 \*.gz
|
||||
|
||||
4. update Formula/hledger.rb
|
||||
|
||||
1. update tarball urls, shas
|
||||
|
||||
2. update other version references
|
||||
|
||||
3. maybe update stackage snapshot
|
||||
|
||||
4. possible new process, see:
|
||||
<https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request#create-your-pull-request-from-a-new-branch>
|
||||
|
||||
5. test (if possible without too many mac/brew hassles)
|
||||
|
||||
1. brew audit --strict Formula/hledger.rb \# some tests are
|
||||
post-install, try also after brew upgrade
|
||||
|
||||
2. brew upgrade Formula/hledger.rb -s -n -v \# \[scrub download
|
||||
cache, dry run, verbose\]
|
||||
|
||||
1. super slow, how to speed up ?
|
||||
|
||||
1. comment out stack update
|
||||
|
||||
2. add , \"--stack-root=/Users/simon/.stack\" to stack
|
||||
install \# fails on permissions
|
||||
|
||||
3. brew test Formula/hledger.rb
|
||||
|
||||
6. commit with name \"hledger X.Y\" and description \"Update to
|
||||
hledger X.Y.\"
|
||||
|
||||
5. get merged
|
||||
|
||||
1. git push -f simonmichael
|
||||
|
||||
2. gh pr create -f
|
||||
|
||||
3. monitor: PR CI, PR merge,
|
||||
<https://formulae.brew.sh/formula/hledger> page
|
||||
|
||||
4. ping brew contributors/maintainers if necessary: @chenrui,
|
||||
@carlocab, @SMillerDev
|
||||
|
||||
#### Update nix install command
|
||||
|
||||
1. Wait for the new hledger version to land in nixpkgs
|
||||
|
||||
1. make nix-hledger-version
|
||||
|
||||
2. Find the nixpkgs haskell-packages commit post-dating the hledger
|
||||
release:
|
||||
|
||||
1. make nix-view-commits \#
|
||||
<https://github.com/NixOS/nixpkgs/commits/master/pkgs/development/haskell-modules/hackage-packages.nix>
|
||||
|
||||
3. Test the nix-env install command with that commit hash
|
||||
|
||||
1. if it fails with \"SSL peer certificate or SSH remote key was
|
||||
not OK\"
|
||||
|
||||
1. . *Users/simon*.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
2. or re-install:
|
||||
|
||||
1. curl -sO <https://nixos.org/nix/install>
|
||||
|
||||
2. less install
|
||||
|
||||
3. sh install
|
||||
|
||||
4. . *Users/simon*.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
2. on linux
|
||||
|
||||
3. on mac
|
||||
|
||||
#### Update stackage
|
||||
|
||||
1. update
|
||||
<https://github.com/fpco/stackage/blob/master/build-constraints.yaml>
|
||||
if needed
|
||||
|
||||
2. monitor for new package versions in nightly: check
|
||||
<https://www.stackage.org/package/hledger>
|
||||
|
||||
72
ROADMAP.org
Normal file
72
ROADMAP.org
Normal file
@ -0,0 +1,72 @@
|
||||
* ROADMAP.org
|
||||
#+OPTIONS: -:nil
|
||||
|
||||
Ideas about where the hledger project should be going next. Being
|
||||
listed here suggests a bit of commitment, perhaps even a schedule.
|
||||
|
||||
** Targets
|
||||
*** Next Targets
|
||||
*** Past Targets
|
||||
|
||||
**** hledger 1.19, 2020-09-01
|
||||
account transactions register, stricter/more correct handling of
|
||||
unbalanced multicommodity transactions (#1177), Track & show deposited
|
||||
lots (#1022), Report unrealized capital gains/losses (#1029)
|
||||
**** hledger 1.18, 2020-06-01
|
||||
more effective CI setup, updated home page, quickstart, tutorials
|
||||
etc., negative matching in CSV rules,
|
||||
**** hledger 1.17, 2020-03-01
|
||||
field matching in CSV rules, reduce install hassles with terminfo C
|
||||
lib (?), more import/export options, simple console charts, refreshed
|
||||
home page, faq, tutorials, manuals,
|
||||
**** hledger 1.16, 2019-12-01
|
||||
ghc 8.8 support, more powerful CSV conversion, updated home page, faq,
|
||||
manuals, reduce install hassles with terminfo C lib
|
||||
|
||||
** 2020 Priorities
|
||||
*** Documentation
|
||||
Improve the docs.
|
||||
|
||||
- home & faq
|
||||
- manuals (more discoverable structure of web manuals)
|
||||
- cookbook docs (survey, plan, update)
|
||||
- contrib guide (update, build from readmes)
|
||||
|
||||
*** Effectiveness
|
||||
Improve getting-started experience, just-works quality, practicality,
|
||||
real-world usefulness.
|
||||
|
||||
- ghc 8.8, get back in stackage nightly
|
||||
- install issues (C libs..)
|
||||
- more powerful CSV conversion
|
||||
- fill out holes in feature matrix
|
||||
|
||||
*** Investment
|
||||
Improve suitability for investment tracking
|
||||
([[https://github.com/simonmichael/hledger/issues/1015][#1015]])
|
||||
|
||||
- market price inference from transactions
|
||||
- easy market price fetching
|
||||
- lot tracking
|
||||
- capital gains reporting
|
||||
|
||||
*** Charts
|
||||
Add charts and more visual appeal.
|
||||
|
||||
- console charts, basic bar charts
|
||||
- clarify architecture/UI for charts
|
||||
- graphical charts using Chart/matplotlib/hvega
|
||||
- review/design/add more attractive/colourful output (see eg
|
||||
taskwarrior)
|
||||
|
||||
*** Correctness
|
||||
|
||||
More support for enforcing correctness & accounting rules.
|
||||
|
||||
- account names
|
||||
- commodity symbols
|
||||
- payees
|
||||
- notes/descriptions ?
|
||||
- account lifetimes ?
|
||||
- account balance conditions ?
|
||||
- transaction templates ?
|
||||
13
SHAKE.md
Normal file
13
SHAKE.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Shake
|
||||
|
||||
`Shake.hs` in the top directory complements the Makefile; it is used for some more complex tasks, such as building documentation and the web site.
|
||||
|
||||
Compile it:
|
||||
|
||||
./Shake.hs # or, make Shake
|
||||
|
||||
See help:
|
||||
|
||||
./Shake
|
||||
|
||||
|
||||
405
Shake.hs
405
Shake.hs
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env stack
|
||||
{- stack script --resolver nightly-2025-09-30 --compile
|
||||
{- stack script --resolver nightly-2022-09-01 --compile
|
||||
--extra-include-dirs /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/usr/include/ffi
|
||||
--package base-prelude
|
||||
--package directory
|
||||
@ -14,15 +14,25 @@
|
||||
-- add this to see packages being installed instead of a long silence:
|
||||
--verbosity=info
|
||||
|
||||
Heavy project scripts, with file dependencies, using https://shakebuild.com.
|
||||
See also justfile, Makefile.
|
||||
Also uses tools like:
|
||||
This is one of two collections of maintainer/developer scripts; Makefile is the other.
|
||||
This one, based on shake, provides a stronger programming language and
|
||||
more platform independence. It requires stack and will auto-install
|
||||
the haskell packages above when needed.
|
||||
|
||||
Some of the commands below require additional command-line tools, including:
|
||||
- hpack (same version that's in current stack release)
|
||||
- GNU date (on mac, get it with brew install coreutils)
|
||||
- pandoc, groff, m4, makeinfo, sed, mv, cat, rm
|
||||
- GNU date (on mac: brew install coreutils)
|
||||
- groff
|
||||
- m4
|
||||
- makeinfo
|
||||
- pandoc
|
||||
- sed
|
||||
- mv
|
||||
- cat
|
||||
- rm
|
||||
|
||||
Some things that may be useful when working on this:
|
||||
- https://docs.haskellstack.org/en/stable/topics/scripts
|
||||
- https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter
|
||||
- watch Shake.hs for compile errors: make ghcid-shake
|
||||
- load Shake.hs in GHCI: make ghci-shake
|
||||
- rebuild things when files change with entr (file watcher), eg:
|
||||
@ -50,14 +60,13 @@ import "safe" Safe
|
||||
import "shake" Development.Shake
|
||||
import "shake" Development.Shake.FilePath
|
||||
import "time" Data.Time
|
||||
-- import Debug.Trace
|
||||
-- import "hledger-lib" Hledger.Utils.Debug
|
||||
|
||||
usage =
|
||||
let scriptname = "Shake" in replaceRe [re|/Shake|] ('/':scriptname) $
|
||||
unlines
|
||||
---------------------------------------79--------------------------------------
|
||||
["Shake: for heavier project scripting. See also Justfile"
|
||||
["hledger developer scripts. See also: make help"
|
||||
,"Usage:"
|
||||
,"./Shake.hs [CMD [ARGS]] run CMD, compiling this script first if needed"
|
||||
,"./Shake [CMD [ARGS]] run CMD, using the compiled version of this script"
|
||||
@ -66,11 +75,10 @@ usage =
|
||||
,"./Shake setversion [VER] [PKGS] [-c]"
|
||||
," update versions in source files to */.version or VER"
|
||||
," and update */*.cabal files"
|
||||
,"./Shake hledger-install-version update some version strs in hledger-install"
|
||||
,"./Shake cmddocs [-c] update all hledger's COMMAND.md and COMMAND.txt files,"
|
||||
," used for --help, manuals etc. (run after changing"
|
||||
," COMMAND.md or command options or general options)"
|
||||
,"./Shake manuals [-c] update the packages' embedded info/man/txt manuals"
|
||||
,"./Shake cmdhelp [-c] update hledger CLI commands' help texts"
|
||||
,"./Shake mandates update the date shown in some manual formats"
|
||||
,"./Shake manuals [-c] update all packages' txt/man/info/web manuals"
|
||||
-- ,"./Shake webmanuals update just the web manuals"
|
||||
,"./Shake changelogs [-c] [-n/--dry-run]"
|
||||
," update CHANGES.md files, adding new commits & headings"
|
||||
,"./Shake docs [-c] update all program docs (CLI help, manuals, changelogs)"
|
||||
@ -84,10 +92,8 @@ usage =
|
||||
,""
|
||||
,"See comments in Shake.hs for more detailed descriptions."
|
||||
,"Add -c/--commit to have commands commit their changes."
|
||||
,"Add -B (on its own) to force rebuilding."
|
||||
,"Add -V/-VV/-VVV/-VVVV to see more verbose output."
|
||||
,"Add --skip-commands to try to avoid running external commands"
|
||||
,"(not a true dry run; some cmd calls may still run, code may do IO, etc)."
|
||||
,"Add -V/-VV/-VVV to see more verbose output."
|
||||
,"Add -B, with nothing immediately after it, to force rebuilding."
|
||||
]
|
||||
-- TODO
|
||||
-- ,"./Shake releasebranch create a new release branch, bump master to next dev version (.99)"
|
||||
@ -97,8 +103,9 @@ usage =
|
||||
|
||||
-- groff = "groff -c" ++ " -Wall" -- see "groff" below
|
||||
m4 = "m4 -P"
|
||||
makeinfo = "makeinfo -cASCII_PUNCTUATION=1 --no-split --force --no-warn --no-validate" -- silence makeinfo warnings, comment these to see them
|
||||
makeinfo = "makeinfo --no-split --force --no-warn --no-validate" -- silence makeinfo warnings, comment these to see them
|
||||
pandoc = "pandoc --strip-comments"
|
||||
gitcommit = "git commit --allow-empty"
|
||||
|
||||
-- We should work with both BSD and GNU sed. Tips:
|
||||
-- use [a-z] [0-9] instead of \w \d etc.
|
||||
@ -145,11 +152,9 @@ main = do
|
||||
-- hledger manual also includes the markdown files from here:
|
||||
let commandsdir = "hledger/Hledger/Cli/Commands"
|
||||
commandmds <-
|
||||
sort . filter (not . ("README." `isPrefixOf`) . takeFileName) . filter (".md" `isSuffixOf`) . map (commandsdir </>)
|
||||
filter (not . ("README." `isPrefixOf`) . takeFileName) . filter (".md" `isSuffixOf`) . map (commandsdir </>)
|
||||
<$> S.getDirectoryContents commandsdir
|
||||
let
|
||||
commandmdsnew = map (<.> "new") commandmds
|
||||
commandtxts = map (-<.> "txt") commandmds
|
||||
let commandtxts = map (-<.> "txt") commandmds
|
||||
|
||||
-- Run the shake rule selected by the first command line argument.
|
||||
-- Other arguments and some custom flags are set aside for the rule
|
||||
@ -194,7 +199,7 @@ main = do
|
||||
pkgdirs = packages
|
||||
pkgandprojdirs = "" : pkgdirs
|
||||
cabalfiles = [p </> p <.> "cabal" | p <- packages]
|
||||
changelogs = map (</> "CHANGES.md") pkgdirs ++ ["doc/CHANGES.md"]
|
||||
changelogs = map (</> "CHANGES.md") pkgandprojdirs
|
||||
packagemanversionm4s = [p </> ".version.m4" | p <- packages]
|
||||
packagemandatem4s = [p </> ".date.m4" | p <- packages]
|
||||
|
||||
@ -269,7 +274,6 @@ main = do
|
||||
|
||||
-- Regenerate .cabal files from package.yaml files.
|
||||
-- (used by "cabalfiles" and "setversion")
|
||||
-- XXX should remove old cabal files first, otherwise fails if they were generated with newer hpack
|
||||
let gencabalfiles = do
|
||||
|
||||
-- Update cabal files with stack build.
|
||||
@ -285,14 +289,14 @@ main = do
|
||||
-- It should be the same hpack version that's in current stack, to avoid commit conflicts.
|
||||
forM_ pkgdirs $ \d -> cmd_ (Cwd d) Shell "hpack --no-hash"
|
||||
|
||||
when commit $ commitIfChanged ";cabal: update cabal files" cabalfiles
|
||||
when commit $ do
|
||||
let msg = ";cabal: update cabal files"
|
||||
cmd Shell gitcommit ("-m '"++msg++"' --") cabalfiles
|
||||
|
||||
-- setversion [VER] [PKGS] [-c]
|
||||
-- Update version strings in all packages, or just the ones specified.
|
||||
-- If a version number is provided as first argument, save that in .version files first.
|
||||
-- Then update various source files to match what's in their nearby .version file, such as:
|
||||
-- package.yaml files, .cabal files (regenerating from package.yaml), .version.m4 files.
|
||||
-- With -c, also commit the changes.
|
||||
-- Update version strings in most "source" files to match what's in PKG/.version.
|
||||
-- If a version number is provided as first argument, save that in PKG/.version files first.
|
||||
-- If one or more subdirectories are provided as arguments, save/update only those.
|
||||
-- Also regenerates .cabal files from package.yaml files.
|
||||
-- See also CONTRIBUTING.md > Version numbers.
|
||||
phony "setversion" $ do
|
||||
let
|
||||
@ -307,7 +311,7 @@ main = do
|
||||
Just v -> liftIO $ forM_ specifiedversionfiles $ flip maybeWriteFile (v++"\n")
|
||||
Nothing -> return ()
|
||||
|
||||
-- update source files depending on .version in the specified packages
|
||||
-- update "source" files depending on .version in the specified packages
|
||||
let dependents = map (</> ".version.m4") specifiedpkgs
|
||||
++ map (</> "package.yaml") specifiedpkgs
|
||||
need dependents
|
||||
@ -315,7 +319,7 @@ main = do
|
||||
-- and maybe commit them
|
||||
when commit $ do
|
||||
let msg = unwords [
|
||||
";pkg: set"
|
||||
";pkg: bump"
|
||||
,case dirargs of
|
||||
[] -> "version"
|
||||
ds -> intercalate ", " ds ++ " version"
|
||||
@ -323,31 +327,22 @@ main = do
|
||||
Nothing -> ""
|
||||
Just v -> "to " ++ v
|
||||
]
|
||||
commitIfChanged msg $ specifiedversionfiles ++ dependents
|
||||
cmd Shell gitcommit ("-m '"++msg++"' --") specifiedversionfiles dependents
|
||||
|
||||
gencabalfiles
|
||||
|
||||
-- Update some of the version strings in hledger-install/hledger-install.sh. Manual fixup will be needed.
|
||||
-- Not done by setversion since that is used on master, where the production hledger-install is.
|
||||
phony "hledger-install-version" $ do
|
||||
let versionfile = ".version"
|
||||
let out = "hledger-install/hledger-install.sh"
|
||||
version <- ((headDef (error $ "failed to read " <> versionfile) . words) <$>) $ liftIO $ readFile versionfile
|
||||
cmd_ Shell sed "-i -e" ("'s/(^HLEDGER_INSTALL_VERSION)=.*/\\1='`date +%Y%m%d`'/'") out
|
||||
cmd_ Shell sed "-i -e" ("'s/(^HLEDGER(|_LIB|_UI|_WEB)_VERSION)=.*/\\1="++version++"/'") out
|
||||
|
||||
-- PKG/.version.m4 <- PKG/.version, just updates the _version_ macro
|
||||
"hledger*/.version.m4" %> \out -> do
|
||||
let versionfile = takeDirectory out </> ".version"
|
||||
need [versionfile]
|
||||
version <- ((headDef (error $ "failed to read " <> versionfile) . words) <$>) $ liftIO $ readFile versionfile
|
||||
version <- ((head . words) <$>) $ liftIO $ readFile versionfile
|
||||
cmd_ Shell sed "-i -e" ("'s/(_version_}}, *)\\{\\{[^}]+/\\1{{"++version++"/;'") out
|
||||
|
||||
-- PKG/package.yaml <- PKG/.version, just updates version strings
|
||||
"hledger*/package.yaml" %> \out -> do
|
||||
let versionfile = takeDirectory out </> ".version"
|
||||
need [versionfile]
|
||||
version <- ((headDef (error $ "failed to read " <> versionfile) . words) <$>) $ liftIO $ readFile versionfile
|
||||
version <- ((head . words) <$>) $ liftIO $ readFile versionfile
|
||||
let ma:jor:_ = splitOn "." version
|
||||
nextmajorversion = intercalate "." [ma, show $ read jor+1]
|
||||
|
||||
@ -415,21 +410,20 @@ main = do
|
||||
-- MANUALS
|
||||
|
||||
-- Generate the manuals in plain text, nroff, info, and markdown formats.
|
||||
-- NB you should run "Shake cmddocs" before this, it's not automatic (?)
|
||||
phony "manuals" $ do
|
||||
need $ concat [
|
||||
["mandates"]
|
||||
,nroffmanuals
|
||||
nroffmanuals
|
||||
,infomanuals
|
||||
-- ,[infodir]
|
||||
,txtmanuals
|
||||
,webmanuals
|
||||
]
|
||||
when commit $
|
||||
commitIfChanged ";doc: update embedded manuals" $
|
||||
concat [commandmds, packagemandatem4s, nroffmanuals, infomanuals, infodirentries, txtmanuals] -- infodir
|
||||
when commit $ do
|
||||
let msg = ";doc: update manuals"
|
||||
cmd Shell gitcommit ("-m '"++msg++"' --") packagemandatem4s nroffmanuals infomanuals infodirentries txtmanuals -- infodir
|
||||
|
||||
-- Update the dates to show in man pages, to the current month and year.
|
||||
-- Currently must be run manually when needed.
|
||||
-- Dates are stored in PKG/.date.m4, and are committed along with manuals by Shake manuals -c.
|
||||
phony "mandates" $ do
|
||||
date <- chomp . fromStdout <$> (cmd Shell "date +'%B %Y'" :: Action (Stdout String))
|
||||
@ -476,10 +470,7 @@ main = do
|
||||
-- remove with col -b, but it doesn't as can be seen with groff -V.)
|
||||
-- To get plain text, we run groff's lower-level commands (from -V) and add -cbuo.
|
||||
-- -Wall silences most troff warnings, remove to see them
|
||||
-- XXX eqn complains on nonascii chars, not needed ?
|
||||
-- cmd Shell "tbl" src "| eqn -Tascii | troff -Wall -mandoc -Tascii | grotty -cbuo >" out
|
||||
-- XXX how to silence wide table warnings (generated by tbl, reported by troff) ?
|
||||
cmd Shell "tbl" src "| troff -Wall -mandoc -Tascii | grotty -cbuo >" out
|
||||
cmd Shell "tbl" src "| eqn -Tascii | troff -Wall -mandoc -Tascii | grotty -cbuo >" out
|
||||
|
||||
-- Generate Info manuals suitable for viewing with info, from the .m4.md source.
|
||||
infomanuals |%> \out -> do -- hledger/hledger.info
|
||||
@ -541,30 +532,15 @@ main = do
|
||||
else h
|
||||
-- assume any other .m4.md files in dir are included by this one XXX not true in hledger-lib
|
||||
subfiles <- liftIO $ filter (/= src) . filter (".m4.md" `isSuffixOf`) . map (dir </>) <$> S.getDirectoryContents dir
|
||||
let deps = [src, commonm4, packageversionm4, packagemandatem4] ++ subfiles
|
||||
let deps = [src, commonm4, commandsm4, packageversionm4, packagemandatem4] ++ subfiles
|
||||
need deps
|
||||
when (manual=="hledger") $ need $ commandsm4 : commandmds
|
||||
when (manual=="hledger") $ need commandmds
|
||||
-- add the web page's heading.
|
||||
-- XXX Might be nice to do this atomically with the below, so
|
||||
-- make avoid any double refresh when watch docs with entr/livereload.
|
||||
-- But cmd Shell doesn't handle arguments containing spaces properly.
|
||||
let
|
||||
aboutmsg =
|
||||
["<!-------------------------------------------------------------------------"
|
||||
,"Don't edit this file directly."
|
||||
,"Instead, in the hledger repo's master branch edit the source file, one of:"
|
||||
] <>
|
||||
[" hledger/Hledger/Cli/Commands/commands.m4" | manual=="hledger"] <>
|
||||
[" hledger/Hledger/Cli/Commands/*.md" | manual=="hledger"] <>
|
||||
[" " <> intercalate "\n " deps
|
||||
,""
|
||||
,"If the change needs to be applied to past releases' manuals on hledger.org,"
|
||||
,"see https://hledger.org/DOCS.html, or ask the maintainer to help."
|
||||
,"-------------------------------------------------------------------------->"
|
||||
]
|
||||
liftIO $ writeFile out $ unlines $
|
||||
aboutmsg <>
|
||||
[""
|
||||
liftIO $ writeFile out $ unlines [
|
||||
"<!-- " ++ "Generated by \"Shake webmanuals\" from " ++ unwords deps ++ " -->"
|
||||
,"<div class=\"docversions\"></div>"
|
||||
,""
|
||||
,"# " ++ heading
|
||||
@ -614,105 +590,40 @@ main = do
|
||||
-- This may also update .cabal files from package.yaml files, and/or install haskell deps.
|
||||
phony "build" $ do
|
||||
let
|
||||
args' = drop 1 args
|
||||
pkgs | null args' = packages
|
||||
| otherwise = args'
|
||||
pkgs | null args = packages
|
||||
| otherwise = args
|
||||
sequence_ [ do
|
||||
need $ fromMaybe [] $ lookup pkg embeddedFiles
|
||||
cmd Shell "stack build " pkg :: Action ()
|
||||
| pkg <- pkgs
|
||||
]
|
||||
|
||||
-- Using the current hledger build, run all commands to update their options help in COMMAND.md,
|
||||
-- then regenerate all the COMMAND.txt from COMMAND.md.
|
||||
-- With -c, also commit any changes in the .md and .txt files.
|
||||
-- The hledger build should up to date when running this. XXX how to check ? need ["build"] is circular
|
||||
phony "cmddocs" $ do
|
||||
liftIO $ putStrLn "please ensure the hledger build is up to date. Running all commands..."
|
||||
-- regenerate Hledger/Cli/Commands/*.txt from the .md source files for CLI help
|
||||
phony "cmdhelp" $ do
|
||||
need commandtxts
|
||||
when commit $ commitIfChanged ";doc: update command docs" $ commandmds <> commandtxts
|
||||
when commit $ do
|
||||
let msg = ";doc: update CLI usage texts"
|
||||
cmd Shell gitcommit ("-m '"++msg++"' --") commandtxts
|
||||
|
||||
-- Regenerate Hledger/Cli/Commands/*.txt from the corresponding .md files,
|
||||
-- after first updating the options help within those.
|
||||
commandtxts |%> \out -> do
|
||||
let src = out -<.> "md"
|
||||
liftIO $ putStrLn ("generating " <> out)
|
||||
need [src <.> "new"] -- 1. depend on phony target that updates the options help in src
|
||||
need [src] -- 2. depend on the now updated src
|
||||
need [src]
|
||||
cmd Shell
|
||||
pandoc fromsrcmd src "--lua-filter" "tools/pandoc-dedent-code-blocks.lua" "-t plain" ">" out
|
||||
|
||||
-- -- Update each Hledger/Cli/Commands/*.md, replacing the ```flags block with latest --help output,
|
||||
-- -- or a placeholder if there are no command-specific flags.
|
||||
-- -- For hledger manual and also for cmddocs below.
|
||||
-- -- NB hledger executables should be up to date, see cmddocs
|
||||
-- phony "optdocs" $ do
|
||||
-- need commandmdsnew
|
||||
-- when commit $ commitIfChanged ";doc: update command flag docs" commandmds
|
||||
|
||||
-- hledger/Hledger/Cli/Commands/CMD.md.new: a phony target that updates the ```flags block
|
||||
-- within hledger/Hledger/Cli/Commands/CMD.md with the output of "stack run -- hledger CMD --help".
|
||||
-- If that fails, a warning is printed and it carries on, keeping the old options help.
|
||||
-- NB this needs the hledger build to be up to date, see cmddocs.
|
||||
phonys $ \out ->
|
||||
if not $ "hledger/Hledger/Cli/Commands/" `isPrefixOf` out && ".md.new" `isSuffixOf` out
|
||||
then Nothing
|
||||
else Just $ do
|
||||
let src = dropExtension out
|
||||
need [src]
|
||||
srcls <- fmap lines $ liftIO $ readFileStrictly src
|
||||
let
|
||||
(pre,rest) = break (=="```flags") srcls
|
||||
(_,post) = span (/="```") rest
|
||||
let cmdname = map toLower $ takeBaseName src
|
||||
do
|
||||
let shellcmd = "stack exec -- hledger -h " <> cmdname
|
||||
-- liftIO $ putStrLn $ "running " <> shellcmd <> " to get options help"
|
||||
cmdhelp <- lines . fromStdout <$> (cmd Shell shellcmd :: Action (Stdout String))
|
||||
let
|
||||
cmdflagshelp = takeWhile (not.null) $ dropWhile (/="Flags:") cmdhelp
|
||||
cmdflagshelp'
|
||||
| null cmdflagshelp = ["Flags:","no command-specific flags"]
|
||||
| otherwise = cmdflagshelp
|
||||
liftIO $ writeFile src $ unlines $ concat [pre, ["```flags"], cmdflagshelp', post]
|
||||
-- This is supposed to print the error but otherwise ignore it, making this action a no-op,
|
||||
-- in case hledger is not yet built/runnable.
|
||||
`actionCatch` \(e::C.IOException) -> return ()
|
||||
-- XXX should somehow control the output and elide the verbose "not found on path" errors
|
||||
-- let elide err
|
||||
-- | "path: [" `isInfixOf` err = takeWhile (/='[') err <> "..."
|
||||
-- | otherwise = err
|
||||
-- in \(e::C.IOException) -> liftIO $ hPutStrLn stderr $ elide $ show e -- not used
|
||||
|
||||
-- CHANGELOGS
|
||||
|
||||
-- update all changelogs with latest commits
|
||||
phony "changelogs" $ do
|
||||
need changelogs
|
||||
when commit $ commitIfChanged ";doc: update changelogs" changelogs
|
||||
|
||||
-- [PKG/]CHANGES.md [-n|--dry-run]
|
||||
-- Add any new commit messages to the specified changelog, idempotently.
|
||||
-- Or with -n/--dry-run, just print the new content to stdout.
|
||||
-- Assumptions/requirements:
|
||||
-- 1. All releases nowadays are full releases (including all four packages).
|
||||
-- 2. The changelog's topmost markdown heading text is a release heading like "1.18.1 2020-06-21", or a more recent commit id like "4fffe6e7".
|
||||
-- 3. When a release heading is added to a changelog, a corresponding release tag is also created.
|
||||
phonys (\out -> if out `notElem` changelogs
|
||||
then Nothing
|
||||
else Just $ do
|
||||
let
|
||||
-- shell command to run git log showing short commit hashes.
|
||||
-- In 2024 git is showing 9 digits, 1 more than jj - show 8 for easier interop
|
||||
gitlog = "git log --abbrev=8"
|
||||
-- git log showing short commit hashes
|
||||
gitlog = "git log --abbrev-commit"
|
||||
|
||||
-- a git log format suitable for changelogs/release notes
|
||||
-- git log formats suitable for changelogs/release notes
|
||||
-- %s=subject, %an=author name, %n=newline if needed, %w=width/indent1/indent2, %b=body, %h=hash
|
||||
changelogGitFormat = "--pretty=format:'- %s (%an)%n%w(0,2,2)%b\n'"
|
||||
-- changelogVerboseGitFormat = "--pretty=format:'- %s (%an)%n%w(0,2,2)%b%h' --stat"
|
||||
|
||||
-- shell command to format a git log message with the above format, as a changelog item
|
||||
commitMessageToChangelogItemCmd = unwords [
|
||||
-- Format a git log message, with one of the formats above, as a changelog item
|
||||
changelogCleanupCmd = unwords [
|
||||
sed
|
||||
,"-e 's/^( )*\\* /\1- /'" -- ensure bullet lists in descriptions use hyphens not stars
|
||||
,"-e 's/ \\(Simon Michael\\)//'" -- strip maintainer's author name
|
||||
@ -723,9 +634,9 @@ main = do
|
||||
,"-e '/./,/^$/!d'" -- replace consecutive newlines with one
|
||||
]
|
||||
|
||||
-- Directories to exclude when doing git log for the project changelog.
|
||||
-- https://git-scm.com/docs/gitglossary.html#gitglossary-aiddefpathspecapathspec
|
||||
projectChangelogExcludes = unwords [
|
||||
-- Things to exclude when doing git log for project-wide changelog.
|
||||
-- git exclude pathspecs, https://git-scm.com/docs/gitglossary.html#gitglossary-aiddefpathspecapathspec
|
||||
projectChangelogExcludeDirs = unwords [
|
||||
":!hledger-lib"
|
||||
,":!hledger"
|
||||
,":!hledger-ui"
|
||||
@ -733,54 +644,110 @@ main = do
|
||||
,":!tests"
|
||||
]
|
||||
|
||||
mpkg = if dir=="doc" then Nothing else Just dir where dir = takeDirectory out
|
||||
-- update all changelogs with latest commits
|
||||
phony "changelogs" $ do
|
||||
need changelogs
|
||||
when commit $ do
|
||||
let msg = ";doc: update changelogs"
|
||||
cmd Shell gitcommit ("-m '"++msg++"' --") changelogs
|
||||
|
||||
-- Parse the changelog.
|
||||
-- [PKG/]CHANGES.md
|
||||
-- Add any new non-boring commits to the specified changelog, in
|
||||
-- an idempotent way, minimising manual toil, as follows. We look at:
|
||||
--
|
||||
-- - the changelog's topmost markdown heading, which can be a
|
||||
-- dev heading (first word is a git revision like 4fffe6e7) or
|
||||
-- a release heading (first word is a release version & tag
|
||||
-- like 1.18.1, second word is a date like 2020-06-21) or a
|
||||
-- package release heading (hledger-ui-1.18.1).
|
||||
--
|
||||
-- - the package version, in the adjacent .version file, which
|
||||
-- can be a dev version like 1.18.99 (first two digits of last
|
||||
-- part are 97, 98 or 99) or a release version like 1.18.1
|
||||
-- (any other cabal-style version).
|
||||
--
|
||||
-- The old changelog heading is removed if it was a dev heading;
|
||||
-- new commits in PKG not prefixed with semicolon are added;
|
||||
-- and a suitable new heading is added: a release heading if
|
||||
-- the package version looks like a release version, otherwise
|
||||
-- a dev heading with the current HEAD revision.
|
||||
--
|
||||
-- With -n/--dry-run, print new content to stdout instead of
|
||||
-- updating the changelog.
|
||||
--
|
||||
phonys (\out -> if out `notElem` changelogs
|
||||
then Nothing
|
||||
else Just $ do
|
||||
tags <- lines . fromStdout <$> (cmd Shell "git tag" :: Action (Stdout String))
|
||||
oldlines <- liftIO $ lines <$> readFileStrictly out
|
||||
let
|
||||
(preamble, oldheading:rest) = span isnotheading oldlines where isnotheading = not . ("#" `isPrefixOf`)
|
||||
oldversion = headDef err $ drop 1 $ words oldheading
|
||||
dir = takeDirectory out
|
||||
mpkg | dir=="." = Nothing
|
||||
| otherwise = Just dir
|
||||
(preamble, oldheading:rest) = span isnotheading oldlines
|
||||
where isnotheading = not . ("#" `isPrefixOf`)
|
||||
-- changelog version: a hash or the last release version of this package (or the project)
|
||||
changelogversion = headDef err $ drop 1 $ words oldheading
|
||||
where err = error $ "could not parse changelog heading: "++oldheading
|
||||
-- prepend the package name if we are in a package (not the top-level project directory)
|
||||
maybePrependPackage s = maybe s (++("-"++s)) mpkg
|
||||
toTag = maybePrependPackage
|
||||
isOldRelease rev = isReleaseVersion rev && toTag rev `elem` tags
|
||||
isNewRelease rev = isReleaseVersion rev && toTag rev `notElem` tags
|
||||
-- git revision corresponding to the changelog version:
|
||||
-- a hash (a3f19c15), package release tag (hledger-ui-1.20), or project release tag (1.20)
|
||||
lastrev
|
||||
| isOldRelease changelogversion = toTag changelogversion -- package release tag
|
||||
| isNewRelease changelogversion =
|
||||
trace (out ++ "'s version \""++changelogversion++"\" is not yet tagged, can't list changes")
|
||||
"HEAD"
|
||||
| otherwise = changelogversion
|
||||
|
||||
-- Find the latest commit that has been scanned for this changelog, as a commit id or tag name.
|
||||
lastscannedrev
|
||||
| isCommitHash oldversion = oldversion
|
||||
| otherwise = maybe oldversion (++("-"++oldversion)) mpkg
|
||||
-- interesting commit messages between lastrev and HEAD, cleaned up
|
||||
let
|
||||
interestingpaths = fromMaybe projectChangelogExcludeDirs mpkg
|
||||
-- interestingmessages = "--invert-grep --grep '^;'" -- ignore commits beginning with ;
|
||||
-- TODO: update for new commit conventions. ; now means skip CI,
|
||||
-- feat:/imp:/fix: means release notes, pkg:/lib: means changelogs, etc.
|
||||
interestingmessages = ""
|
||||
newitems <- fromStdout <$>
|
||||
(cmd Shell gitlog changelogGitFormat (lastrev++"..") interestingmessages "--" interestingpaths
|
||||
"|" changelogCleanupCmd :: Action (Stdout String))
|
||||
|
||||
-- Find the latest commit (HEAD).
|
||||
latestrev <- unwords . words . fromStdout <$> (cmd Shell gitlog "-1 --pretty=%h" :: Action (Stdout String))
|
||||
|
||||
-- If it's newer,
|
||||
when (lastscannedrev /= latestrev) $ do
|
||||
|
||||
-- Find the new commit messages relevant to this changelog, and clean them.
|
||||
let scanpath = fromMaybe projectChangelogExcludes mpkg
|
||||
newitems <- fromStdout <$> (cmd Shell
|
||||
"set -o pipefail;" -- so git log failure will cause this action to fail
|
||||
gitlog changelogGitFormat (lastscannedrev++"..") "--" scanpath
|
||||
"|" commitMessageToChangelogItemCmd
|
||||
:: Action (Stdout String))
|
||||
|
||||
-- Add the new heading and change items to the changelog, or print them.
|
||||
let newcontent = "# " ++ latestrev ++ "\n\n" ++ newitems ++ "\n"
|
||||
liftIO $ if dryrun
|
||||
then putStr $ out ++ ":\n" ++ newcontent
|
||||
else do
|
||||
writeFile out $ concat [
|
||||
-- git revision of current HEAD
|
||||
headrev <- unwords . words . fromStdout <$>
|
||||
(cmd Shell gitlog "-1 --pretty=%h -- " interestingpaths :: Action (Stdout String))
|
||||
-- package version: the version number currently configured for this package (or the project)
|
||||
packageversion <-
|
||||
let versionfile = dir </> ".version"
|
||||
err = error $ "could not parse a version in "++versionfile
|
||||
in liftIO $ headDef err . words <$> readFileStrictly versionfile
|
||||
date <- liftIO getCurrentDay
|
||||
let
|
||||
-- the new changelog heading will be a final (dated, versioned) heading if
|
||||
-- the configured package version is a new release version (non-dev & non-tagged)
|
||||
(newrev, newheading)
|
||||
| isNewRelease packageversion = (toTag packageversion, unwords [packageversion, show date])
|
||||
| otherwise = (headrev, headrev)
|
||||
newcontent = "# "++newheading++"\n" ++ newitems
|
||||
newchangelog =
|
||||
unlines preamble
|
||||
,newcontent
|
||||
,"\n"
|
||||
,if isCommitHash oldversion then "" else oldheading
|
||||
,"\n"
|
||||
,unlines rest
|
||||
]
|
||||
putStrLn (out ++ ": updated to " ++ latestrev)
|
||||
++ newcontent
|
||||
++ (if isCommitHash changelogversion then "" else oldheading)
|
||||
++ unlines rest
|
||||
|
||||
liftIO $ if
|
||||
| lastrev == newrev -> pure () -- putStrLn $ out ++ ": up to date"
|
||||
| dryrun -> putStr $ out ++ ":\n" ++ newcontent
|
||||
| otherwise -> do
|
||||
writeFile out newchangelog
|
||||
putStrLn $ out ++ ": updated to " ++ newrev
|
||||
|
||||
)
|
||||
|
||||
-- Update all program-specific docs, eg after setversion.
|
||||
phony "docs" $ need [
|
||||
"cmddocs"
|
||||
"cmdhelp"
|
||||
,"manuals"
|
||||
,"changelogs"
|
||||
]
|
||||
@ -789,28 +756,36 @@ main = do
|
||||
phony "site" $ do
|
||||
need [
|
||||
"webmanuals"
|
||||
,"orgfiles"
|
||||
]
|
||||
cmd_ "make -C site build"
|
||||
|
||||
-- Markdown generated from org files, for the website.
|
||||
-- [ -- "doc/BACKLOG.md"
|
||||
-- ] |%> \out -> do
|
||||
-- let src = out -<.> "org"
|
||||
-- need [src]
|
||||
-- -- replace the generated top heading with our own so we can insert the TOC after it
|
||||
-- let heading = dropExtension out
|
||||
-- mdlines <- drop 1 . lines . fromStdout <$> (cmd Shell pandoc fromorg towebmd src :: Action (Stdout String))
|
||||
-- liftIO $ writeFile out $ unlines $ [
|
||||
-- "<!-- " ++ "Generated by \"Shake " ++ out ++ " from " ++ src ++ " -->"
|
||||
-- ,""
|
||||
-- ,"# " ++ heading
|
||||
-- ,""
|
||||
-- ,"<div class=\"pagetoc\">"
|
||||
-- ,""
|
||||
-- ,"<!-- toc -->"
|
||||
-- ,"</div>"
|
||||
-- ,""
|
||||
-- ] ++ mdlines
|
||||
phony "orgfiles" $
|
||||
need [
|
||||
".BACKLOG.md"
|
||||
,".ROADMAP.md"
|
||||
]
|
||||
|
||||
-- These org files are converted to markdown for the website.
|
||||
[ ".ROADMAP.md"
|
||||
,".BACKLOG.md"
|
||||
] |%> \out -> do
|
||||
let src = drop 1 out -<.> "org"
|
||||
need [src]
|
||||
-- replace the generated top heading with our own so we can insert the TOC after it
|
||||
let heading = dropExtension $ drop 1 out
|
||||
mdlines <- drop 1 . lines . fromStdout <$> (cmd Shell pandoc fromorg towebmd src :: Action (Stdout String))
|
||||
liftIO $ writeFile out $ unlines $ [
|
||||
"<!-- " ++ "Generated by \"Shake " ++ out ++ " from " ++ src ++ " -->"
|
||||
,""
|
||||
,"# " ++ heading
|
||||
,""
|
||||
,"<div class=\"pagetoc\">"
|
||||
,""
|
||||
,"<!-- toc -->"
|
||||
,"</div>"
|
||||
,""
|
||||
] ++ mdlines
|
||||
|
||||
-- XXX try to style backlog items as unnumbered or nested-numbered list items
|
||||
{-
|
||||
@ -860,13 +835,7 @@ main>ol>li {
|
||||
putNormal "Cleaning shake build cache"
|
||||
removeFilesAfter ".shake" ["//*"]
|
||||
|
||||
-- Git commit the given files with the given message if they have changes,
|
||||
-- otherwise print a no change message and continue.
|
||||
commitIfChanged msg files = do
|
||||
diffs <- (/=ExitSuccess) . fromExit <$> cmd Shell "git diff --no-ext-diff --quiet --exit-code --" files
|
||||
if diffs
|
||||
then cmd Shell ("git commit -m '"++msg++"' --") files
|
||||
else liftIO $ putStrLn $ "nothing to commit for \"" ++ msg ++ "\""
|
||||
|
||||
|
||||
-- Convert numbered man page names to manual names.
|
||||
-- hledger.1 -> hledger, hledger_journal.5 -> hledger_journal
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# TESTS
|
||||
# Tests
|
||||
|
||||
<div class=pagetoc>
|
||||
|
||||
@ -99,9 +99,12 @@ About testing in the hledger project, as of 201809.
|
||||
[examples](https://github.com/simonmichael/hledger/blob/master/hledger-lib/Hledger/Read/JournalReader.hs#L579).
|
||||
|
||||
The unit tests are shipped as part of the hledger executable, and
|
||||
can always be run via the [test](https://hledger.org/hledger.html#test)
|
||||
can always be run via the [test](https://hledger.org/manual#test)
|
||||
command (`hledger test`).
|
||||
|
||||
Here\'s the quick way to run unit tests while developing:\
|
||||
`make ghcid-test` or `make ghcid-test-Some.Module`.
|
||||
|
||||
2. Doc tests
|
||||
|
||||
Like unit tests, but defined inside functions\' haddock
|
||||
@ -132,8 +135,16 @@ About testing in the hledger project, as of 201809.
|
||||
|
||||
4. Code tests
|
||||
|
||||
We have some tests aimed at testing eg code quality, generally runnable via just.
|
||||
Eg `just haddocktest`, `just hlinttest`.
|
||||
We have some tests aimed at testing eg code quality, generally
|
||||
defined as make rules, such as:
|
||||
|
||||
--------------------- -------------------------------------------------------------------------------------
|
||||
`make haddocktest` can haddock process all code docs without error
|
||||
`make buildtest` does all code build warning free with the default GHC version & stackage snapshot
|
||||
`make buildtestall` does the code build warning free with all supported GHC versions/stackage snapshots
|
||||
--------------------- -------------------------------------------------------------------------------------
|
||||
|
||||
See below for examples.
|
||||
|
||||
5. Package test suites
|
||||
|
||||
@ -176,20 +187,20 @@ tests, at least. It would be useful to set this up for hledger.
|
||||
Run unit tests:
|
||||
|
||||
``` example
|
||||
$ just unittest
|
||||
$ make unittest
|
||||
```
|
||||
|
||||
Run doctests:
|
||||
|
||||
``` example
|
||||
$ just doctest
|
||||
$ make doctest
|
||||
```
|
||||
|
||||
Run functional tests (and unit tests, now):
|
||||
|
||||
``` example
|
||||
$ stack install shelltestrunner
|
||||
$ just functest
|
||||
$ make functest
|
||||
```
|
||||
|
||||
Run the package tests (unit tests, maybe doctests, but not functional
|
||||
@ -202,13 +213,25 @@ $ stack test [PKG]
|
||||
Run \"default tests: package plus functional tests\":
|
||||
|
||||
``` example
|
||||
$ just test
|
||||
$ make test
|
||||
```
|
||||
|
||||
Test generation of haddock docs:
|
||||
|
||||
``` example
|
||||
$ just haddocktest
|
||||
$ make haddocktest
|
||||
```
|
||||
|
||||
Thorough test for build issues with current GHC:
|
||||
|
||||
``` example
|
||||
$ make buildtest
|
||||
```
|
||||
|
||||
Thorough test for build issues with all supported GHC versions:
|
||||
|
||||
``` example
|
||||
$ make buildtestall
|
||||
```
|
||||
|
||||
Run built-in hledger/hledger-lib unit tests via hledger command:
|
||||
@ -228,16 +251,22 @@ test [TESTPATTERN] [SEED]
|
||||
seed for easytests.
|
||||
```
|
||||
|
||||
Rebuild and rerun hledger/hledger-lib doc tests via ghcid:
|
||||
Rebuild and rerun hledger/hledger-lib unit tests via ghcid:
|
||||
|
||||
``` example
|
||||
$ just ghcid-doctest
|
||||
$ make ghcid-test
|
||||
```
|
||||
|
||||
See all test-related just rules:
|
||||
Rebuild and rerun only some tests via ghcid (see hledger test --help):
|
||||
|
||||
``` example
|
||||
$ just h test
|
||||
$ make ghcid-test-TESTPATTERN
|
||||
```
|
||||
|
||||
See all test-related make rules:
|
||||
|
||||
``` example
|
||||
$ make help-test
|
||||
```
|
||||
|
||||
|
||||
@ -59,8 +59,8 @@ Current process:
|
||||
- `PKG/package.yaml` contains the cabal package version declaration,
|
||||
bounds on other hledger packages, and a CPP VERSION macro used in
|
||||
`hledger/Hledger/Cli/Version.hs`. Changes in package.yaml will be
|
||||
propagated to `PKG/PKG.cabal` on the next stack build or --dry-run build
|
||||
or with `just cabalfiles`.
|
||||
propagated to `PKG/PKG.cabal` on the next stack or Shake build, or
|
||||
by `make gencabal`.
|
||||
|
||||
- `PKG/.version.m4` contains the _version_ macro used in documentation source files (*.m4.md). It is updated by `./Shake setversion`.
|
||||
|
||||
@ -14,9 +14,8 @@ Ensure [`git`](https://git-scm.com) is installed. On Windows, it comes with stac
|
||||
|
||||
Here are some useful optional tools:
|
||||
|
||||
- [`just`](https://github.com/casey/just) for automating project tasks
|
||||
- [GNU Make](https://www.gnu.org/software/make) for automating tasks in a few subdirectories
|
||||
- [`watchexec`](https://watchexec.github.io) for re-running commands when files change
|
||||
- [GNU Make](https://www.gnu.org/software/make): to use the convenient [Make rules](#make).
|
||||
- [`entr`](https://www.entrproject.org/) runs arbitrary commands when files change.
|
||||
- [`ghcid`](https://hackage.haskell.org/package/ghcid) gives real-time GHC feedback as you make code changes.
|
||||
- [`shelltestrunner`](https://hackage.haskell.org/package/shelltestrunner) runs hledger's functional tests.
|
||||
- [`quickbench`](https://hackage.haskell.org/package/quickbench) measures and reports time taken by commands.
|
||||
@ -38,7 +37,7 @@ Eg:
|
||||
- review and discuss new [pull requests](http://prs.hledger.org) and commits on github
|
||||
- build hledger and test the latest changes in your own repo
|
||||
- read the existing [code docs and source](#quick-links)
|
||||
- send feedback or discuss via [IRC or mail list](support.md)
|
||||
- send feedback or discuss via [IRC or mail list](support.html)
|
||||
|
||||
## Build in place
|
||||
|
||||
@ -86,33 +85,33 @@ Runs any performance reports defined by each hledger package.
|
||||
|
||||
Times the end-user commands in `bench.sh` using quickbench.
|
||||
|
||||
just bench
|
||||
make bench
|
||||
|
||||
## Run functional tests
|
||||
|
||||
Runs the shelltestrunner tests defined in hledger/test/, which test the hledger CLI.
|
||||
|
||||
just functest
|
||||
make functest
|
||||
|
||||
## Run haddock tests
|
||||
|
||||
Checks for anything that would break haddock doc generation.
|
||||
|
||||
just haddocktest
|
||||
make haddocktest
|
||||
|
||||
Checks for the unit-tests embedded in documentation.
|
||||
|
||||
just doctest
|
||||
make doctest
|
||||
|
||||
## Simulate Travis tests
|
||||
|
||||
Locally runs tests similar to what we run on Travis CI.
|
||||
|
||||
just travistest
|
||||
make travistest
|
||||
|
||||
## Test with all supported GHC versions/stackage snapshots
|
||||
|
||||
just allsnapshotstest
|
||||
make allsnapshotstest
|
||||
|
||||
## Use GHCI
|
||||
|
||||
@ -180,7 +179,7 @@ If you're new to this process, [help.github.com](https://help.github.com) may be
|
||||
|
||||
## Add yourself to the contributor list
|
||||
|
||||
- after getting something into the master branch, read and sign the [contributor list & agreement](https://hledger.org/contributors.html). Or, [ask](support.md) to be added.
|
||||
- after getting something into the master branch, read and sign the [contributor list & agreement](https://hledger.org/contributors.html). Or, [ask](support.html) to be added.
|
||||
- give yourself a high five!
|
||||
|
||||
## Work on docs
|
||||
@ -206,15 +205,15 @@ Most docs tasks are handled by [Shake](#shake).
|
||||
|
||||
## Use ghcid for watching GHC/GHCI
|
||||
|
||||
[ghcid](https://hackage.haskell.org/package/ghcid) is the most reliable and fastest way to see GHC's feedback, and optionally run tests or a GHCI command, as you edit. We run it via just, for convenience and to watch multiple packages rather than just one. Run `just h ghcid` to list related rules.
|
||||
[ghcid](https://hackage.haskell.org/package/ghcid) is the most reliable and fastest way to see GHC's feedback, and optionally run tests or a GHCI command, as you edit. We run it via make, for convenience and to watch multiple packages rather than just one. Run `make help-ghcid` to list related rules.
|
||||
|
||||
### Watch for compile errors in hledger-lib and hledger:
|
||||
|
||||
just ghcid
|
||||
make ghcid
|
||||
|
||||
### Watch compile errors and the output of some hledger command:
|
||||
|
||||
ghcid -c 'just ghci' -T ':main -f a.j bal --budget -N'
|
||||
ghcid -c 'make ghci' -T ':main -f a.j bal --budget -N'
|
||||
|
||||
## Use --file-watch for watching stack
|
||||
|
||||
@ -224,6 +223,10 @@ stack's --file-watch flag will re-run build/test/bench when source files or pack
|
||||
|
||||
If you find that adding --fast makes this any faster, please update this.
|
||||
|
||||
## Use entr for watching arbitrary commands
|
||||
|
||||
[entr](https://entrproject.org/) is the most robust cross-platform tool for watching files and running a command when they change. Note its first argument must be an executable program, to run a shell command or multiple commands use `bash -c "..."`.
|
||||
|
||||
### Rerun a single functional test as you change it:
|
||||
|
||||
watchexec -w hledger/test/journal/assertions.test just functest -i budget.*19
|
||||
ls hledger/test/budget/budget.test | entr bash -c 'clear; COLUMNS=80 stack exec -- shelltest --execdir hledger/test/budget/budget.test -i12'
|
||||
@ -1,3 +0,0 @@
|
||||
hledger -f examples/10ktxns-100kaccts.journal print
|
||||
hledger -f examples/10ktxns-100kaccts.journal register
|
||||
hledger -f examples/10ktxns-100kaccts.journal balance
|
||||
@ -1,3 +0,0 @@
|
||||
hledger -f examples/10ktxns-10kaccts.journal print
|
||||
hledger -f examples/10ktxns-10kaccts.journal register
|
||||
hledger -f examples/10ktxns-10kaccts.journal balance
|
||||
@ -1,22 +0,0 @@
|
||||
hledger -f examples/1ktxns-1accts.journal balance
|
||||
hledger -f examples/1ktxns-10accts.journal balance
|
||||
hledger -f examples/1ktxns-100accts.journal balance
|
||||
hledger -f examples/1ktxns-1kaccts.journal balance
|
||||
hledger -f examples/1ktxns-10kaccts.journal balance
|
||||
hledger -f examples/1ktxns-100kaccts.journal balance
|
||||
hledger -f examples/1ktxns-1maccts.journal balance
|
||||
hledger -f examples/10ktxns-1accts.journal balance
|
||||
hledger -f examples/10ktxns-10accts.journal balance
|
||||
hledger -f examples/10ktxns-100accts.journal balance
|
||||
hledger -f examples/10ktxns-1kaccts.journal balance
|
||||
hledger -f examples/10ktxns-10kaccts.journal balance
|
||||
hledger -f examples/10ktxns-20kaccts.journal balance
|
||||
hledger -f examples/10ktxns-30kaccts.journal balance
|
||||
hledger -f examples/10ktxns-40kaccts.journal balance
|
||||
hledger -f examples/10ktxns-50kaccts.journal balance
|
||||
hledger -f examples/10ktxns-60kaccts.journal balance
|
||||
hledger -f examples/10ktxns-70kaccts.journal balance
|
||||
hledger -f examples/10ktxns-80kaccts.journal balance
|
||||
hledger -f examples/10ktxns-90kaccts.journal balance
|
||||
hledger -f examples/10ktxns-100kaccts.journal balance
|
||||
#hledger -f examples/10ktxns-1maccts.journal balance
|
||||
@ -1,19 +0,0 @@
|
||||
hledger -f examples/1ktxns-1kaccts.journal balance
|
||||
hledger -f examples/2ktxns-1kaccts.journal balance
|
||||
hledger -f examples/3ktxns-1kaccts.journal balance
|
||||
hledger -f examples/4ktxns-1kaccts.journal balance
|
||||
hledger -f examples/5ktxns-1kaccts.journal balance
|
||||
hledger -f examples/6ktxns-1kaccts.journal balance
|
||||
hledger -f examples/7ktxns-1kaccts.journal balance
|
||||
hledger -f examples/8ktxns-1kaccts.journal balance
|
||||
hledger -f examples/9ktxns-1kaccts.journal balance
|
||||
hledger -f examples/10ktxns-1kaccts.journal balance
|
||||
hledger -f examples/20ktxns-1kaccts.journal balance
|
||||
hledger -f examples/30ktxns-1kaccts.journal balance
|
||||
hledger -f examples/40ktxns-1kaccts.journal balance
|
||||
hledger -f examples/50ktxns-1kaccts.journal balance
|
||||
hledger -f examples/60ktxns-1kaccts.journal balance
|
||||
hledger -f examples/70ktxns-1kaccts.journal balance
|
||||
hledger -f examples/80ktxns-1kaccts.journal balance
|
||||
hledger -f examples/90ktxns-1kaccts.journal balance
|
||||
hledger -f examples/100ktxns-1kaccts.journal balance
|
||||
43
bench.sh
43
bench.sh
@ -5,7 +5,7 @@
|
||||
# (criterion) is more robust.
|
||||
#
|
||||
# Generate the test journals:
|
||||
# just samplejournals
|
||||
# make samplejournals
|
||||
#
|
||||
# Get quickbench:
|
||||
# git clone https://github.com/simonmichael/quickbench
|
||||
@ -15,31 +15,32 @@
|
||||
# Measure performance:
|
||||
# time ./bench.sh # show if these work, what they do, total time (GNU time also shows max memory)
|
||||
# quickbench [OPTS] # time each command, one or more times
|
||||
# make bench # time each command with several hledger versions (BENCHEXES in Makefile)
|
||||
# stack bench hledger # time a different set of benchmarks (bench/bench.hs)
|
||||
# stack bench hledger --ba --criterion # time more carefully, using criterion
|
||||
|
||||
# commands to benchmark:
|
||||
|
||||
# hledger -f examples/100txns-100accts.journal print
|
||||
# hledger -f examples/1ktxns-1kaccts.journal print
|
||||
hledger -f examples/10ktxns-1kaccts.journal print
|
||||
# hledger -f examples/10ktxns-1kaccts.journal print ff
|
||||
#hledger -f examples/100ktxns-1kaccts.journal print
|
||||
#hledger -f examples/100ktxns-1kaccts.journal print ff
|
||||
# hledger -f examples/100x100x10.journal print
|
||||
# hledger -f examples/1000x1000x10.journal print
|
||||
hledger -f examples/10000x1000x10.journal print
|
||||
# hledger -f examples/10000x1000x10.journal print ff
|
||||
#hledger -f examples/100000x1000x10.journal print
|
||||
#hledger -f examples/100000x1000x10.journal print ff
|
||||
|
||||
# hledger -f examples/100txns-100accts.journal register
|
||||
# hledger -f examples/1ktxns-1kaccts.journal register
|
||||
hledger -f examples/10ktxns-1kaccts.journal register
|
||||
# hledger -f examples/10ktxns-1kaccts.journal register ff
|
||||
#hledger -f examples/100ktxns-1kaccts.journal register
|
||||
#hledger -f examples/100ktxns-1kaccts.journal register ff
|
||||
# hledger -f examples/100x100x10.journal register
|
||||
# hledger -f examples/1000x1000x10.journal register
|
||||
hledger -f examples/10000x1000x10.journal register
|
||||
# hledger -f examples/10000x1000x10.journal register ff
|
||||
#hledger -f examples/100000x1000x10.journal register
|
||||
#hledger -f examples/100000x1000x10.journal register ff
|
||||
|
||||
# hledger -f examples/100txns-100accts.journal balance
|
||||
# hledger -f examples/1ktxns-1kaccts.journal balance
|
||||
hledger -f examples/10ktxns-1kaccts.journal balance
|
||||
# hledger -f examples/10ktxns-1kaccts.journal balance ff
|
||||
#hledger -f examples/100ktxns-1kaccts.journal balance
|
||||
#hledger -f examples/100ktxns-1kaccts.journal balance ff
|
||||
#hledger -f examples/1ktxns-1kaccts.journal balance --weekly
|
||||
#hledger -f examples/10ktxns-1kaccts.journal balance --weekly
|
||||
# hledger -f examples/100x100x10.journal balance
|
||||
# hledger -f examples/1000x1000x10.journal balance
|
||||
hledger -f examples/10000x1000x10.journal balance
|
||||
# hledger -f examples/10000x1000x10.journal balance ff
|
||||
#hledger -f examples/100000x1000x10.journal balance
|
||||
#hledger -f examples/100000x1000x10.journal balance ff
|
||||
hledger -f examples/1000x1000x10.journal balance --weekly
|
||||
hledger -f examples/10000x1000x10.journal balance --weekly
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
hledger -f examples/100ktxns-1kaccts.journal print
|
||||
hledger -f examples/100ktxns-1kaccts.journal register
|
||||
hledger -f examples/100ktxns-1kaccts.journal balance
|
||||
@ -1,3 +0,0 @@
|
||||
hledger -f examples/10ktxns-1kaccts.journal print
|
||||
hledger -f examples/10ktxns-1kaccts.journal register
|
||||
hledger -f examples/10ktxns-1kaccts.journal balance
|
||||
@ -1,3 +0,0 @@
|
||||
hledger -f examples/1ktxns-1kaccts.journal print
|
||||
hledger -f examples/1ktxns-1kaccts.journal register
|
||||
hledger -f examples/1ktxns-1kaccts.journal balance
|
||||
@ -1,3 +0,0 @@
|
||||
hledger -f examples/5ktxns-1kaccts.journal print
|
||||
hledger -f examples/5ktxns-1kaccts.journal register
|
||||
hledger -f examples/5ktxns-1kaccts.journal balance
|
||||
33
bin/.gitignore
vendored
33
bin/.gitignore
vendored
@ -1,24 +1,9 @@
|
||||
# lots of uncommitted stuff here
|
||||
|
||||
#g.*
|
||||
# _*
|
||||
# *.hi
|
||||
# *.o
|
||||
|
||||
# executables compiled from .hs scripts
|
||||
gsheet-csv
|
||||
hledger-balance-as-budget-multi
|
||||
hledger-balance-as-budget
|
||||
hledger-check-fancyassertions
|
||||
hledger-check-postable
|
||||
hledger-check-tagfiles.cabal
|
||||
hledger-check-tagfiles
|
||||
hledger-combine-balances
|
||||
hledger-move
|
||||
hledger-register-max
|
||||
hledger-register-max2
|
||||
hledger-report1
|
||||
hledger-script-example-short
|
||||
hledger-script-example
|
||||
hledger-smooth
|
||||
hledger-swap-dates
|
||||
hledger-budget
|
||||
hledger-chart
|
||||
hledger-check-dates
|
||||
hledger-dupes
|
||||
hledger-equity
|
||||
hledger-prices
|
||||
hledger-print-unique
|
||||
hledger-register-match
|
||||
hledger-rewrite
|
||||
|
||||
361
bin/Justfile
361
bin/Justfile
@ -1,361 +0,0 @@
|
||||
#!/usr/bin/env just -f
|
||||
# * financial reports/scripts, managed with https://github.com/casey/just
|
||||
# ** PUBLIC: the scripts below can be shared in hledger's bin/Justfile.
|
||||
|
||||
# *** PREAMBLE ------------------------------------------------------------
|
||||
|
||||
just := "just -f " + justfile()
|
||||
TODAY := `date +%Y-%m-%d`
|
||||
|
||||
# list the commands available
|
||||
@help:
|
||||
{{ just }} -ul --list-heading=$'{{ file_name(justfile()) }} commands:\n\
|
||||
ARGS can be added to customise reports.\n\
|
||||
'
|
||||
# XXX we don't quote ARGS properly, so each one must be free of spaces
|
||||
|
||||
# XXX broken
|
||||
# # interactively pick a command with the default chooser. Eg: just pick -
|
||||
# pick:
|
||||
# {{ just }} --choose
|
||||
|
||||
# XXX be careful, runs each selected command immediately. Use mouse to select.
|
||||
# interactively view command outputs with fzf and bkt. Eg: just view - --black
|
||||
view *ARGS:
|
||||
{{ just }} --choose --chooser="fzf --reverse --preview='bkt --ttl=15m --stale=15s -- just {}' {{ ARGS }}"
|
||||
|
||||
# rerun the given command with watchexec whenever local files change
|
||||
watch CMD:
|
||||
watchexec -- {{ just }} {{ CMD }}
|
||||
|
||||
# *** IMPORT ------------------------------------------------------------
|
||||
|
||||
# where to import most hledger transactions from
|
||||
# import sources:
|
||||
# 1. cash wallets
|
||||
# 2. wells fargo bank
|
||||
# 3. bank of ireland
|
||||
# 4. fidelity
|
||||
# 5. paypal
|
||||
IMPORTFILES := '\
|
||||
wf-bchecking.csv.rules \
|
||||
wf-pchecking.csv.rules \
|
||||
wf-bsavings.csv.rules \
|
||||
wf-psavings.csv.rules \
|
||||
bofi-ichecking.csv.rules \
|
||||
fidelity.csv.rules \
|
||||
paypal.csv \
|
||||
'
|
||||
|
||||
# get auto-downloadable CSVs, and clean manually-downloaded CSVs
|
||||
csv:
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# latestcsv PARTIALFILEPATH - list latest non-cleaned CSV with this path
|
||||
latestcsv() { ls -t "$1"*.csv | grep -v ".clean" | head -1; }
|
||||
|
||||
echo "cleaning fidelity csv"
|
||||
# remove leading space
|
||||
for f in $(latestcsv ~/Downloads/History_for_Account_); do
|
||||
g=~/Downloads/$(basename $f csv)clean.csv
|
||||
sed -e 's/^ //' $f >$g
|
||||
# ls -l $g
|
||||
done
|
||||
|
||||
echo "getting paypal csv..."
|
||||
paypaljson | paypaljson2csv > paypal.csv
|
||||
# ls -l paypal.csv
|
||||
|
||||
# get CSVs, then import any new transactions from them to the journal, logging but not printing errors; add --dry to preview
|
||||
@csv-import *ARGS:
|
||||
date >>import.log
|
||||
{{ just }} csv 2>>import.log || echo "Failed, check import.log"
|
||||
hledger import {{ IMPORTFILES }} {{ ARGS }} 2>>import.log || echo "Failed, check import.log"
|
||||
|
||||
|
||||
HOUSEHOLDEKRECENT := "household-recent.journal"
|
||||
|
||||
# get a household adjustment transaction for last month
|
||||
household:
|
||||
#!/usr/bin/env bash
|
||||
echo "getting household google sheet..."
|
||||
date=$(if [ "$(builtin type -p gdate)" ]; then echo gdate; else echo date; fi)
|
||||
env household $($date --date -1month +%b) >{{ HOUSEHOLDEKRECENT }}
|
||||
|
||||
# get a household adjustment transaction for last month, then import it if new; add --dry to preview
|
||||
@household-import *ARGS:
|
||||
{{ just }} household 2>>import.log || echo "Failed, check import.log"
|
||||
hledger import {{ HOUSEHOLDEKRECENT }} -I {{ ARGS }} 2>>import.log || echo "Failed, check import.log"
|
||||
|
||||
|
||||
# show the forecast transactions predicted recently and soon
|
||||
@forecast *ARGS:
|
||||
hledger print --forecast=15daysago..15days tag:_generated --auto -I {{ ARGS }}
|
||||
|
||||
# import any new forecast transactions; add --dry to preview
|
||||
@forecast-import *ARGS:
|
||||
#!/usr/bin/env bash
|
||||
echo "importing transactions from forecast rules"
|
||||
hledger import forecast.journal --forecast=15daysago..15days --auto -I {{ ARGS }} 2>>import.log || echo "Failed, check import.log"
|
||||
if [[ "$ARGS" != *"--dry"* ]]; then
|
||||
echo "(remove any near-future transactions included for preview)"
|
||||
echo "resetting .latest.forecast.journal to today's date"
|
||||
date +%Y-%m-%d >.latest.forecast.journal
|
||||
fi
|
||||
|
||||
# get and import all the above; add --dry to preview
|
||||
@import *ARGS:
|
||||
{{ just }} csv-import {{ ARGS }}
|
||||
{{ just }} household-import {{ ARGS }}
|
||||
{{ just }} forecast-import {{ ARGS }}
|
||||
|
||||
|
||||
# show prices for main commodities (default: today's)
|
||||
@get-prices *PHFETCHARGS:
|
||||
(pricehist fetch -o ledger -s {{ TODAY }} alphavantage EUR/USD {{ PHFETCHARGS }} | sed -E 's/EUR/€/') &
|
||||
(pricehist fetch -o ledger -s {{ TODAY }} alphavantage GBP/USD {{ PHFETCHARGS }} | sed -E 's/GBP/£/') &
|
||||
(pricehist fetch -o ledger -s {{ TODAY }} alphavantage JPY/USD {{ PHFETCHARGS }} | sed -E 's/JPY/¥/')
|
||||
# Parallelised for speed; do slowest last.
|
||||
# Output order varies, can be sorted with LC_COLLATE=C.UTF-8 sort or hledger -f- prices.
|
||||
|
||||
# *** REPORTS ------------------------------------------------------------
|
||||
|
||||
PERIOD := "1/1..tomorrow"
|
||||
|
||||
# show balance sheet
|
||||
bs *ARGS:
|
||||
hledger bs --layout bare --pretty --drop 1 -p {{ PERIOD }} -E -5 {{ ARGS }}
|
||||
|
||||
# show income statement
|
||||
is *ARGS:
|
||||
hledger is --layout bare --pretty --drop 1 -p {{ PERIOD }} -S {{ ARGS }}
|
||||
|
||||
# show assets
|
||||
a *ARGS:
|
||||
hledger bal type:al -H --layout bare --pretty --drop 1 -p {{ PERIOD }} -E {{ ARGS }}
|
||||
|
||||
# show revenues
|
||||
r *ARGS:
|
||||
hledger bal type:r --layout bare --pretty --drop 1 -p {{ PERIOD }} -S --invert {{ ARGS }}
|
||||
|
||||
# show expenses
|
||||
x *ARGS:
|
||||
hledger bal type:x --layout bare --pretty --drop 1 -p {{ PERIOD }} -S --invert {{ ARGS }}
|
||||
|
||||
# show assets bar chart
|
||||
ab *ARGS:
|
||||
echo "Quarterly net worth:"
|
||||
hledger-bar -v 200 -Q type:al -H {{ ARGS }}
|
||||
|
||||
# show revenues bar chart
|
||||
rb *ARGS:
|
||||
echo "Quarterly revenues:"
|
||||
hledger-bar -v 40 -Q type:r --invert {{ ARGS }}
|
||||
|
||||
# show expenses bar chart
|
||||
xb *ARGS:
|
||||
echo "Quarterly expenses:"
|
||||
hledger-bar -v 40 -Q type:x --invert {{ ARGS }}
|
||||
|
||||
# XXX with partial workaround for https://github.com/gooofy/drawilleplot/issues/4
|
||||
|
||||
# show assets line chart
|
||||
al *ARGS:
|
||||
hledger plot -- bal --depth=1 type:a --historical --terminal --rcParams '{"figure.figsize":[8,3]}' --no-today -q --title "hledger assets" {{ ARGS }} | sed 's/⠀/ /g'
|
||||
|
||||
# show revenues line chart
|
||||
rl *ARGS:
|
||||
hledger plot -- bal --depth=1 type:r --monthly --invert --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly revenues" {{ ARGS }} | sed 's/⠀/ /g'
|
||||
|
||||
# show expenses line chart
|
||||
xl *ARGS:
|
||||
hledger plot -- bal --depth=1 type:x --monthly --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly expenses" {{ ARGS }} | sed 's/⠀/ /g'
|
||||
|
||||
# show consulting revenue
|
||||
consulting *ARGS:
|
||||
hledger reg --invert 'revenues:(cw|ah)' -p {{ PERIOD }} {{ ARGS }}
|
||||
|
||||
# estimated-tax *ARGS :
|
||||
# @echo "Federal estimated tax due for this year"
|
||||
# $(HLEDGER) register liabilities:personal:tax:federal:$(YEAR) --width=130
|
||||
# @echo State estimated tax due for this year:
|
||||
# @$(HLEDGER) register liabilities:personal:tax:state:$(YEAR) --width=130
|
||||
# @echo
|
||||
|
||||
# *** TIME REPORTS ------------------------------------------------------------
|
||||
|
||||
set export := true
|
||||
|
||||
# The file where actual time data is logged, for dashboard's stats.
|
||||
# This might or might not be the top-level $TIMELOG file.
|
||||
#TIMELOGDATA=$TIMELOG
|
||||
|
||||
YEAR := `date +%Y`
|
||||
TIMELOGDATA := 'time-' + YEAR + '.timedot'
|
||||
TIMELOGALL := `dirname "$TIMELOG"` + '/time-all.journal'
|
||||
|
||||
# This redisplays only when a file listed by `hledger -f $TIMELOG files` is modified.
|
||||
# To force a per minute display as well, have $TIMELOG include a dummy file (.update)
|
||||
# and configure a cron job to touch that every minute.
|
||||
# (This is better than touching the timelog file itself, which confuses editors.)
|
||||
#
|
||||
|
||||
# show time dashboard, redisplaying when timelog files change
|
||||
tdash *ARGS:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
dir=$(dirname "$TIMELOG")
|
||||
cd "$dir"
|
||||
opts= #--poll=10 # <- uncomment to fix symlinked files being ignored
|
||||
watchexec $opts --no-vcs-ignore \
|
||||
--filter-file=<(hledger -f "$TIMELOG" files | sed -E "s|$dir/||g") \
|
||||
-c -r {{ just }} tstatus {{ ARGS }}
|
||||
|
||||
# show time dashboard, redisplaying every minute with watch
|
||||
# dash-1m *ARGS:
|
||||
# watch -n60 -c tt status
|
||||
# }
|
||||
|
||||
# show current time status
|
||||
tstatus *ARGS:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
date=$(if [ "$(builtin type -p gdate)" ]; then echo gdate; else echo date; fi)
|
||||
stat=$(if [ "$(builtin type -p gstat)" ]; then echo gstat; else echo stat; fi)
|
||||
curtime=$($date +'%H:%M %Z, %a %b %-e %Y')
|
||||
modtime=$($date +'%H:%M %Z' -r "$TIMELOGDATA")
|
||||
modsecs=$($stat -c %Y "$TIMELOGDATA")
|
||||
nowsecs=$($date +%s)
|
||||
agesecs=$((nowsecs - modsecs))
|
||||
agemins=$(python3 -c "print($agesecs/60)")
|
||||
agehrs=$(python3 -c "print($agesecs/3600.0)")
|
||||
ageqtrhrs=$(python3 -c "print(round($agesecs/900.0))")
|
||||
agedots=$({{ just }} tdots "$ageqtrhrs")
|
||||
printf "Current time: %s\n" "$curtime"
|
||||
# old, for osh: use env here to run the system printf, which supports floating point
|
||||
env printf "Timelog saved: %s, %.0fm / %.1fh / %s ago\n" "$modtime" "$agemins" "$agehrs" "$agedots"
|
||||
# Show the current day/week/month budget status.
|
||||
printf "Time plans:\n"
|
||||
# calculate each period's budget from daily budget
|
||||
hledger -f "$TIMELOG" bal -1 -p 'daily today' --budget=Daily {{ ARGS }} | tail +2
|
||||
hledger -f "$TIMELOG" bal -1 -p 'weekly this week' --budget=Daily {{ ARGS }} | tail +2
|
||||
hledger -f "$TIMELOG" bal -1 -p 'monthly this month' --budget=Daily {{ ARGS }} | tail +2
|
||||
# or use each period's specific budget
|
||||
# hledger -f "$TIMELOG" bal -p 'daily today' --budget=Daily -1 | tail +2
|
||||
# hledger -f "$TIMELOG" bal -p 'weekly this week' --budget=Weekly -1 | tail +2
|
||||
# hledger -f "$TIMELOG" bal -p 'monthly this month' --budget=Monthly -1 | tail +2
|
||||
echo
|
||||
hledger -f "$TIMELOG" check -s tags ordereddates || true
|
||||
# this comes last because it's slow and variable length
|
||||
echo
|
||||
printf "Display activity:\n"
|
||||
wakelog today | tail -n 6
|
||||
|
||||
# what happened ? Show largest time balances first, today and depth 1 by default
|
||||
@twhat *ARGS:
|
||||
hledger -f "$TIMELOG" bal -S -1 -p today {{ ARGS }}
|
||||
|
||||
# print line of N dots, grouped in 4s (suitable for timedot)
|
||||
tdots N:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
n={{ N }}
|
||||
ndiv4=$((n/4))
|
||||
nmod4=$((n-n/4*4))
|
||||
sep=''
|
||||
while [[ $ndiv4 -gt 0 ]]; do ndiv4=$((ndiv4-1)); echo -n "$sep...."; sep=' '; done
|
||||
while [[ $nmod4 -gt 0 ]]; do nmod4=$((nmod4-1)); echo -n "$sep."; sep=''; done
|
||||
echo
|
||||
|
||||
RFLAGS := '-tM'
|
||||
|
||||
# horizontal time summary this year, monthly by default
|
||||
@tx *ARGS:
|
||||
hledger -f "$TIMELOG" bal -1 "$RFLAGS" {{ ARGS }}
|
||||
|
||||
# vertical time summary this year, monthly by default
|
||||
@ty *ARGS:
|
||||
hledger -f "$TIMELOG" bal -1 "$RFLAGS" --transpose {{ ARGS }}
|
||||
|
||||
# horizontal time summary since 2007, yearly by default. Gaps in 2010-2015.
|
||||
@txall *ARGS:
|
||||
hledger -f "$TIMELOGALL" bal -1 "$RFLAGS" -Y {{ ARGS }}
|
||||
|
||||
# vertical time summary since 2007, yearly by default. Gaps in 2010-2015.
|
||||
@tyall *ARGS:
|
||||
hledger -f "$TIMELOGALL" bal -1 "$RFLAGS" -Y --transpose {{ ARGS }}
|
||||
|
||||
# horizontal hledger time summary, yearly by default. Gaps in 2010-2015.
|
||||
@txallhledger *ARGS:
|
||||
{{ just }} txall hledger not:^ser.ek -AT {{ ARGS }}
|
||||
|
||||
# show a bar chart of this year's time in hours, weekly by default. Bar resolution is 1h.
|
||||
@tbar *ARGS:
|
||||
hledger-bar -v 1 -f "$TIMELOG" -W {{ ARGS }}
|
||||
|
||||
# show a bar chart of time since 2007, monthly by default, with 10h bar resolution. Gaps in 2010-2015.
|
||||
@tbarall *ARGS:
|
||||
hledger-bar -v 10 -f "$TIMELOGALL" -M not:cur: {{ ARGS }}
|
||||
# not:cur: because --layout=bare will add a row for no-symbol commodity if any periods are zero.
|
||||
|
||||
# show a bar chart of time since 2007, yearly by default, with 100h bar resolution. Gaps in 2010-2015.
|
||||
@tbarally *ARGS:
|
||||
hledger-bar -v 100 -f "$TIMELOGALL" -Y not:cur:'' {{ ARGS }}
|
||||
# not:cur: because --layout=bare will add a row for no-symbol commodity if any periods are zero.
|
||||
|
||||
# this and last week's time budgets
|
||||
@tweekbudgets *ARGS:
|
||||
printf "\nLast week, this week:\n"
|
||||
timeweekly run
|
||||
|
||||
# recent past weeks' time budgets
|
||||
@tweekbudgetspast *ARGS:
|
||||
printf "\nPast weeks:\n"
|
||||
timeweekly past
|
||||
|
||||
# show unused / undeclared time accounts
|
||||
@taccunused *ARGS:
|
||||
echo "Unused: (but declared)"
|
||||
hledger -f "$TIMELOG" acc --unused {{ ARGS }} --directives | gsed -E 's/:(.)/.\1/g'
|
||||
echo
|
||||
echo "Undeclared: (but used)"
|
||||
hledger -f "$TIMELOG" acc --undeclared {{ ARGS }} --directives | gsed -E 's/:(.)/.\1/g'
|
||||
|
||||
# show unused / undeclared time accounts by category
|
||||
@taccunusedcat *ARGS:
|
||||
for a in $(tt acc -1); do line; echo "$a":; tt unused "^$a"; echo; done; line
|
||||
|
||||
# add declarations for all undeclared time accounts
|
||||
@taccadd *ARGS:
|
||||
hledger -f "$TIMELOG" accounts --undeclared --directives | sed 's/:/./g' >>"$TIMELOG"
|
||||
|
||||
# show monthly time budget performance this year
|
||||
@tbudgets *ARGS:
|
||||
{{ just }} tx --budget=daily -M -p jan..tomorrow {{ ARGS }}
|
||||
|
||||
# show monthly time budget performance this year, vertically
|
||||
@tbudgetsy *ARGS:
|
||||
{{ just }} ty --budget=daily -M -p jan..tomorrow {{ ARGS }}
|
||||
|
||||
# dedicated weekly reports, needed to set proper week start date, to ensure simple headings:
|
||||
|
||||
# show weekly time budget performance this year
|
||||
@tbudgetsw *ARGS:
|
||||
{{ just }} ty --budget=daily -W -p 3/27..tomorrow {{ ARGS }}
|
||||
|
||||
# show weekly time budget performance this year, horizontally
|
||||
@tbudgetswx *ARGS:
|
||||
{{ just }} tx --budget=daily -W -p 3/27..tomorrow {{ ARGS }}
|
||||
|
||||
# show monthly time percentages
|
||||
@txpc *ARGS:
|
||||
{{ just }} tx -% {{ ARGS }}
|
||||
|
||||
# show monthly time tagged by activity type
|
||||
@txt *ARGS:
|
||||
hledger -f "$TIMELOG" bal -b2023/5 -M tag:t -1 {{ ARGS }}
|
||||
|
||||
# show monthly time tagged by activity type as percentages
|
||||
@txtpc *ARGS:
|
||||
{{ just }} txt -% {{ ARGS }}
|
||||
|
||||
644
bin/README.md
644
bin/README.md
@ -1,94 +1,43 @@
|
||||
# Scripts and add-ons
|
||||
# Scripts
|
||||
|
||||
<div class=pagetoc>
|
||||
|
||||
<!-- toc -->
|
||||
</div>
|
||||
|
||||
(This is the README in the hledger repo's `bin/` directory,
|
||||
also published as the [Scripts and add-ons] page on hledger.org.)
|
||||
<!-- This page can be viewed on github or hledger.org, so use absolute urls here: -->
|
||||
This document is the README in the hledger repo's [bin] directory,
|
||||
and is also published as [Scripts] on hledger.org.
|
||||
Here we collect hledger scripts: additional small tools which complement hledger in some way.
|
||||
These can be:
|
||||
|
||||
[Scripts and add-ons]: https://hledger.org/scripts.html
|
||||
[Scripting hledger]: https://hledger.org/scripting.html
|
||||
- shell aliases or functions, defined eg in your shell's startup file
|
||||
- shell script files
|
||||
- programs written in other languages, like Python or Haskell.
|
||||
Haskell scripts are the most powerful since they can call hledger's Haskell API (we'll call these *hledger-integrated*).
|
||||
- script files or programs named `hledger-*`,
|
||||
which show up in hledger's [commands list](hledger.html#commands)
|
||||
as [add-on commands](https://hledger.org/dev/hledger.html#addons).
|
||||
|
||||
The most common types of hledger script are:
|
||||
|
||||
1. shell aliases/functions/scripts which run hledger with custom options and arguments, eg to produce a particular report
|
||||
2. Haskell add-on command scripts implementing variants of the built-in commands, or new kinds of report.
|
||||
|
||||
[Scripting hledger] has more on this general topic.
|
||||
|
||||
The current "bin scripts" are listed in the page contents and below, categorised by how they invoke hledger.
|
||||
They are either useful as is, or can be examples/inspiration for making your own.
|
||||
Contributions welcome!
|
||||
Following the list are [install instructions](#installing-the-bin-scripts) and other tips.
|
||||
|
||||
<!-- This page can be viewed on github or hledger.org, so use absolute urls. -->
|
||||
[bin]: https://github.com/simonmichael/hledger/tree/master/bin
|
||||
[Scripts]: https://hledger.org/scripts.html
|
||||
[Scripting hledger]: https://hledger.org/scripting.html
|
||||
|
||||
A *script* is a program you can run immediately without needing to compile it first.
|
||||
They are often small and defined in a single file or shell alias or shell function.
|
||||
You can create your own simple or complex scripts which enhance hledger.
|
||||
Eg you might script a complicated report so you don't have to remember the detailed command(s).
|
||||
## hledger-running scripts
|
||||
|
||||
A hledger *add-on command* is any program whose name begins with "hledger-".
|
||||
Add-on commands found in PATH will appear in the commands list (shown when you run `hledger` with no arguments).
|
||||
Some of the scripts below are add-ons.
|
||||
Some add-ons are written in Haskell and can use hledger's full power, like builtin commands.
|
||||
|
||||
Below are some existing scripts you can use or learn from.
|
||||
Most of these are collected in [hledger's bin/ directory][bin],
|
||||
which you can get by [cloning](https://hledger.org/scripts.html#install-scripts) the hledger source.
|
||||
Compiled add-ons are also listed below, in their own section.
|
||||
|
||||
Note, you don't need any of these extras if you are new to hledger -
|
||||
except possibly hledger-ui and hledger-web, which can be nice to have at the start.
|
||||
|
||||
|
||||
## Related scripts
|
||||
|
||||
Here are some scripts which don't use hledger directly, but might be useful to hledger users.
|
||||
(For more, see also: [plaintextaccounting.org > Software](https://plaintextaccounting.org#software)).
|
||||
|
||||
|
||||
### ledgereval
|
||||
|
||||
[ledgereval](https://github.com/simonmichael/hledger/blob/master/bin/ledgereval)
|
||||
is a helper for evaluating Ledger value expressions.
|
||||
It's useful eg when converting amount expressions like `(1 USD + 2 USD)` to simple amounts.
|
||||
|
||||
### pricehist
|
||||
|
||||
[pricehist](https://pypi.org/project/pricehist) is useful for downloading market prices / conversion rates; recommended.
|
||||
And [`hledger-pricehist`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-pricehist)
|
||||
is a small script to make it show up in the hledger commands list.
|
||||
|
||||
### paypaljson
|
||||
|
||||
[`paypaljson`](https://github.com/simonmichael/hledger/blob/master/bin/paypaljson)
|
||||
downloads the last 30 days of Paypal transactions (requires a free developer account & API key).
|
||||
|
||||
### paypalcsv
|
||||
|
||||
[`paypalcsv`](https://github.com/simonmichael/hledger/blob/master/bin/paypalcsv) (python)
|
||||
converts `paypaljson`'s output to CSV, with format similar to Paypal's manually-downloaded CSV.
|
||||
|
||||
Example usage with hledger 1.50+:
|
||||
call these in a CSV [rules file](https://hledger.org/hledger.html#csv) like: `source | paypaljson | paypalcsv`.
|
||||
Or, do the download externally with `paypaljson >paypal.json`,
|
||||
then convert to CSV in the rules file: `source | paypalcsv paypal.json`.
|
||||
|
||||
### simplefinsetup
|
||||
|
||||
[`simplefinsetup`](https://github.com/simonmichael/hledger/blob/master/bin/simplefinsetup)
|
||||
helps set up access to SimpleFIN ([simplefin.org](https://simplefin.org)), a developer-friendly aggregator of US bank data.
|
||||
|
||||
### simplefinjson
|
||||
|
||||
[`simplefinjson`](https://github.com/simonmichael/hledger/blob/master/bin/simplefinjson)
|
||||
downloads data for one or more bank accounts from SimpleFIN's API, as JSON.
|
||||
|
||||
### simplefincsv
|
||||
|
||||
[`simplefincsv`](https://github.com/simonmichael/hledger/blob/master/bin/simplefincsv)
|
||||
converts SimpleFIN's JSON data to CSV, for one or more bank accounts.
|
||||
|
||||
Example usage with hledger 1.50+:
|
||||
download multi-account JSON once with `simplefinjson >simplefin.json`,
|
||||
and in each account's CSV [rules file](https://hledger.org/hledger.html#csv), extract that account's CSV, eg:
|
||||
`source | simplefincsv simplefin.json 'wells fargo.*checking'`.
|
||||
See also [hledger and SimpleFIN](https://hledger.org/simplefin.html).
|
||||
|
||||
## hledger command line scripts
|
||||
|
||||
These scripts use hledger's command line interface, or process one of its output formats.
|
||||
These run hledger via its command line interface, and perhaps process its output:
|
||||
|
||||
### bashrc
|
||||
|
||||
@ -101,157 +50,6 @@ $ . bin/bashrc
|
||||
$ fin # list the scripts available
|
||||
```
|
||||
|
||||
### ft
|
||||
|
||||
[`ft`](https://github.com/simonmichael/hledger/blob/master/bin/ft)
|
||||
is a way to organise your finance-related reports and scripts using standard bash.
|
||||
(See also [Justfile](#justfile) below.)
|
||||
|
||||
```cli
|
||||
$ alias f=~/src/hledger/bin/ft
|
||||
$ f
|
||||
--------------------------------------------------------------------------------"; }
|
||||
ft - finance tool: run financial reports and finance-related scripts
|
||||
Usage: ft [COMMAND [ARGS]]
|
||||
Commands:
|
||||
help show this help
|
||||
get-csv download auto-downloadable CSVs (paypal)
|
||||
import-dry import new downloaded transactions to the journal, dry run
|
||||
import import new downloaded transactions to the journal, logging and not printing errors
|
||||
get-prices [PRICEHISTFETCHOPTS] - download prices for main commodities (default: today's)
|
||||
bs show balance sheet
|
||||
is show income statement
|
||||
a show assets
|
||||
r show revenues
|
||||
x show expenses
|
||||
ab show assets bar chart
|
||||
rb show revenues bar chart
|
||||
xb show expenses bar chart
|
||||
al show assets line chart
|
||||
rl show revenues line chart
|
||||
xl show expenses line chart
|
||||
forecast print transactions predicted by forecast rules from last week on
|
||||
household show a draft month-end household adjustment transaction for last month
|
||||
consulting show consulting revenue
|
||||
bin [PAT] show all scripts in $DIR/bin/[bashrc] (default: ~/finance/)
|
||||
OTHERCMD [ARGS] run other hledger commands on the default journal
|
||||
|
||||
Add hledger options to customise reports.
|
||||
```
|
||||
|
||||
### tt
|
||||
|
||||
[`tt`](https://github.com/simonmichael/hledger/blob/master/bin/tt)
|
||||
is a similar bash multi-script for time reports.
|
||||
|
||||
```cli
|
||||
$ alias t=~/src/hledger/bin/tt
|
||||
$ t
|
||||
--------------------------------------------------------------------------------
|
||||
tt - time tool: run time reports and time-related scripts
|
||||
Usage: tt [COMMAND [ARGS]]
|
||||
Commands:
|
||||
help show this help
|
||||
dash show time dashboard, redisplaying when timelog files change
|
||||
status show current time status
|
||||
what what happened ? Show largest balances first, today and depth 1 by default
|
||||
dots print line of N dots, grouped in 4s (suitable for timedot)
|
||||
x horizontal time summary this year, monthly by default
|
||||
y vertical time summary this year, monthly by default
|
||||
rweeks recent weeks' time budgets
|
||||
weeks this and last week's time budgets
|
||||
hours show a bar chart of daily hours
|
||||
accunused show unused / undeclared accounts
|
||||
accunusedcat show unused / undeclared accounts by category
|
||||
accadd add declarations for all undeclared accounts
|
||||
budgets show monthly time budget performance this year
|
||||
budgetsy show monthly time budget performance this year, vertically
|
||||
budgetsw show weekly time budget performance this year
|
||||
budgetswx show weekly time budget performance this year, horizontally
|
||||
OTHERCMD [ARGS] run other hledger commands on $TIMELOG
|
||||
|
||||
Add hledger options to customise reports.
|
||||
```
|
||||
|
||||
### Justfile
|
||||
|
||||
<https://github.com/casey/just> is a nice tool for organising financial reports and scripts,
|
||||
similar to `make`, but more robust for this use case. I can recommend it.
|
||||
See also [hledger and just](just.md).
|
||||
|
||||
Here is a [Justfile](https://github.com/simonmichael/hledger/blob/master/bin/Justfile)
|
||||
reimplementing the `ft` and `tt` scripts more simply:
|
||||
|
||||
```cli
|
||||
$ brew install just # eg
|
||||
$ alias j=just
|
||||
$ cd ~/finance
|
||||
$ cp ~/src/hledger/bin/Justfile . # or start from scratch: just --init
|
||||
$ j
|
||||
Justfile commands:
|
||||
watch CMD # rerun the given command with watchexec whenever local files change
|
||||
get-csv # download auto-downloadable CSVs (paypal)
|
||||
import-dry # import new downloaded transactions to the main journal, dry run
|
||||
import # import new downloaded transactions to the journal, logging and not printing errors
|
||||
get-prices *PRICEHISTFETCHOPTS # show prices for main commodities (default: today's)
|
||||
bs *HLEDGERARGS # show balance sheet
|
||||
is *HLEDGERARGS # show income statement
|
||||
a *HLEDGERARGS # show assets
|
||||
r *HLEDGERARGS # show revenues
|
||||
x *HLEDGERARGS # show expenses
|
||||
ab *HLEDGERARGS # show assets bar chart
|
||||
rb *HLEDGERARGS # show revenues bar chart
|
||||
xb *HLEDGERARGS # show expenses bar chart
|
||||
al *HLEDGERARGS # show assets line chart
|
||||
rl *HLEDGERARGS # show revenues line chart
|
||||
xl *HLEDGERARGS # show expenses line chart
|
||||
forecast *HLEDGERARGS # print transactions predicted by forecast rules from last week on
|
||||
household *HLEDGERARGS # show a draft month-end household adjustment transaction for last month
|
||||
consulting *HLEDGERARGS # show consulting revenue
|
||||
tdash *HLEDGERARGS # show time dashboard, redisplaying when timelog files change
|
||||
tstatus *HLEDGERARGS # show current time status
|
||||
twhat *HLEDGERARGS # what happened ? Show largest time balances first, today and depth 1 by default
|
||||
tdots N # print line of N dots, grouped in 4s (suitable for timedot)
|
||||
tx *HLEDGERARGS # horizontal time summary this year, monthly by default
|
||||
ty *HLEDGERARGS # vertical time summary this year, monthly by default
|
||||
tweeks *HLEDGERARGS # this and last week's time budgets
|
||||
tweekspast *HLEDGERARGS # recent past weeks' time budgets
|
||||
thours *HLEDGERARGS # show a bar chart of daily hours
|
||||
taccunused *HLEDGERARGS # show unused / undeclared time accounts
|
||||
taccunusedcat *HLEDGERARGS # show unused / undeclared time accounts by category
|
||||
taccadd *HLEDGERARGS # add declarations for all undeclared time accounts
|
||||
tbudgets *HLEDGERARGS # show monthly time budget performance this year
|
||||
tbudgetsy *HLEDGERARGS # show monthly time budget performance this year, vertically
|
||||
tbudgetsw *HLEDGERARGS # show weekly time budget performance this year
|
||||
tbudgetswx *HLEDGERARGS # show weekly time budget performance this year, horizontally
|
||||
```
|
||||
|
||||
### watchaccounts
|
||||
|
||||
[`watchaccounts`](https://github.com/simonmichael/hledger/blob/master/bin/watchaccounts)
|
||||
shows hledger account names, updating on file change under the current directory.
|
||||
Arguments are passed to the `hledger accounts` command. Useful when cleaning up accounts.
|
||||
```cli
|
||||
$ watchaccounts expenses -2
|
||||
$ watchaccounts -f time.journal client1 date:thismonth -l
|
||||
```
|
||||
|
||||
### sortandmergepostings
|
||||
|
||||
[`sortandmergepostings`](https://github.com/simonmichael/hledger/blob/master/bin/sortandmergepostings)
|
||||
is an adventuresome AWK script intended to clean up and merge similar postings in a transaction
|
||||
(see [original discussion](https://unix.stackexchange.com/questions/526995/re-order-lines-and-merge-others-based-on-a-specific-criteria/527004)).
|
||||
It sorts postings so that positive ones are first, negative ones last.
|
||||
Within each sign, postings are sorted by commodity.
|
||||
Within each commodity group, postings are sorted by amount.
|
||||
Among identical amounts in the same group, postings are sorted alphabetically by account name.
|
||||
Once sorted, if there are multiple postings to the same account in the same direction with the same commodity and comments, it tries to merge them (by leaving some amounts blank).
|
||||
Subsequently piping the output to `hledger print` can recalculate the missing amounts.
|
||||
Multiple runs might be needed to clean up all duplicates.
|
||||
```cli
|
||||
$ sortandmergepostings input.journal | hledger -f - print -x
|
||||
```
|
||||
|
||||
### hledger-simplebal
|
||||
|
||||
[`hledger-simplebal`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-simplebal)
|
||||
@ -262,197 +60,57 @@ This and the other "hledger-" scripts are add-on commands.
|
||||
$ hledger simplebal
|
||||
```
|
||||
|
||||
### hledger-bar
|
||||
|
||||
[`hledger-bar`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-bar)
|
||||
prints quick bar charts in the terminal.
|
||||
|
||||
```cli
|
||||
$ hledger bar reimbursement
|
||||
2023-01 ++++++
|
||||
2023-02 ++
|
||||
2023-03 ++
|
||||
2023-04 -------
|
||||
```
|
||||
|
||||
```cli
|
||||
$ hledger bar # show help
|
||||
$ hledger bar food # monthly food expenses
|
||||
$ hledger bar 1 --count food # monthly food posting counts
|
||||
$ hledger bar type:c not:tag:clopen cur:\\\\$ -W # weekly cashflow, $ only
|
||||
$ hledger bar type:al not:tag:clopen cur:\\\\$ # monthly net worth change ($)
|
||||
$ hledger bar type:rx --invert cur:\\\\$ # monthly profit/loss ($)
|
||||
$ hledger bar -v 1 -f $TIMELOG -D # daily hours, with numbers
|
||||
```
|
||||
(or with hledger <1.50: `hledger bar -- ...`)
|
||||
|
||||
### hledger-check-buynothing
|
||||
|
||||
[`hledger-check-buynothing`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-check-buynothing)
|
||||
checks for no activity in Expense accounts on Buy Nothing Day (or other period).
|
||||
|
||||
### hledger-git
|
||||
|
||||
[`hledger-git`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-git)
|
||||
provides easy version control for your journal files, using [git](https://git-scm.com).
|
||||
Run it with no arguments for help.
|
||||
provides easy version control for your journal files, using git. Run it with no arguments for help.
|
||||
```cli
|
||||
$ hledger git log
|
||||
$ hledger git status
|
||||
$ hledger git record [MSG]
|
||||
```
|
||||
|
||||
### hledger-jj
|
||||
|
||||
[`hledger-jj`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-jj)
|
||||
provides easy version control for your journal files, using [jj](https://jj-vcs.github.io)
|
||||
(and a git repo).
|
||||
This is newer and better than hledger-git and hledger-pijul.
|
||||
Unlike most shell scripts here, it requires [ysh](https://oils.pub).
|
||||
```cli
|
||||
$ hledger jj log
|
||||
$ hledger jj status
|
||||
$ hledger jj diff
|
||||
$ hledger jj commit [MSG]
|
||||
```
|
||||
|
||||
### hledger-pijul
|
||||
|
||||
[`hledger-pijul`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-pijul)
|
||||
provides easy version control for your journal files, using the [pijul](https://pijul.org) version control system.
|
||||
provides the same thing using the [pijul](https://pijul.org) version control system..
|
||||
```cli
|
||||
$ hledger pijul log
|
||||
$ hledger pijul status
|
||||
$ hledger pijul record [MSG]
|
||||
```
|
||||
|
||||
### hledger-dc
|
||||
## hledger-integrated scripts
|
||||
|
||||
[`hledger-dc`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-dc)
|
||||
reads journal files which use a Dr/Cr notation instead of/in addition to amount signs:
|
||||
```journal
|
||||
2025-01-01 salary
|
||||
Cr revenues 800 USD
|
||||
Dr assets
|
||||
```
|
||||
These call hledger as a Haskell library, and so must be written in
|
||||
Haskell. They can use hledger's internal data types and can do
|
||||
anything hledger's built-in commands can do:
|
||||
|
||||
### hledger-edit
|
||||
### hledger-addon-example
|
||||
|
||||
The [hledger-utils python package](https://pypi.org/project/hledger-utils/) provides
|
||||
a `hledger-edit` command to edit the queried transactions in your `$EDITOR` no matter what file they reside in.
|
||||
[`hledger-addon-example.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-addon-example.hs)
|
||||
is a starter template for a common type of script: a hledger-integrated add-on command.
|
||||
It has the same structure as most of the other add-ons here:
|
||||
- implemented as a stack script for robustness
|
||||
- provides command line help
|
||||
- accepts common hledger options
|
||||
|
||||
Install or upgrade:
|
||||
Further cleanup and documentation is ongoing.
|
||||
|
||||
### hledger-print-location
|
||||
|
||||
[`hledger-print-location.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-print-location.hs)
|
||||
is a variant of hledger's `print` command
|
||||
that adds the file and line number to every transaction, as a tag:
|
||||
```cli
|
||||
$ pip install -U hledger-utils # might be slightly different on your system
|
||||
$ hledger print-location -f hledger/examples/sample.journal desc:eat
|
||||
2008/06/03 * eat & shop
|
||||
; location: /Users/simon/src/hledger/examples/sample.journal:30
|
||||
expenses:food $1
|
||||
expenses:supplies $1
|
||||
assets:cash
|
||||
```
|
||||
|
||||
Examples:
|
||||
```cli
|
||||
# Opens your $EDITOR or $VISUAL with only costs in Florida
|
||||
# (if you named and tagged them like that)
|
||||
# edit the transactions, save and exit your editor,
|
||||
# then the changes are distributed to the original files
|
||||
$ hledger edit Cost tag:location=Florida
|
||||
```
|
||||
```
|
||||
# Automate changes by setting `$EDITOR` to a script
|
||||
# (here all food we had on that one day in Florida was Fast Food 🌭 and we initially forgot to write that)
|
||||
EDITOR='perl -pi -e "s|Cost:Food|Cost:Food:Fast Food|g"' hledger edit tag:location=Florida date:2022-12-20
|
||||
```
|
||||
[](https://asciinema.org/a/549559)
|
||||
|
||||
### hledger-plot
|
||||
|
||||
The [hledger-utils python package](https://pypi.org/project/hledger-utils/) provides
|
||||
a `hledger-plot` command for generating charts with matplotlib.
|
||||
|
||||
Install or upgrade:
|
||||
```cli
|
||||
$ pip install -U hledger-utils # might be slightly different on your system
|
||||
```
|
||||
Examples:
|
||||
```
|
||||
$ hledger-plot -h
|
||||
$ hledger plot bal -DH ^Assets -2
|
||||
```
|
||||
(or with hledger <1.50: `hledger plot -- ...`)
|
||||
|
||||
### hledger-lots
|
||||
|
||||
[`hledger-lots`](https://github.com/edkedk99/hledger-lots)
|
||||
shows a lots report, or generates a lot sale transaction, using FIFO strategy
|
||||
(and without needing subaccounts for lots).
|
||||
|
||||
Install or upgrade:
|
||||
```
|
||||
$ pip install -U hledger-lots
|
||||
```
|
||||
Examples:
|
||||
```cli
|
||||
$ hledger lots
|
||||
$ hledger lots view
|
||||
$ hledger lots list
|
||||
```
|
||||
|
||||
### hledger-report1.sh
|
||||
|
||||
[hledger-report1.sh](https://github.com/simonmichael/hledger/blob/master/bin/hledger-report1.sh)
|
||||
is a custom compound report done in shell. See also hledger-report1.hs.
|
||||
|
||||
### hledger-timedothm
|
||||
|
||||
[`hledger-timedothm`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-timedothm)
|
||||
reads timedot files which support HOURS:MINUTES notation:
|
||||
```timedot
|
||||
2025-09-27
|
||||
time ..
|
||||
time 0.5
|
||||
time 30m
|
||||
time 0:30 ; new H:M syntax
|
||||
```
|
||||
and it displays amounts in that notation:
|
||||
```cli
|
||||
$ hledger timedothm sample.timedothm reg -w80
|
||||
2025-09-27 (time) 0:30 0:30
|
||||
(time) 0:30 1:00
|
||||
(time) 0:30 1:30
|
||||
(time) 0:30 2:00
|
||||
```
|
||||
|
||||
### hledgerj1
|
||||
|
||||
[`hledgerj1`](https://github.com/simonmichael/hledger/blob/master/bin/hledgerj1)
|
||||
is a small example of a wrapper script that preprocesses the journal,
|
||||
converting it from a custom format, in this case a one-line journal format
|
||||
where slash represents newline. Eg:
|
||||
```text
|
||||
2025-01-04 shopping / assets:bank:checking / expenses:food 200 USD / expenses:supplies 50 USD
|
||||
```
|
||||
```cli
|
||||
$ hledgerj1 a.j1 print
|
||||
2025-01-04 shopping
|
||||
assets:bank:checking
|
||||
expenses:food 200 USD
|
||||
expenses:supplies 50 USD
|
||||
|
||||
```
|
||||
|
||||
## hledger haskell scripts
|
||||
|
||||
These scripts are written in Haskell and use hledger's haskell API (by importing the `hledger` or `hledger-lib` haskell libraries).
|
||||
They are often [stack scripts](https://docs.haskellstack.org/en/stable/topics/scripts).
|
||||
They can do anything hledger's builtin commands can do, and are usually more robust than command line scripts.
|
||||
Some builtin commands were first developed as standalone haskell scripts.
|
||||
|
||||
### hledger-script-example
|
||||
|
||||
[`hledger-script-example.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-script-example.hs)
|
||||
is a template for writing your own hledger-integrated add-on command.
|
||||
It has the same structure as most of the add-ons here:
|
||||
- a stack script for robustness
|
||||
- providing command line help
|
||||
- accepting common hledger options
|
||||
|
||||
### hledger-swap-dates
|
||||
|
||||
[`hledger-swap-dates.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-swap-dates.hs)
|
||||
@ -465,18 +123,6 @@ interprets all tag values containing a `/` (forward slash) as file paths, and ch
|
||||
[`hledger-check-tagfiles.cabal.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-check-tagfiles.cabal.hs)
|
||||
is the same command implemented as a cabal script rather than a stack script.
|
||||
|
||||
### hledger-register-max
|
||||
|
||||
[`hledger-register-max.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-register-max.hs)
|
||||
runs a register report and prints the posting with largest historical balance.
|
||||
|
||||
```cli
|
||||
$ hledger-register-max -f examples/bcexample.hledger checking
|
||||
2013-01-03 Hoogle | Payroll Assets:US:BofA:Checking 1350.60 USD 8799.22 USD
|
||||
$ hledger register-max -f examples/bcexample.hledger checking
|
||||
2013-01-03 Hoogle | Payroll Assets:US:BofA:Checking 1350.60 USD 8799.22 USD
|
||||
```
|
||||
|
||||
### hledger-check-postable
|
||||
|
||||
[`hledger-check-postable.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-check-postable.hs)
|
||||
@ -504,151 +150,129 @@ shows balance reports for two different periods side by side.
|
||||
[`hledger-balance-as-budget.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-balance-as-budget.hs)
|
||||
uses one balance report to set budget goals for another balance report.
|
||||
|
||||
This is useful for compare-and-contrast reports. You can, for example, use a previous year as a budget for this year, and see
|
||||
how this year spending compares to your past spending.
|
||||
|
||||
### hledger-balance-as-budget-multi
|
||||
|
||||
[`hledger-balance-as-budget.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-balance-as-budget-multi.hs)
|
||||
uses one balance report to set budget goals for another balance report, and allows you to run multiple balance commands on them.
|
||||
|
||||
Like `hledger run`, this will load journals only once, and will be significantly faster than calling `hledger-balance-as-budget`
|
||||
multiple times.
|
||||
|
||||
### hledger-smooth
|
||||
|
||||
[`hledger-smooth.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-smooth.hs)
|
||||
is an incomplete attempt at automatically splitting infrequent/irregular transactions.
|
||||
|
||||
### hledger-move
|
||||
## hledger-related scripts
|
||||
|
||||
[`hledger-move.hs`](https://github.com/simonmichael/hledger/blob/master/bin/hledger-move.hs)
|
||||
helps make subaccount/cost-preserving transfers.
|
||||
These don't run hledger, but are probably related to it in some way:
|
||||
|
||||
### hledger-report1.hs
|
||||
### paypaljson
|
||||
|
||||
[hledger-report1.hs](https://github.com/simonmichael/hledger/blob/master/bin/hledger-report1.hs)
|
||||
is a custom compound report done in haskell. See also hledger-report1.sh.
|
||||
[`paypaljson`](https://github.com/simonmichael/hledger/blob/master/bin/paypaljson)
|
||||
downloads the last 30 days of Paypal transactions (requires a free developer account & API key).
|
||||
|
||||
### hledger-txnsbycat.hs
|
||||
### paypaljson2csv
|
||||
|
||||
[hledger-txnsbycat.hs](https://github.com/brianhv/hledger-scripts/blob/main/hledger-txnsbycat.hs)
|
||||
is a mixture of a balance report and a register report; it shows each account's transactions
|
||||
under the account's balance.
|
||||
[`paypaljson2csv`](https://github.com/simonmichael/hledger/blob/master/bin/paypaljson2csv) (python)
|
||||
converts `paypaljson`'s output to CSV, with format similar to Paypal's manually-downloaded CSV.
|
||||
|
||||
## Add-ons
|
||||
## More scripts
|
||||
|
||||
These are some official and third-party add-ons you can install as compiled programs:
|
||||
|
||||
### hledger-ui
|
||||
|
||||
[hledger-ui](hledger-ui.html) is hledger's official terminal UI. It allows faster browsing of your accounts and transactions.
|
||||
|
||||
### hledger-web
|
||||
|
||||
[hledger-web](hledger-web.html) is hledger's official web UI. It allows data entry and simple reports in a web browser. It's good for non-command-line users.
|
||||
|
||||
### hledger-iadd
|
||||
|
||||
[hledger-iadd](https://hackage.haskell.org/package/hledger-iadd) is a popular alternative to the builtin `add` command.
|
||||
|
||||
### hledger-interest
|
||||
|
||||
[hledger-interest](https://hackage.haskell.org/package/hledger-interest) generates interest transactions.
|
||||
|
||||
Notes (as of 1.6.7):
|
||||
|
||||
- Use the <https://github.com/peti/hledger-interest#readme>, it's better than the command line help or hackage description.
|
||||
- hledger-interest silently ignores $LEDGER_FILE, so be sure to provide a file name explicitly with -f.
|
||||
|
||||
### hledger-sankeymatic
|
||||
|
||||
[hledger-sankeymatic](https://github.com/victormihalache/hledger-sankeymatic) helps export hledger data to make flow diagrams at <https://sankeymatic.com>.
|
||||
See also [Charts](charts.md).
|
||||
|
||||
### Other
|
||||
|
||||
- [hledger-stockquotes](https://hackage.haskell.org/package/hledger-stockquotes) fetches market prices. Not widely used, use pricehist instead.
|
||||
- [hledger-diff](https://hackage.haskell.org/package/hledger-diff) compares two journal files. It's now built in to hledger, so you don't need it.
|
||||
[plaintextaccounting.org](https://plaintextaccounting.org) has a longer list of PTA tools, not hledger-specific.
|
||||
|
||||
|
||||
## Installing the bin scripts
|
||||
|
||||
## How to...
|
||||
|
||||
### Install scripts
|
||||
|
||||
To use these bin scripts you must ensure they are in your $PATH and runnable:
|
||||
|
||||
- Shell scripts: you may need [bash](https://www.gnu.org/software/bash), or to adapt the scripts for your shell.
|
||||
- Python scripts: you'll need python 3 and pip.
|
||||
- Haskell scripts: you'll need [stack](http://haskellstack.org).
|
||||
Or if you know how, you can make them cabal scripts, or install their dependencies manually and use runghc/ghc.
|
||||
|
||||
Here's a suggested install procedure:
|
||||
These [bin](https://github.com/simonmichael/hledger/tree/master/bin) scripts
|
||||
are not automatically installed along with hledger;
|
||||
if you want them you must download them separately. Here's a suggested method:
|
||||
|
||||
```cli
|
||||
# Go to wherever you keep financial files:
|
||||
# go to wherever you keep financial files
|
||||
$ cd ~/finance
|
||||
|
||||
# Get the hledger repo
|
||||
# the fast way, without version control:
|
||||
# get the hledger repo (the fast way, without version control)
|
||||
$ curl -LOJ https://github.com/simonmichael/hledger/archive/refs/heads/master.zip && unzip hledger-master.zip && mv hledger-master hledger
|
||||
# or the slow way, with version control for easy diffing/updating/contributing
|
||||
# git clone https://github.com/simonmichael/hledger
|
||||
|
||||
# Make a more convenient symlink to the bin directory:
|
||||
# (or the slow way, with version control for easy diffing/updating/contributing)
|
||||
# git clone https://github.com/simonmichael/hledger.git
|
||||
|
||||
# make a more convenient symlink to the bin directory
|
||||
$ ln -s hledger/bin
|
||||
|
||||
# Add the bin directory to your PATH. Eg as a bash user:
|
||||
# add the bin directory to your PATH. Eg as a bash user:
|
||||
$ echo "export PATH=$PATH:$PWD/bin" >>~/.bash_profile"
|
||||
$ export PATH=$PATH:$PWD/bin
|
||||
|
||||
# Optionally, compile all haskell scripts for faster startup:
|
||||
$ cd hledger; bin/compile.sh
|
||||
|
||||
# Optionally, install the python scripts:
|
||||
$ pip install -U hledger-utils
|
||||
$ pip install -U hledger-lots
|
||||
|
||||
# Check that hledger's command list now includes the bin scripts.
|
||||
# Eg "check-fancyassertions" and "swap-dates" should be listed:
|
||||
# check that hledger's command list now shows the hledger-* scripts
|
||||
# (they will be listed with a + prefix):
|
||||
$ hledger
|
||||
```
|
||||
|
||||
Scripts with no file extension are mostly [bash] scripts except where noted.
|
||||
if you don't want to install bash you might have to adapt them to your shell.
|
||||
|
||||
Scripts with a `.hs` file extension are usually [stack scripts], requiring [stack] to run.
|
||||
If you don't want to install stack you can adapt them to be cabal scripts,
|
||||
or install their required libraries yourself and run/compile them with suitable runghc/ghc commands.
|
||||
See also [Working with hledger-*.hs scripts](#working-with-hledger-hs-scripts) below.
|
||||
|
||||
[bash]: https://www.gnu.org/software/bash
|
||||
[stack]: https://haskellstack.org
|
||||
[stack scripts]: https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter
|
||||
|
||||
## Working with hledger-*.hs scripts
|
||||
|
||||
The hledger-*.hs [add-on commands] are mostly implemented as [stack]
|
||||
runghc scripts. See the comments in hledger-check-fancyassertions.hs
|
||||
for more about how to run or compile them. Short version: run
|
||||
bin/compile.sh to compile all scripts, and add this directory to your
|
||||
$PATH so they show up in hledger's command list.
|
||||
|
||||
[add-on commands]: http://hledger.org/hledger.html#add-on-commands
|
||||
[stack]: https://www.fpcomplete.com/haskell/get-started
|
||||
[cabal]: https://www.haskell.org/cabal
|
||||
|
||||
How to:
|
||||
|
||||
### Install all add-on commands
|
||||
|
||||
$ git clone https://github.com/simonmichael/hledger
|
||||
$ hledger/bin/compile.sh
|
||||
$ export PATH=$PATH:$PWD/hledger/bin
|
||||
|
||||
$ hledger # scripts now appear in commands list
|
||||
$ hledger-print-location --help # run a script directly
|
||||
$ hledger print-location -- --help # or run it via hledger. -- is needed before script options
|
||||
|
||||
### Create a new script
|
||||
|
||||
To create a new hledger-integrated script, copy hledger-script-example.hs.
|
||||
On unix, the new script should be marked executable. This should do it:
|
||||
The example scripts follow a template that implements hledger's
|
||||
standard command line options and help, so it's a good idea to use one
|
||||
as your starting point. The hledger- naming is not required, but it
|
||||
causes scripts to show up in the hledger commands list. On unix,
|
||||
your new script should be marked executable. This should do it:
|
||||
|
||||
$ cd bin
|
||||
$ cp hledger-script-example.hs hledger-cmd.hs # replace cmd with your command name
|
||||
# edit hledger-cmd.hs, updating at least the command name and help
|
||||
$ stack install safe text # ensure the script's dependencies are installed
|
||||
$ hledger-cmd.hs --help
|
||||
cmd [OPTIONS]
|
||||
My new cmd command.
|
||||
$ cd hledger
|
||||
$ cp bin/hledger-swap-dates.hs bin/hledger-foo.hs # and edit, at least the command name and help
|
||||
$ stack install string-qq # ensure any extra script deps are installed
|
||||
$ bin/hledger-cmd.hs --help
|
||||
foo [OPTIONS]
|
||||
My new foo command.
|
||||
...
|
||||
$ stack ghc hledger-cmd.hs # optionally compile for faster startup/durability
|
||||
$ hledger cmd --help
|
||||
cmd [OPTIONS]
|
||||
My new cmd command.
|
||||
$ stack ghc bin/hledger-cmd.hs
|
||||
$ hledger foo -- --help
|
||||
foo [OPTIONS]
|
||||
My new foo command.
|
||||
...
|
||||
|
||||
### Run ghcid on a script
|
||||
|
||||
$ stack exec --package 'safe text' -- ghcid hledger-cmd.hs
|
||||
$ stack install string-qq # ensure any extra script deps are installed
|
||||
$ stack exec -- ghcid bin/hledger-foo.hs
|
||||
...
|
||||
Ok, one module loaded.
|
||||
All good (1 module, at 10:50:48)
|
||||
|
||||
### Run ghci on a script
|
||||
|
||||
$ stack ghci --package 'safe text' hledger-cmd.hs
|
||||
$ stack install string-qq # ensure any extra script deps are installed
|
||||
$ stack ghci bin/hledger-foo.hs
|
||||
...
|
||||
Ok, one module loaded.
|
||||
...
|
||||
ghci>
|
||||
|
||||
### Learn more about scripting hledger
|
||||
|
||||
See [Scripting hledger].
|
||||
|
||||
194
bin/_hledger-chart.hs
Executable file
194
bin/_hledger-chart.hs
Executable file
@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env stack
|
||||
{- stack runghc --verbosity info --resolver lts-9.3
|
||||
--package hledger
|
||||
--package Chart
|
||||
--package Chart-diagrams
|
||||
--package cmdargs
|
||||
--package colour
|
||||
--package data-default
|
||||
--package here
|
||||
--package safe
|
||||
--package text
|
||||
-}
|
||||
{- stackage nightly:
|
||||
--package SVGFonts
|
||||
--package diagrams-core
|
||||
--package diagrams-lib
|
||||
--package diagrams-postscript
|
||||
--package diagrams-svg
|
||||
--package svg-builder
|
||||
--package cereal-vector
|
||||
--package dual-tree
|
||||
--package diagrams-solve
|
||||
--package statestack
|
||||
-}
|
||||
|
||||
{-# OPTIONS_GHC -Wno-missing-signatures -Wno-unused-do-bind #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
import Control.Monad
|
||||
import Data.Colour
|
||||
import Data.Colour.Names hiding (red,green)
|
||||
import Data.Colour.RGBSpace
|
||||
import Data.Colour.RGBSpace.HSL (hsl)
|
||||
import Data.Colour.SRGB.Linear (rgb)
|
||||
import Data.Default
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.Ord
|
||||
import Data.String.Here
|
||||
import qualified Data.Text as T
|
||||
import Graphics.Rendering.Chart
|
||||
import Graphics.Rendering.Chart.Backend.Diagrams
|
||||
import Safe
|
||||
import System.Console.CmdArgs.Explicit
|
||||
import System.Exit
|
||||
|
||||
import Hledger.Cli hiding (num,green,is,balance)
|
||||
|
||||
defchartoutput = "hledger.svg"
|
||||
defchartitems = 10
|
||||
defchartsize = "600x400"
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
cmdmode = hledgerCommandMode
|
||||
[here| chart
|
||||
Generate a pie chart for the top account balances with the same sign,
|
||||
in SVG format.
|
||||
|
||||
Based on the old hledger-chart package, this is not yet useful.
|
||||
It's supposed to show only balances of one sign, but this might be broken.
|
||||
|]
|
||||
[flagReq ["chart-output","o"] (\s opts -> Right $ setopt "chart-output" s opts) "IMGFILE" ("output filename (default: "++defchartoutput++")")
|
||||
,flagReq ["chart-items"] (\s opts -> Right $ setopt "chart-items" s opts) "N" ("number of accounts to show (default: "++show defchartitems++")")
|
||||
,flagReq ["chart-size"] (\s opts -> Right $ setopt "chart-size" s opts) "WIDTHxHEIGHT" ("image size (default: "++defchartsize++")")
|
||||
] [generalflagsgroup1]
|
||||
[]
|
||||
([], Just $ argsFlag "[QUERY]")
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
data ChartOpts = ChartOpts {
|
||||
chart_output_ :: FilePath
|
||||
,chart_items_ :: Int
|
||||
,chart_size_ :: String
|
||||
,cliopts_ :: CliOpts
|
||||
} deriving (Show)
|
||||
|
||||
defchartopts = ChartOpts
|
||||
def
|
||||
def
|
||||
def
|
||||
defcliopts
|
||||
|
||||
getHledgerChartOpts :: IO ChartOpts
|
||||
getHledgerChartOpts = do
|
||||
cliopts <- getHledgerCliOpts cmdmode
|
||||
return defchartopts {
|
||||
chart_output_ = fromMaybe defchartoutput $ maybestringopt "debug-chart" $ rawopts_ cliopts
|
||||
,chart_items_ = fromMaybe defchartitems $ maybeintopt "debug-items" $ rawopts_ cliopts
|
||||
,chart_size_ = fromMaybe defchartsize $ maybestringopt "debug-size" $ rawopts_ cliopts
|
||||
,cliopts_ = cliopts
|
||||
}
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
chopts <- getHledgerChartOpts
|
||||
d <- getCurrentDay
|
||||
j <- defaultJournal
|
||||
let ropts = (reportopts_ $ cliopts_ chopts)
|
||||
let balreport = balanceReportFromMultiBalanceReport ropts (queryFromOpts d ropts) j
|
||||
let go -- | "--help" `elem` (rawopts_ $ cliopts_ chopts) = putStr (showModeHelp chartmode) >> exitSuccess
|
||||
-- | "--version" `elem` (rawopts_ $ cliopts_ chopts) = putStrLn progversion >> exitSuccess
|
||||
= withJournalAndChartOptsDo chopts (writeChart balreport)
|
||||
go
|
||||
|
||||
-- copied from hledger-web
|
||||
withJournalAndChartOptsDo :: ChartOpts -> (ChartOpts -> Journal -> IO ()) -> IO ()
|
||||
withJournalAndChartOptsDo opts cmd = do
|
||||
f <- head `fmap` journalFilePathFromOpts (cliopts_ opts)
|
||||
readJournalFile Nothing Nothing True f >>=
|
||||
either error' (cmd opts . journalApplyAliases (aliasesFromOpts $ cliopts_ opts))
|
||||
|
||||
-- | Generate an image with the pie chart and write it to a file
|
||||
writeChart :: BalanceReport -> ChartOpts -> Journal -> IO ()
|
||||
writeChart balreport opts j = do
|
||||
-- d <- getCurrentDay
|
||||
if null $ jtxns j
|
||||
then putStrLn "This journal has no transactions, can't make a chart." >> exitFailure
|
||||
else do
|
||||
let chart = genPie opts balreport
|
||||
let fileoptions = def -- FileOptions (fromIntegral w, fromIntegral h) SVG loadSansSerifFonts
|
||||
renderableToFile fileoptions filename (toRenderable chart)
|
||||
return ()
|
||||
where
|
||||
filename = chart_output_ opts
|
||||
-- (w,h) = parseSize $ chart_size_ opts
|
||||
-- ropts = reportopts_ $ cliopts_ opts
|
||||
|
||||
-- | Parse image size from a command-line option
|
||||
-- parseSize :: String -> (Int,Int)
|
||||
-- parseSize str = (read w, read h)
|
||||
-- where
|
||||
-- x = fromMaybe (error' "Size should be in WIDTHxHEIGHT format") $ findIndex (=='x') str
|
||||
-- (w,_:h) = splitAt x str
|
||||
|
||||
-- | Generate pie chart
|
||||
genPie :: ChartOpts -> BalanceReport -> PieLayout
|
||||
genPie opts (items, _total) = def { _pie_background = solidFillStyle $ opaque $ white
|
||||
, _pie_plot = pie_chart }
|
||||
where
|
||||
pie_chart = def { _pie_data = map (uncurry accountPieItem) chartitems
|
||||
, _pie_start_angle = (-90)
|
||||
, _pie_colors = mkColours hue
|
||||
, _pie_label_style = def{_font_size=12}
|
||||
}
|
||||
chartitems = dbg1 "chart" $ top num samesignitems :: [(AccountName, Double)]
|
||||
(samesignitems, sign) = sameSignNonZero items
|
||||
top n t = topn ++ [other]
|
||||
where
|
||||
(topn,rest) = splitAt n $ sortBy (flip $ comparing snd) t
|
||||
other = ("other", sum $ map snd rest)
|
||||
num = chart_items_ opts
|
||||
hue = if sign > 0 then red else green where (red, green) = (0, 110)
|
||||
-- copts = cliopts_ opts
|
||||
-- ropts = reportopts_ copts
|
||||
|
||||
-- | Select the nonzero items with same sign as the first, and make
|
||||
-- them positive. Also return a 1 or -1 corresponding to the original sign.
|
||||
sameSignNonZero :: [BalanceReportItem] -> ([(AccountName, Double)], Int)
|
||||
sameSignNonZero is
|
||||
| null nzs = ([], 1)
|
||||
| otherwise = (map pos $ filter (test.fourth4) nzs, sign)
|
||||
where
|
||||
nzs = filter ((/=0).fourth4) is
|
||||
pos (acct,_,_,as) = (acct, abs $ read $ show $ maybe 0 aquantity $ headMay $ amounts as)
|
||||
sign = if fourth4 (head nzs) >= 0 then 1 else (-1)
|
||||
test = if sign > 0 then (>0) else (<0)
|
||||
|
||||
-- | Convert all quantities of MixedAccount to a single commodity
|
||||
-- amountValue :: MixedAmount -> Double
|
||||
-- amountValue = quantity . mixedAmountWithCommodity unknown
|
||||
|
||||
-- | Generate a tree of account names together with their balances.
|
||||
-- The balance of account is decremented by the balance of its subaccounts
|
||||
-- which are drawn on the chart.
|
||||
-- balances :: Tree Account -> Tree (AccountName, Double)
|
||||
-- balances (Node rootAcc subAccs) = Node newroot newsubs
|
||||
-- where
|
||||
-- newroot = (aname rootAcc,
|
||||
-- amountValue $
|
||||
-- aibalance rootAcc - (sum . map (aibalance . root)) subAccs)
|
||||
-- newsubs = map balances subAccs
|
||||
|
||||
-- | Build a single pie chart item
|
||||
accountPieItem :: AccountName -> Double -> PieItem
|
||||
accountPieItem accname = PieItem (T.unpack accname) offset where offset = 0
|
||||
|
||||
-- | Generate an infinite color list suitable for charts.
|
||||
mkColours :: Double -> [AlphaColour Double]
|
||||
mkColours hue = cycle $ [opaque $ rgbToColour $ hsl h s l | (h,s,l) <- liftM3 (,,)
|
||||
[hue] [0.7] [0.1,0.2..0.7] ]
|
||||
|
||||
rgbToColour :: (Fractional a) => RGB a -> Colour a
|
||||
rgbToColour (RGB r g b) = rgb r g b
|
||||
273
bin/bashrc
273
bin/bashrc
@ -1,155 +1,42 @@
|
||||
# Some hledger/PTA-related bash scripts. See also Justfile.
|
||||
# Some hledger/PTA-related bash scripts.
|
||||
|
||||
export FIRSTYEAR="${FIRSTYEAR:-2020}"
|
||||
export YEAR="${YEAR:-$(date +%Y)}"
|
||||
export FINDIR=~/finance
|
||||
export LEDGER_FILE=$FINDIR/$YEAR/$YEAR.journal
|
||||
export LEDGER_FILE=$FINDIR/2022.journal
|
||||
|
||||
alias all='hledger -f $FINDIR/all.journal'
|
||||
alias 2020='hledger -f $FINDIR/2020/2020.journal'
|
||||
alias 2021='hledger -f $FINDIR/2021/2021.journal'
|
||||
alias 2022='hledger -f $FINDIR/2022/2022.journal'
|
||||
alias 2023='hledger -f $FINDIR/2023/2023.journal'
|
||||
alias 2024='hledger -f $FINDIR/2024/2024.journal'
|
||||
alias 2025='hledger -f $FINDIR/2024/2025.journal'
|
||||
alias 2026='hledger -f $FINDIR/2024/2026.journal'
|
||||
alias jan="hledger -p jan"
|
||||
alias feb="hledger -p feb"
|
||||
alias mar="hledger -p mar"
|
||||
alias apr="hledger -p apr"
|
||||
alias may="hledger -p may"
|
||||
alias jun="hledger -p jun"
|
||||
alias jul="hledger -p jul"
|
||||
alias aug="hledger -p aug"
|
||||
alias sep="hledger -p sep"
|
||||
alias oct="hledger -p oct"
|
||||
alias nov="hledger -p nov"
|
||||
alias dec="hledger -p dec"
|
||||
|
||||
alias accounts='hledger accounts'
|
||||
alias activity='hledger activity'
|
||||
alias add='hledger add'
|
||||
alias areg='hledger aregister'
|
||||
alias bal='hledger balance'
|
||||
alias bar='hledger bar'
|
||||
alias bs='hledger balancesheet'
|
||||
alias bse='hledger balancesheetequity'
|
||||
alias budget='hledger balance --budget'
|
||||
alias cf='hledger cashflow'
|
||||
alias check='hledger check'
|
||||
alias close='hledger close'
|
||||
alias codes='hledger codes'
|
||||
alias commodities='hledger commodities'
|
||||
alias desc='hledger descriptions'
|
||||
alias files='hledger files'
|
||||
alias iadd='hledger-iadd'
|
||||
alias interest='hledger interest'
|
||||
alias import='hledger import'
|
||||
alias is='hledger incomestatement'
|
||||
alias lots='hledger lots'
|
||||
alias notes='hledger notes'
|
||||
alias payees='hledger payees'
|
||||
alias plot='hledger plot'
|
||||
alias prices='hledger prices'
|
||||
alias print='hledger print'
|
||||
alias reg='hledger register'
|
||||
alias repl='hledger repl'
|
||||
alias rewrite='hledger rewrite'
|
||||
alias roi='hledger roi'
|
||||
alias run='hledger run'
|
||||
alias stats='hledger stats'
|
||||
alias tags='hledger tags'
|
||||
alias ui='hledger ui'
|
||||
alias web='hledger web'
|
||||
|
||||
alias bser='hledger -f $LEDGER_FILE -f <(hledger close --retain) bse'
|
||||
alias f=$FINDIR/Justfile
|
||||
alias hl='hledger'
|
||||
|
||||
# query hledger with sqlite
|
||||
hq() {
|
||||
(hledger print -O sql; echo "$1") | sqlite3 -column -header;
|
||||
fin() { # fin [PAT] - list financial scripts in $FINDIR/bin/[bashrc] (default: ~/finance)
|
||||
(cd ${FINDIR:-~/finance} || exit; bin "$@")
|
||||
}
|
||||
|
||||
# list likely hledger-readable files in current directory
|
||||
hledgerfiles() {
|
||||
ls $@ *.{journal,j,timelog,csv,ledger,lgr,dat} 2>/dev/null
|
||||
}
|
||||
|
||||
# helpers for working with yearly files.
|
||||
|
||||
yearfiles() { # yearfiles [N] - list all or the last N yearly journal files
|
||||
N="$1"; shift
|
||||
YEAR=$(date +%Y)
|
||||
if [[ -n "$N" ]]; then
|
||||
START=$(( "$YEAR" - "$N" + 1))
|
||||
else
|
||||
START=$FIRSTYEAR
|
||||
fi
|
||||
for ((y="$START"; y<="$YEAR"; y++)); do
|
||||
echo "$FINDIR/$y/$y.journal"
|
||||
bin() { # bin [PAT] - list aliases, functions, scripts in ./bin/[bashrc]
|
||||
PAT="${1-.}"
|
||||
BINDIR=./bin
|
||||
BASHRC=$BINDIR/bashrc
|
||||
( [[ -e $BASHRC ]] && grep -E '^(alias|function|\w+\(\))' $BASHRC \
|
||||
| gnused -E -e 's/^alias *//' -e 's/^(function )?(\w+) *\(\) *\{/\2()/' -e 's/#/\t#/' \
|
||||
# -e "s/=('[^']+'|\"[^\"]+\"|\w+)/=/" # uncomment to hide alias definitions
|
||||
[[ -d $BINDIR ]] && for F in "$BINDIR"/*; do
|
||||
[[ -x $F ]] || continue
|
||||
printf '%s ' "$(basename "$F")"
|
||||
(grep -IE '^(#|--) ' "$F" 2>/dev/null | gnused -E 's/(#|--)/\t#/'; echo) | head -1
|
||||
done
|
||||
) | grep -iE "$PAT" \
|
||||
#| sort -b -k2 # uncomment to sort by name
|
||||
}
|
||||
|
||||
yearfileopts() { # yearfileopts [N] - print -f options for all or the last N yearly journals
|
||||
for y in $(yearfiles "$1"); do
|
||||
echo -f"$y"
|
||||
done
|
||||
gnused() { # GNU sed, called gsed on mac
|
||||
if hash gsed 2>/dev/null; then gsed "$@"; else sed "$@"; fi
|
||||
}
|
||||
|
||||
# years [N] CMD.. - run hledger CMD on all or just the last N yearly journals combined
|
||||
# eg:
|
||||
# years stats
|
||||
# years 2 stats
|
||||
years() {
|
||||
N="$1"
|
||||
if [[ "$N" =~ ^[0-9]+$ ]]; then
|
||||
shift
|
||||
else
|
||||
N=
|
||||
fi
|
||||
# shellcheck disable=SC2046
|
||||
hledger $(yearfileopts "$N" | xargs) "$@"
|
||||
gnudate() { # GNU date, called gdate on mac
|
||||
if hash gdate 2>/dev/null; then gdate "$@"; else date "$@"; fi
|
||||
}
|
||||
|
||||
# eachyear [N] [n|p|P] "SHELLCMD" - run SHELLCMD with $LEDGER_FILE set,
|
||||
# for each or just the last N yearly journals,
|
||||
# optionally printing the file name with 0, 1 or 2 line breaks.
|
||||
# Accepts shell commands, extra quoting may be needed.
|
||||
# eg:
|
||||
# eachyear 10 hledger bal -0 -N cur:\\\\$
|
||||
# eachyear p files
|
||||
# eachyear P 'files | wc -l'
|
||||
# eachyear 5 P 5 'hledger stats | tail -1'
|
||||
# eachyear 7 p 'comm | rg ^...$'
|
||||
eachyear() {
|
||||
N="$1"
|
||||
if [[ "$N" =~ ^[0-9]+$ ]]; then
|
||||
shift
|
||||
else
|
||||
N=
|
||||
fi
|
||||
P="$1"
|
||||
if [[ "$P" =~ ^[npP]$ ]]; then
|
||||
shift
|
||||
else
|
||||
P=
|
||||
fi
|
||||
for f in $(yearfiles "$N"); do
|
||||
if [[ -n "$P" ]]; then
|
||||
if [[ $P == P ]]; then echo; fi
|
||||
printf "%s: " "$(basename "$f")"
|
||||
if [[ $P != n ]]; then echo; fi
|
||||
fi
|
||||
bash -ic "(LEDGER_FILE=$f; $*)" # XXX loses some quoting
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# time
|
||||
|
||||
#export TIMELOG=$FINDIR/time.journal
|
||||
export TIMELOG=$FINDIR/time/time-2024.journal
|
||||
export TIMEDOT=$FINDIR/time/time-2024.timedot
|
||||
# all in one big journal:
|
||||
#export TIMELOG=~/personal/time.journal
|
||||
|
||||
alias hours="hledger -f $TIMELOG"
|
||||
alias today='hours -p today'
|
||||
@ -172,3 +59,115 @@ alias sephours="hours -p sep"
|
||||
alias octhours="hours -p oct"
|
||||
alias novhours="hours -p nov"
|
||||
alias dechours="hours -p dec"
|
||||
alias 2008hours="hours -p 2008"
|
||||
alias 2009hours="hours -p 2009"
|
||||
alias 2010hours="hours -p 2010"
|
||||
alias 2011hours="hours -p 2011"
|
||||
alias 2012hours="hours -p 2012"
|
||||
alias 2013hours="hours -p 2013"
|
||||
alias 2014hours="hours -p 2014"
|
||||
alias 2015hours="hours -p 2015"
|
||||
alias weeklyhours="hours -p 'weekly this year' register --empty"
|
||||
alias monthlyhours="hours -p 'monthly this year' register --empty"
|
||||
alias weeklybillablehours="weeklyhours jobs not:unbilled --depth 3"
|
||||
alias monthlybillablehours="monthlyhours jobs not:unbilled --depth 3"
|
||||
|
||||
# money
|
||||
|
||||
# one journal per year, included by current and all journals:
|
||||
#export LEDGER_FILE=~/personal/current.journal
|
||||
#export LEDGER_FILE=~/personal/all.journal
|
||||
|
||||
alias jan="hledger -p jan"
|
||||
alias feb="hledger -p feb"
|
||||
alias mar="hledger -p mar"
|
||||
alias apr="hledger -p apr"
|
||||
alias may="hledger -p may"
|
||||
alias jun="hledger -p jun"
|
||||
alias jul="hledger -p jul"
|
||||
alias aug="hledger -p aug"
|
||||
alias sep="hledger -p sep"
|
||||
alias oct="hledger -p oct"
|
||||
alias nov="hledger -p nov"
|
||||
alias dec="hledger -p dec"
|
||||
alias 2006='hledger -f ~/personal/2006.journal'
|
||||
alias 2007='hledger -f ~/personal/2007.journal'
|
||||
alias 2008='hledger -f ~/personal/2008.journal'
|
||||
alias 2009='hledger -f ~/personal/2009.journal'
|
||||
alias 2010='hledger -f ~/personal/2010.journal'
|
||||
alias 2011='hledger -f ~/personal/2011.journal'
|
||||
alias 2012='hledger -f ~/personal/2012.journal'
|
||||
alias 2013='hledger -f ~/personal/2013.journal'
|
||||
alias 2014='hledger -f ~/personal/2014.journal'
|
||||
alias 2015='hledger -f ~/personal/2015.journal'
|
||||
alias all='hledger -f ~/personal/all.journal'
|
||||
alias household='hledger -f ~/personal/household.journal'
|
||||
alias add='hledger add'
|
||||
|
||||
alias bankbalances='hledger bal assets:bank liabilities:credit -E'
|
||||
alias cashflow="hledger balance '^assets:(bank|cash)'"
|
||||
alias incexp="hledger balance '(^income|^expenses|^equity:draw)'"
|
||||
# show activity in these accounts this and last month
|
||||
alias cash="hledger -d 'd>=[last month]' reg 'assets:cash' -B"
|
||||
alias checking="hledger -d 'd>=[last month]' reg 'assets:bank:wells fargo:checking' -B"
|
||||
# show daily cleared checking balance - for reconciling with online bank statement
|
||||
alias checkingcleared="checking --cleared --period 'daily to tomorrow'"
|
||||
# show checking balance from today forward
|
||||
alias checkingfuture="checking -d 'd>=[yesterday]'"
|
||||
|
||||
# generate a chart and view it in emacs
|
||||
chart () {
|
||||
hledger chart $* && emacsclient -n hledger.png
|
||||
}
|
||||
|
||||
# old ledger 2.6 scripts
|
||||
|
||||
BalanceSheet() {
|
||||
echo "Balance sheet as of `date`"
|
||||
echo "totals include sub-accounts"
|
||||
echo
|
||||
ledger -n --balance-format '%10T %2_%-a\n' --display "l<=3" --basis --subtotal $* balance assets
|
||||
echo
|
||||
ledger -n --balance-format '%10T %2_%-a\n' --display "l<=3" --basis --subtotal $* balance liabilities
|
||||
echo
|
||||
ledger -nE --balance-format '%10T %2_%-a\n' --display "l<=4" --basis --subtotal $* balance equity
|
||||
echo
|
||||
echo "`ledger --balance-format '%10T %2_%-a\n' --basis $* balance liabilities equity | tail -1`liabilities + equity"
|
||||
echo
|
||||
ledger --balance-format '%10T %2_%-a\n' --basis $* balance assets liabilities | tail -2
|
||||
}
|
||||
|
||||
IncomeStatement() {
|
||||
echo "Income statement for `date +%Y` as of `date`"
|
||||
echo "totals include sub-accounts"
|
||||
echo
|
||||
ledger -n --balance-format '%10(-T) %2_%-a\n' --display "l<=3" --basis --subtotal $* balance income
|
||||
echo
|
||||
ledger -n --balance-format '%10(-T) %2_%-a\n' --display "l<=2" --basis --subtotal $* balance expenses -equity
|
||||
echo
|
||||
ledger --balance-format '%10(-T) %2_%-a\n' --basis $* balance income expenses -equity | tail -2
|
||||
}
|
||||
|
||||
# function CashflowStatement () {
|
||||
# echo "Cashflow statement for `date +%Y`"
|
||||
# #echo "(totals include sub-accounts)"
|
||||
# echo
|
||||
# cat <<EOF
|
||||
# cash flows from operating activities
|
||||
# net income as on income statement
|
||||
# add: depreciation
|
||||
# add: allowance for doubtful accounts
|
||||
# deduct: increase in inventory
|
||||
# deduct: increase in prepaid expenses
|
||||
# deduct: decrease in accounts payable
|
||||
# cash flows from investing activities
|
||||
# cash received from investments sold
|
||||
# less: cash paid for store equipment
|
||||
# cash flows from financing activities
|
||||
# cash paid for dividends
|
||||
#
|
||||
# Increase in cash:
|
||||
# Cash at the beginning of the year:
|
||||
# Cash at the end of the year:
|
||||
# EOF
|
||||
# }
|
||||
|
||||
@ -8,7 +8,7 @@ echo "building hledger libraries for scripts"
|
||||
stack build hledger
|
||||
|
||||
echo "installing extra libraries for scripts"
|
||||
stack install string-qq microlens
|
||||
stack install string-qq
|
||||
|
||||
echo "compiling the hledger-* scripts"
|
||||
for f in `git ls-files 'hledger-*.hs'`; do stack ghc -- "$f"; done
|
||||
|
||||
38
bin/csv.mk
Normal file
38
bin/csv.mk
Normal file
@ -0,0 +1,38 @@
|
||||
# some CSV-related make scripts
|
||||
|
||||
HLEDGER=hledger
|
||||
|
||||
YEAR:=$(shell date +%Y)
|
||||
MONTH:=$(shell date +%m)
|
||||
MONTHS:=$(shell ghc -e "(putStr . unwords . map show) [1..$(MONTH)]")
|
||||
MONTHS2:=$(shell ghc -e "(putStr . unwords . map show) [2..$(MONTH)]")
|
||||
|
||||
###############################################################################
|
||||
|
||||
# convert latest bank csv downloads to journal files
|
||||
BANKJOURNALS = \
|
||||
mint.journal \
|
||||
WellsFargoChecking1.journal \
|
||||
WellsFargoSavings2.journal \
|
||||
WellsFargoSavings3.journal \
|
||||
WellsFargoCreditCard4.journal \
|
||||
Paypal.journal
|
||||
convert-csv: move-csv $(BANKJOURNALS)
|
||||
|
||||
# move and rename any newly downloaded bank csv files
|
||||
DOWNLOADDIR=~/Desktop
|
||||
move-csv:
|
||||
@(F=$(DOWNLOADDIR)/transactions.csv; [ -e $$F ] && (mv $$F mint.csv; echo new mint.csv found) || exit 0)
|
||||
@(F=$(DOWNLOADDIR)/Checking1.csv; [ -e $$F ] && (mv $$F WellsFargoChecking1.csv; echo new WellsFargoChecking1.csv found) || exit 0)
|
||||
@(F=$(DOWNLOADDIR)/Savings2.csv; [ -e $$F ] && (mv $$F WellsFargoSavings2.csv; echo new WellsFargoSavings2.csv found) || exit 0)
|
||||
@(F=$(DOWNLOADDIR)/Savings3.csv; [ -e $$F ] && (mv $$F WellsFargoSavings3.csv; echo new WellsFargoSavings3.csv found) || exit 0)
|
||||
@(F=$(DOWNLOADDIR)/CreditCard4.csv; [ -e $$F ] && (mv $$F WellsFargoCreditCard4.csv; echo new WellsFargoCreditCard4.csv found) || exit 0)
|
||||
@(F=$(DOWNLOADDIR)/Download.csv; [ -e $$F ] && (mv $$F Paypal.csv; echo new Paypal.csv found) || exit 0)
|
||||
|
||||
# convert a csv to a journal using the similarly named rules file
|
||||
%.journal: %.csv %.rules
|
||||
$(HLEDGER) convert $< >$@
|
||||
|
||||
%.rules:
|
||||
touch '$@'
|
||||
|
||||
162
bin/ft
162
bin/ft
@ -1,162 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# * ft - financial scripts, see below
|
||||
# ** PREAMBLE
|
||||
# shellcheck shell=bash disable=SC2317
|
||||
# Customise as needed; consider keeping as a git checkout for merging updates.
|
||||
# See also: justfile, an alternative.
|
||||
|
||||
set -e
|
||||
|
||||
rg="rg -IN --sort=path"
|
||||
date=$(if [ "$(builtin type -p gdate)" ]; then echo gdate; else echo date; fi)
|
||||
sed=$(if [ "$(builtin type -p gsed)" ]; then echo gsed; else echo sed; fi)
|
||||
|
||||
help() { # show this help
|
||||
cat <<EOF
|
||||
--------------------------------------------------------------------------------"; }
|
||||
ft - finance tool: run financial reports and finance-related scripts
|
||||
Usage: ft [COMMAND [ARGS]]
|
||||
Commands:
|
||||
$($rg '^\w.*\(\) *\{ *#' "$0" | $sed -e 's/() *{//' | column -t -s'#')
|
||||
OTHERCMD [ARGS] run other hledger commands on the default journal
|
||||
|
||||
Add hledger options to customise reports.
|
||||
EOF
|
||||
}
|
||||
# '(...|# \*\* [^#].*)' -or '$3 $1|$2'
|
||||
|
||||
# The main hledger file to import to and report on. It should exist.
|
||||
JOURNAL="$LEDGER_FILE"
|
||||
|
||||
#DIR=${FINDIR:-~/finance}
|
||||
DIR=$(dirname "$JOURNAL")
|
||||
cd "$DIR"
|
||||
|
||||
PERIOD="1/1..tomorrow"
|
||||
TODAY=$($date +%Y-%m-%d)
|
||||
#TODAY=$(TZ=UTC $date +%Y-%m-%d)
|
||||
#YEAR=$($date +%Y)
|
||||
|
||||
# ** IMPORT TXNS ------------------------------------------------------------
|
||||
|
||||
# where to import most hledger transactions from
|
||||
IMPORTFILES=(\
|
||||
bank1-checking.csv.rules \
|
||||
bank1-savings.csv.rules \
|
||||
paypal.csv \
|
||||
)
|
||||
|
||||
# hledger .rules files(/globs) used for IMPORTFILES
|
||||
IMPORTRULESFILES=$($sed -Ee 's/.csv /.csv.rules /g' <<< "${IMPORTFILES[*]}")
|
||||
IMPORTRULESFILES+=(common.rules unify.rules wf.rules wf*checking.rules wf*savings.rules)
|
||||
|
||||
get-csv() { # download auto-downloadable CSVs (paypal)
|
||||
paypaljson | paypaljson2csv > paypal.csv
|
||||
}
|
||||
|
||||
import-dry() { # import new downloaded transactions to the journal, dry run
|
||||
hledger -f "$JOURNAL" import "${IMPORTFILES[@]}" --dry-run
|
||||
}
|
||||
|
||||
import() { # import new downloaded transactions to the journal, logging and not printing errors
|
||||
date >>import.log
|
||||
hledger -f "$JOURNAL" import "${IMPORTFILES[@]}" 2>>import.log || echo "Failed, check import.log"
|
||||
echo "Use ledger-mode's M-q to align entries."
|
||||
}
|
||||
|
||||
# ** IMPORT PRICES ------------------------------------------------------------
|
||||
|
||||
get-prices() { # [PRICEHISTFETCHOPTS] - download prices for main commodities (default: today's)
|
||||
(pricehist fetch -o ledger -s "$TODAY" alphavantage EUR/USD "$@" | $sed -E 's/EUR/€/') &
|
||||
(pricehist fetch -o ledger -s "$TODAY" alphavantage GBP/USD "$@" | $sed -E 's/GBP/£/') &
|
||||
(pricehist fetch -o ledger -s "$TODAY" alphavantage JPY/USD "$@" | $sed -E 's/JPY/¥/')
|
||||
# Parallelised for speed; do slowest last.
|
||||
# Output order varies, can be sorted with LC_COLLATE=C.UTF-8 sort or hledger -f- prices.
|
||||
}
|
||||
|
||||
# ** REPORTS ------------------------------------------------------------
|
||||
# *** general ------------------------------------------------------------
|
||||
|
||||
bs() { # show balance sheet
|
||||
hledger -f "$JOURNAL" bs --layout bare --pretty --drop 1 -p "$PERIOD" -E -5 "$@"
|
||||
}
|
||||
|
||||
is() { # show income statement
|
||||
hledger -f "$JOURNAL" is --layout bare --pretty --drop 1 -p "$PERIOD" -S "$@"
|
||||
}
|
||||
|
||||
a() { # show assets
|
||||
hledger -f "$JOURNAL" bal type:al -H --layout bare --pretty --drop 1 -p "$PERIOD" -E "$@"
|
||||
}
|
||||
|
||||
r() { # show revenues
|
||||
hledger -f "$JOURNAL" bal type:r --layout bare --pretty --drop 1 -p "$PERIOD" -S --invert "$@"
|
||||
}
|
||||
|
||||
x() { # show expenses
|
||||
hledger -f "$JOURNAL" bal type:x --layout bare --pretty --drop 1 -p "$PERIOD" -S --invert "$@"
|
||||
}
|
||||
|
||||
ab() { # show assets bar chart
|
||||
echo "Quarterly net worth:"
|
||||
hledger-bar -v 200 -f "$JOURNAL" -Q type:al -H "$@"
|
||||
}
|
||||
|
||||
rb() { # show revenues bar chart
|
||||
echo "Quarterly revenues:"
|
||||
hledger-bar -v 40 -f "$JOURNAL" -Q type:r --invert "$@"
|
||||
}
|
||||
|
||||
xb() { # show expenses bar chart
|
||||
echo "Quarterly expenses:"
|
||||
hledger-bar -v 40 -f "$JOURNAL" -Q type:x --invert "$@"
|
||||
}
|
||||
|
||||
# XXX with partial workaround for https://github.com/gooofy/drawilleplot/issues/4
|
||||
al() { # show assets line chart
|
||||
hledger -f "$JOURNAL" plot -- bal --depth=1 ^assets --historical --terminal --rcParams '{"figure.figsize":[8,3]}' --no-today -q --title "hledger assets" "$@" | $sed 's/⠀/ /g'
|
||||
}
|
||||
|
||||
rl() { # show revenues line chart
|
||||
hledger -f "$JOURNAL" plot -- bal --depth=1 ^revenues --monthly --invert --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly revenues" "$@" | $sed 's/⠀/ /g'
|
||||
}
|
||||
|
||||
xl() { # show expenses line chart
|
||||
hledger -f "$JOURNAL" plot -- bal --depth=1 ^expenses --monthly --terminal --rcParams '{"figure.figsize":[8,3]}' --drawstyle 'steps-mid' --no-today -q --title "hledger monthly expenses" "$@" | $sed 's/⠀/ /g'
|
||||
}
|
||||
|
||||
forecast() { # print transactions predicted by forecast rules from last week on
|
||||
hledger print --auto --forecast=lastweek.. -I tag:_generated "$@"
|
||||
}
|
||||
|
||||
household() { # show a draft month-end household adjustment transaction for last month
|
||||
env household "$($date -v-1m +%b)"
|
||||
}
|
||||
|
||||
# *** tax ------------------------------------------------------------
|
||||
|
||||
# estimated-tax:
|
||||
# @echo "Federal estimated tax due for this year"
|
||||
# $(HLEDGER) register liabilities:personal:tax:federal:$(YEAR) --width=130
|
||||
# @echo State estimated tax due for this year:
|
||||
# @$(HLEDGER) register liabilities:personal:tax:state:$(YEAR) --width=130
|
||||
# @echo
|
||||
|
||||
# *** business ------------------------------------------------------------
|
||||
|
||||
consulting() { # show consulting revenue
|
||||
hledger -f "$JOURNAL" reg --invert 'revenues:(client1|client2)' -p "$PERIOD" "$@"
|
||||
}
|
||||
|
||||
# *** other ------------------------------------------------------------
|
||||
|
||||
bin() { # [PAT] show all scripts in $DIR/bin/[bashrc] (default: ~/finance/)
|
||||
env bin "$@"
|
||||
}
|
||||
|
||||
# ** END
|
||||
|
||||
if [[ $# -eq 0 ]]; then help # no args shows help
|
||||
elif declare -f "$1" > /dev/null; then "$@"; # arg 1 selects a function above
|
||||
else hledger -f "$JOURNAL" "$@"; fi # or fall through to hledger
|
||||
exit
|
||||
@ -1,101 +0,0 @@
|
||||
#!/usr/bin/env stack
|
||||
{- stack --resolver=nightly-2025-09-30 script --compile --verbosity=error
|
||||
--package "bytestring cassava gogol gogol-core gogol-sheets lens pretty-show text"
|
||||
-}
|
||||
-- or
|
||||
#!/usr/bin/env cabal
|
||||
{- cabal:
|
||||
build-depends: aeson<1.6, bytestring, cassava, gogol, gogol-core, gogol-sheets, lens, pretty-show, text
|
||||
-}
|
||||
|
||||
-- In 2023-02, this is hard to build; gogol is unmaintained and requires old aeson < 1.6,
|
||||
-- which requires old bytestring which requires old GHC (8.10 or 9.0).
|
||||
-- On modern macs these GHCs are difficult to run. This build most deps for me:
|
||||
-- brew install llvm@12
|
||||
-- ghcup set ghc 9.0.2
|
||||
-- PATH=/opt/homebrew/opt/llvm@12/bin:$PATH CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/usr/include/ffi cabal build gsheet-csv.hs
|
||||
-- but failed on cryptonite with "error: instruction requires: sha3", an llvm 12 on arm bug
|
||||
|
||||
{-
|
||||
gsheet-csv - download the CSV of a Google Sheet you have access to
|
||||
|
||||
INSTALL:
|
||||
Get stack if needed, eg from https://haskell-lang.org/get-started
|
||||
Run "./gsheet-csv.hs" once to compile. On Windows, run "stack gsheet-csv.hs".
|
||||
|
||||
SETUP:
|
||||
Set up an account at https://console.developers.google.com/iam-admin/serviceaccounts, selecting or creating a project
|
||||
Save the service account's email address
|
||||
Create a key and download as json to ~/.config/gcloud/KEYFILE.json
|
||||
Symlink this to ~/.config/gcloud/application_default_credentials.json
|
||||
Share spreadsheets with the service account's email address
|
||||
|
||||
USAGE:
|
||||
gsheet-csv SPREADSHEETID SHEETNAME - print specified sheet as CSV
|
||||
|
||||
-}
|
||||
|
||||
{-# LANGUAGE PackageImports #-}
|
||||
|
||||
module Main
|
||||
where
|
||||
import "lens" Control.Lens
|
||||
import "bytestring" qualified Data.ByteString.Lazy as B
|
||||
import "cassava" Data.Csv
|
||||
import "text" qualified Data.Text as T
|
||||
import "gogol" Network.Google
|
||||
import "gogol-sheets" Network.Google.Sheets
|
||||
import "base" System.Environment
|
||||
import "base" System.IO
|
||||
-- import "base" Debug.Trace
|
||||
-- import "pretty-show" Text.Show.Pretty (pPrint, ppShow)
|
||||
|
||||
main = do
|
||||
[spreadsheetId, sheetName] <- map T.pack <$> getArgs
|
||||
let range = sheetName -- ++"!A1:J10"
|
||||
lgr <- newLogger Info stdout
|
||||
env <- newEnv <&> (envLogger .~ lgr) . (envScopes .~ spreadsheetsReadOnlyScope)
|
||||
values <- view vrValues <$> (runResourceT . runGoogle env $ send (spreadsheetsValuesGet spreadsheetId range))
|
||||
B.putStr $ Data.Csv.encode $ map (map bs) values
|
||||
where bs = drop 8 . init . show -- no more time for hilariously craptastic haskell libs
|
||||
|
||||
|
||||
------------------------------
|
||||
-- notes
|
||||
|
||||
-- import Data.Aeson
|
||||
-- import Data.Text (Text)
|
||||
-- import Network.Google.Data.JSON
|
||||
-- import Network.Google.Resource.Sheets.Spreadsheets.Get
|
||||
|
||||
|
||||
{-
|
||||
TODO:
|
||||
gsheet-csv [-h] - show help
|
||||
gsheet-csv SPREADSHEETID - get first sheet
|
||||
gsheet-csv SPREADSHEETID SHEETNAME RANGE - get just the specified cells
|
||||
|
||||
-}
|
||||
|
||||
{-
|
||||
Notes for developers of stack (1.9.1) scripts:
|
||||
|
||||
1. In the stack header above, flags' position and style are critical.
|
||||
Minor variations cause very different behaviour.
|
||||
|
||||
2. For different run actions, adjust the stack command:
|
||||
script --optimize - run compiled, after compiling if needed
|
||||
script --compile - run compiled, after compiling if needed (without optimisation)
|
||||
script - run interpreted (slower)
|
||||
exec runghc - run interpreted using ambient GHC package db
|
||||
exec ghc - compile
|
||||
exec ghci - load in GHCI
|
||||
exec ghcid - watch for compile errors
|
||||
|
||||
3. To silence "Using resolver:" output (but also deps install output), change --verbosity to warn
|
||||
|
||||
4. Declare which package each import is from, keep synced with --package; might as well be clear
|
||||
|
||||
5. Doc: https://docs.haskellstack.org/en/stable/topics/scripts
|
||||
|
||||
-}
|
||||
77
bin/hledger-addon-example.hs
Executable file
77
bin/hledger-addon-example.hs
Executable file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env stack
|
||||
-- stack runghc --verbosity info --package hledger --package string-qq
|
||||
--resolver nightly-2022-09-01
|
||||
|
||||
{-
|
||||
hledger-addon-example - a hledger addon command template.
|
||||
|
||||
This an example of an addon command (an executable named hledger-*).
|
||||
By default it reads your default journal and prints the number of
|
||||
transactions. It supports many of the usual hledger options; run it
|
||||
with -h/--help to see them. When you want to create a new hledger
|
||||
command, save this script under a new name, somewhere in $PATH,
|
||||
keeping it executable, and start tweaking the code.
|
||||
|
||||
Requirements:
|
||||
|
||||
This is a stack script, requiring stack to run. hledger addons do not
|
||||
have to be stack scripts, but this one is, as they work well for this.
|
||||
If you prefer you can adapt it to be a cabal script, or you can
|
||||
install the required haskell libraries (see above) and then
|
||||
run/compile it with a suitable runghc/ghc command.
|
||||
|
||||
The script may require specific versions of the libraries.
|
||||
If run/compiled from inside the hledger source tree, it will use that hledger
|
||||
version and the libs of the stackage resolver in stack.yaml.
|
||||
If run/compiled from outside the hledger source tree, it will use the hledger
|
||||
and libs of the resolver in ~/.stack/global-project/stack.yaml.
|
||||
Or you can uncomment --resolver above to use another resolver.
|
||||
|
||||
Usage:
|
||||
|
||||
Executing this script will cause stack to run it in interpreted mode:
|
||||
|
||||
$ hledger-addon-example.hs
|
||||
|
||||
Or you can compile first:
|
||||
|
||||
$ stack ghc hledger-addon-example.hs --package hledger --package string-qq
|
||||
$ hledger-addon-example
|
||||
|
||||
Whether compiled or not, you can also run it as a hledger subcommand, if it is in $PATH:
|
||||
|
||||
$ hledger addon-example
|
||||
|
||||
-}
|
||||
|
||||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
|
||||
import Data.String.QQ (s)
|
||||
import Text.Printf
|
||||
import Hledger
|
||||
import Hledger.Cli
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
cmdmode = hledgerCommandMode
|
||||
[s| addon-example
|
||||
Print the number of transactions in the journal.
|
||||
|
||||
_FLAGS
|
||||
|]
|
||||
[]
|
||||
[generalflagsgroup1]
|
||||
[]
|
||||
([], Nothing) -- Just $ argsFlag "[QUERY]")
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
opts@CliOpts{reportspec_=rspec} <- getHledgerCliOpts cmdmode
|
||||
withJournalDo opts $ \j -> do
|
||||
d <- getCurrentDay
|
||||
let
|
||||
q = _rsQuery rspec
|
||||
ts = filter (q `matchesTransaction`) $ jtxns $ journalApplyValuationFromOpts rspec j
|
||||
printf "File %s: %d transactions\n" (journalFilePath j) (length ts)
|
||||
@ -1,112 +0,0 @@
|
||||
#!/usr/bin/env stack
|
||||
-- stack runghc --verbosity info --package hledger
|
||||
-- Run from inside the hledger source tree, or compile with compile.sh.
|
||||
-- See hledger-check-fancyassertions.hs.
|
||||
|
||||
-- {-# OPTIONS_GHC -Wno-missing-signatures #-}
|
||||
|
||||
{-| Construct two balance reports for two different time periods and use one of the as "budget" for
|
||||
the other, thus comparing them
|
||||
-}
|
||||
import Data.Text.Lazy.IO qualified as TL
|
||||
import System.Environment (getArgs)
|
||||
import Hledger.Cli.Script
|
||||
import Hledger.Cli.Commands.Balance
|
||||
import qualified Data.Map as Map
|
||||
import Data.List (sortOn)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
cmdmode = hledgerCommandMode
|
||||
(unlines ["balance-as-budget-multi"
|
||||
,"Read two journal files and generate multiple balance reports that use first of them as budget for the second."
|
||||
," "
|
||||
,"Pass two journal names and a file that contains sets of 'hledger balance'-compatible options, one per line"
|
||||
,"For example, to use Jan 2019 as budget for Jan 2020, use:"
|
||||
,"2019.journal 2020.journal commands.txt"
|
||||
,"and put '\"assets\" --depth 3 --value=$,then' in the commands.txt"
|
||||
])
|
||||
[]
|
||||
[generalflagsgroup1]
|
||||
[]
|
||||
([], Just $ argsFlag "BUDGET_JOURNAL ACTUAL_JOURNAL COMMAND_FILE")
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
case args of
|
||||
[budget_f, real_f, commands_f] -> runAllCommands budget_f real_f commands_f
|
||||
_ -> error' "expected exactly three arguments"
|
||||
|
||||
runAllCommands :: String -> String -> String -> IO ()
|
||||
runAllCommands budget_f real_f commands_f = do
|
||||
d <- getCurrentDay
|
||||
budget <- readJournalFile' budget_f
|
||||
real <- readJournalFile' real_f
|
||||
let styles = journalCommodityStylesWith HardRounding real
|
||||
commands <- lines <$> readFile commands_f
|
||||
forM_ commands $ \command -> do
|
||||
let args = words' command
|
||||
case args of
|
||||
[] -> return ()
|
||||
"echo":args -> putStrLn $ unwords args
|
||||
_ -> do
|
||||
opts@CliOpts{reportspec_=rspec} <- getHledgerCliOpts' balancemode args
|
||||
let reportopts = _rsReportOpts rspec
|
||||
|
||||
-- Generate both reports from their respective journals (unchanged)
|
||||
let budgetReport = multiBalanceReport rspec budget
|
||||
actualReport = multiBalanceReport rspec real
|
||||
|
||||
-- Combine the reports
|
||||
let combined = combineBudgetAndActual reportopts real budgetReport actualReport
|
||||
|
||||
writeOutputLazyText opts $ budgetReportAsText reportopts $ styleAmounts styles $ combined
|
||||
|
||||
-- | Combine two MultiBalanceReports into a BudgetReport, comparing them side by side.
|
||||
-- The budget report uses the date periods from the actual (second) report.
|
||||
combineBudgetAndActual :: ReportOpts -> Journal -> MultiBalanceReport -> MultiBalanceReport -> BudgetReport
|
||||
combineBudgetAndActual ropts j
|
||||
(PeriodicReport budgetperiods budgetrows (PeriodicReportRow _ budgettots budgetgrandtot budgetgrandavg))
|
||||
(PeriodicReport actualperiods actualrows (PeriodicReportRow _ actualtots actualgrandtot actualgrandavg)) =
|
||||
PeriodicReport actualperiods combinedrows totalrow
|
||||
where
|
||||
-- Build maps of amounts by account name
|
||||
budgetMap = Map.fromList
|
||||
[ (prrFullName row, (prrAmounts row, prrTotal row, prrAverage row))
|
||||
| row <- budgetrows
|
||||
]
|
||||
actualMap = Map.fromList
|
||||
[ (prrFullName row, (prrAmounts row, prrTotal row, prrAverage row))
|
||||
| row <- actualrows
|
||||
]
|
||||
|
||||
-- Accounts with actual amounts (and their budgets if available)
|
||||
actualWithBudget =
|
||||
[ PeriodicReportRow acct cells total avg
|
||||
| PeriodicReportRow acct actualamts actualtot actualavg <- actualrows
|
||||
, let budgetamts = maybe (replicate (length actualperiods) Nothing) (\(amts, _, _) -> map Just amts)
|
||||
(Map.lookup (displayFull acct) budgetMap)
|
||||
, let cells = zip (map Just actualamts) budgetamts
|
||||
, let total = (Just actualtot, fmap (\(_, t, _) -> t) (Map.lookup (displayFull acct) budgetMap))
|
||||
, let avg = (Just actualavg, fmap (\(_, _, a) -> a) (Map.lookup (displayFull acct) budgetMap))
|
||||
]
|
||||
|
||||
-- Budget-only accounts (no actual amounts)
|
||||
budgetOnly =
|
||||
[ PeriodicReportRow acct cells total avg
|
||||
| PeriodicReportRow acct budgetamts budgettot budgetavg <- budgetrows
|
||||
, let acctName = displayFull acct
|
||||
, not (acctName `Map.member` actualMap) -- Only include if not in actual
|
||||
, let cells = zip (replicate (length actualperiods) (Just nullmixedamt)) (map Just budgetamts)
|
||||
, let total = (Just nullmixedamt, Just budgettot)
|
||||
, let avg = (Just nullmixedamt, Just budgetavg)
|
||||
]
|
||||
|
||||
-- Combine and sort all rows by account name
|
||||
combinedrows = sortOn prrFullName (actualWithBudget ++ budgetOnly)
|
||||
|
||||
totalrow = PeriodicReportRow ()
|
||||
(zip (map Just actualtots) (map Just budgettots))
|
||||
(Just actualgrandtot, Just budgetgrandtot)
|
||||
(Just actualgrandavg, Just budgetgrandavg)
|
||||
@ -10,10 +10,7 @@
|
||||
-}
|
||||
import Data.Text.Lazy.IO as TL
|
||||
import System.Environment (getArgs)
|
||||
import Hledger.Cli.Script
|
||||
import Hledger.Cli.Commands.Balance
|
||||
import qualified Data.Map as Map
|
||||
import Data.List (sortOn)
|
||||
import Hledger.Cli
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
cmdmode = hledgerCommandMode
|
||||
@ -37,68 +34,13 @@ main = do
|
||||
args <- getArgs
|
||||
let report1args = takeWhile (/= "--") args
|
||||
let report2args = drop 1 $ dropWhile (/= "--") args
|
||||
|
||||
-- Get options for both reports
|
||||
opts1@CliOpts{reportspec_=rspec1} <- getHledgerCliOpts' balancemode report1args
|
||||
opts2@CliOpts{reportspec_=rspec2} <- getHledgerCliOpts' balancemode report2args
|
||||
|
||||
withJournal opts1 $ \j1 -> do
|
||||
withJournal opts2 $ \j2 -> do
|
||||
-- Generate both reports with their respective date periods
|
||||
let report1 = multiBalanceReport rspec1 j1 -- budget
|
||||
report2 = multiBalanceReport rspec2 j2 -- actual
|
||||
ropts2 = _rsReportOpts rspec2
|
||||
styles = journalCommodityStylesWith HardRounding j2
|
||||
|
||||
-- Combine the reports (using report2's date periods for display)
|
||||
let combined = combineBudgetAndActual ropts2 j2 report1 report2
|
||||
|
||||
writeOutputLazyText opts2 $ budgetReportAsText ropts2 $ styleAmounts styles $ combined
|
||||
|
||||
-- | Combine two MultiBalanceReports into a BudgetReport, comparing them side by side.
|
||||
-- The budget report uses the date periods from the actual (second) report.
|
||||
combineBudgetAndActual :: ReportOpts -> Journal -> MultiBalanceReport -> MultiBalanceReport -> BudgetReport
|
||||
combineBudgetAndActual ropts j
|
||||
(PeriodicReport budgetperiods budgetrows (PeriodicReportRow _ budgettots budgetgrandtot budgetgrandavg))
|
||||
(PeriodicReport actualperiods actualrows (PeriodicReportRow _ actualtots actualgrandtot actualgrandavg)) =
|
||||
PeriodicReport actualperiods combinedrows totalrow
|
||||
(_,_,report1) <- mbReport report1args
|
||||
(ropts2,j,report2) <- mbReport report2args
|
||||
let pastAsBudget = combineBudgetAndActual ropts2 j report1{prDates=prDates report2} report2
|
||||
TL.putStrLn $ budgetReportAsText ropts2 pastAsBudget
|
||||
where
|
||||
-- Build maps of amounts by account name
|
||||
budgetMap = Map.fromList
|
||||
[ (prrFullName row, (prrAmounts row, prrTotal row, prrAverage row))
|
||||
| row <- budgetrows
|
||||
]
|
||||
actualMap = Map.fromList
|
||||
[ (prrFullName row, (prrAmounts row, prrTotal row, prrAverage row))
|
||||
| row <- actualrows
|
||||
]
|
||||
|
||||
-- Accounts with actual amounts (and their budgets if available)
|
||||
actualWithBudget =
|
||||
[ PeriodicReportRow acct cells total avg
|
||||
| PeriodicReportRow acct actualamts actualtot actualavg <- actualrows
|
||||
, let budgetamts = maybe (replicate (length actualperiods) Nothing) (\(amts, _, _) -> map Just amts)
|
||||
(Map.lookup (displayFull acct) budgetMap)
|
||||
, let cells = zip (map Just actualamts) budgetamts
|
||||
, let total = (Just actualtot, fmap (\(_, t, _) -> t) (Map.lookup (displayFull acct) budgetMap))
|
||||
, let avg = (Just actualavg, fmap (\(_, _, a) -> a) (Map.lookup (displayFull acct) budgetMap))
|
||||
]
|
||||
|
||||
-- Budget-only accounts (no actual amounts)
|
||||
budgetOnly =
|
||||
[ PeriodicReportRow acct cells total avg
|
||||
| PeriodicReportRow acct budgetamts budgettot budgetavg <- budgetrows
|
||||
, let acctName = displayFull acct
|
||||
, not (acctName `Map.member` actualMap) -- Only include if not in actual
|
||||
, let cells = zip (replicate (length actualperiods) (Just nullmixedamt)) (map Just budgetamts)
|
||||
, let total = (Just nullmixedamt, Just budgettot)
|
||||
, let avg = (Just nullmixedamt, Just budgetavg)
|
||||
]
|
||||
|
||||
-- Combine and sort all rows by account name
|
||||
combinedrows = sortOn prrFullName (actualWithBudget ++ budgetOnly)
|
||||
|
||||
totalrow = PeriodicReportRow ()
|
||||
(zip (map Just actualtots) (map Just budgettots))
|
||||
(Just actualgrandtot, Just budgetgrandtot)
|
||||
(Just actualgrandavg, Just budgetgrandavg)
|
||||
mbReport args = do
|
||||
opts@CliOpts{reportspec_=rspec} <- getHledgerCliOpts' cmdmode args
|
||||
d <- getCurrentDay
|
||||
(report,j) <- withJournalDo opts $ \j -> return (multiBalanceReport rspec j, j)
|
||||
return (_rsReportOpts rspec,j,report)
|
||||
|
||||
137
bin/hledger-bar
137
bin/hledger-bar
@ -1,137 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# hledger-bar - see below
|
||||
|
||||
usage() {
|
||||
cat <<'EOS'
|
||||
hledger-bar - show quick bar charts in the terminal
|
||||
Usage:
|
||||
hledger-bar [-h|--help]
|
||||
hledger-bar [-v|-vv] [SCALE] BALARGS
|
||||
hledger bar -- [-v|-vv] [SCALE] BALARGS # might need extra quoting
|
||||
|
||||
Requires bash (or osh) and hledger >= ~1.25.
|
||||
|
||||
With no arguments, shows this help.
|
||||
Otherwise, runs hledger's 'balance' command, reporting monthly
|
||||
balance changes by default, and shows the period totals as a bar chart
|
||||
in the terminal, with positive amounts shown as '+' and negatives as '-'
|
||||
(in green and red respectively, unless NO_COLOR is set).
|
||||
|
||||
Bars are not auto-sized; they will be (amount divided by SCALE) long, where
|
||||
SCALE is 100 by default. This is overrideable by a numeric first argument.
|
||||
Eg if bars are too long, try 200; if they are too short, try 50.
|
||||
|
||||
Most other options/arguments understood by the balance command can be
|
||||
used, such as one or more account names, or different report intervals
|
||||
like -W (weekly) or -Q (quarterly). There are two restrictions:
|
||||
|
||||
- You must ensure the report is for a single commodity. So use eg
|
||||
'cur:€' or 'cur:\\$' or 'cur:\\\\$' or '-B' or '-X$ --infer-market-prices'
|
||||
as needed.
|
||||
|
||||
- You can't use spaces in arguments (even quoted). If needed,
|
||||
you could write '.' instead of space.
|
||||
|
||||
If you don't see the results you expect:
|
||||
|
||||
- Note that revenues appear negative and expenses positive,
|
||||
as with the balance command; to flip signs, use --invert.
|
||||
|
||||
- Run as 'hledger-bar' to minimise command line quoting issues.
|
||||
|
||||
- Use -v as first argument to also show the (unscaled, rounded) amounts.
|
||||
|
||||
- Use -vv as first argument to show the amounts and the balance command
|
||||
(approximately; you might need to add one level of quoting).
|
||||
Tip: remove some of this command's first options to see a more
|
||||
human-readable balance report.
|
||||
|
||||
- When you are reporting changes in asset/liability/equity accounts,
|
||||
you will probably want to exclude opening/closing balance transactions,
|
||||
eg with not:desc:'(opening|closing)' or not:tag:clopen if you use those.
|
||||
|
||||
Examples:
|
||||
|
||||
$ hledger-bar food # monthly food expenses
|
||||
$ hledger-bar 1 --count food # monthly food posting counts
|
||||
$ hledger-bar -v 1 -f $TIMELOG -D # daily hours, with numbers
|
||||
$ hledger-bar type:c not:tag:clopen cur:\\$ -W # weekly cashflow, $ only
|
||||
$ hledger-bar type:al not:tag:clopen cur:\\$ # monthly net worth change ($)
|
||||
$ hledger-bar type:rx --invert cur:\\$ # monthly profit/loss ($)
|
||||
$ hledger-bar type:rx --invert cur:\\$ --infer-market-prices --value=then,$
|
||||
# monthly profit/loss ($, plus anything that can be converted to $,
|
||||
# using conversion rates on transaction dates)
|
||||
$ hledger-bar . cur:\\$ # all accounts' change ($)
|
||||
$ hledger bar -- . cur:\\\\$ # as hledger subcommand
|
||||
|
||||
EOS
|
||||
}
|
||||
###############################################################################
|
||||
|
||||
set -e
|
||||
|
||||
defscale=100
|
||||
negchar="-"
|
||||
poschar="+"
|
||||
|
||||
# utils
|
||||
|
||||
# https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit and 24-bit colors.
|
||||
# Disable if stdout is not a terminal or NO_COLOR is defined.
|
||||
if [[ ! -t 1 || -n ${NO_COLOR} ]]; then
|
||||
red=''
|
||||
green=''
|
||||
nocol=''
|
||||
else
|
||||
red='\e[38;5;1m'
|
||||
green="\e[38;5;2m"
|
||||
nocol="\e[0m"
|
||||
fi
|
||||
|
||||
unquote() { s="${1%\"}"; echo "${s#\"}"; }
|
||||
|
||||
# process command line
|
||||
shownum=0
|
||||
verbose=0
|
||||
scale=${defscale}
|
||||
if [[ $# -eq 0 || $1 == --help || $1 == -h ]]; then usage; exit; fi
|
||||
if [[ $1 == -v ]]; then shownum=1; shift; elif [[ $1 == -vv ]]; then shownum=1; verbose=1; shift; fi
|
||||
if [[ $1 =~ ^[0-9]+$ ]]; then scale=$1; shift; fi
|
||||
|
||||
# helpers
|
||||
|
||||
# The hledger reporting command. It should produce a two-column CSV
|
||||
# report with one line per period and one currency. It must have a
|
||||
# report interval for --transpose to work. shellcheck disable=SC2124
|
||||
cmd="hledger balance -Ocsv --transpose -N -0 --layout=bare -M $*"
|
||||
|
||||
printcmd() {
|
||||
echo "From command (might need added quotes):" # don't know how to print all the slashes
|
||||
echo "${cmd}"
|
||||
}
|
||||
|
||||
printamterr() {
|
||||
cat <<EOS
|
||||
Error: could not parse as a single-commodity amount: $1
|
||||
The report must be restricted or converted to a single commodity.
|
||||
Eg to report $, try: cur:\\\\$ or cur:\\\\\\\\$ or -B or -X$ --infer-market-prices
|
||||
EOS
|
||||
printcmd
|
||||
}
|
||||
|
||||
# main
|
||||
# shellcheck disable=SC2312
|
||||
${cmd} | while IFS=, read -r period amount; do
|
||||
if [[ ! ${amount} =~ [0-9] ]]; then continue; fi # ignore lines where amount has no digits
|
||||
if [[ ${amount} =~ , ]]; then printamterr "${amount}"; exit 1; fi # check there is a single amount column
|
||||
shopt -s inherit_errexit
|
||||
int=$(printf '%.f' "$(unquote "${amount}")")
|
||||
if [[ ${shownum} -gt 0 ]]; then num=$(printf "%10d " "${int}"); else num=""; fi
|
||||
if [[ ${int} -lt 0 ]]; then c="${negchar}"; col=${red}; else c="${poschar}"; col=${green}; fi
|
||||
n=$((int / scale))
|
||||
absn=${n#-}
|
||||
bar=$(while [[ ${absn} -gt 0 ]]; do printf "%s" "${c}"; absn=$((absn - 1)); done)
|
||||
printf '%s\t%b%s%s%b\n' "$(unquote "${period}")" "${col}" "${num}" "${bar}" "${nocol}"
|
||||
done
|
||||
|
||||
if [[ ${verbose} -gt 0 ]]; then printcmd; fi
|
||||
@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# hledger check-buynothing [-p PERIOD] [OTHERHLEDGERARGS]
|
||||
# Check for no activity in Expense accounts on Buy Nothing Day (November 28th).
|
||||
#
|
||||
# You can specify a different date or period with -p.
|
||||
# You can add other options/arguments to refine the query.
|
||||
|
||||
txns=$(hledger reg type:x -p 11/28 "$@")
|
||||
if [[ ! "$txns" == "" ]]
|
||||
then
|
||||
echo "Buy Nothing failure!"
|
||||
echo "$txns"
|
||||
exit 1
|
||||
fi
|
||||
@ -11,7 +11,7 @@
|
||||
--
|
||||
-- You could make this a standalone script that runs from anywhere and
|
||||
-- recompiles itself when changed, by replacing "runghc" above with
|
||||
-- "script --compile --resolver lts-22" (eg). However this uses the
|
||||
-- "script --compile --resolver lts-16" (eg). However this uses the
|
||||
-- hledger version from that stackage resolver, so in this case you
|
||||
-- should check out the corresponding release-tagged version of this
|
||||
-- script for compatibility (eg: git checkout 1.18.1).
|
||||
@ -111,18 +111,18 @@ import Data.Maybe (fromMaybe, mapMaybe)
|
||||
import Data.Time.Calendar (toGregorian)
|
||||
import Data.Time.Calendar.OrdinalDate (mondayStartWeek, sundayStartWeek, toOrdinalDate)
|
||||
import Data.Text (Text, isPrefixOf, pack, unpack)
|
||||
import Data.Text qualified as T
|
||||
import Data.Text.IO qualified as T
|
||||
import Hledger.Data qualified as H
|
||||
import Hledger.Query qualified as H
|
||||
import Hledger.Read qualified as H
|
||||
import Hledger.Utils.Parse qualified as H
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as T
|
||||
import qualified Hledger.Data as H
|
||||
import qualified Hledger.Query as H
|
||||
import qualified Hledger.Read as H
|
||||
import qualified Hledger.Utils.Parse as H
|
||||
import Lens.Micro (set)
|
||||
import Options.Applicative
|
||||
import System.Exit (exitFailure)
|
||||
import System.FilePath (FilePath)
|
||||
import Text.Megaparsec qualified as P
|
||||
import Text.Megaparsec.Char qualified as P
|
||||
import qualified Text.Megaparsec as P
|
||||
import qualified Text.Megaparsec.Char as P
|
||||
|
||||
-- Don't know how to preserve newlines yet.
|
||||
helptxt = unlines [
|
||||
|
||||
@ -14,18 +14,20 @@ import Data.String.QQ (s)
|
||||
import Text.Printf
|
||||
import Control.Monad
|
||||
import Data.List
|
||||
import Data.Text qualified as T
|
||||
import qualified Data.Text as T
|
||||
-- import Data.Time.Calendar
|
||||
import Safe
|
||||
import System.Exit
|
||||
import Hledger
|
||||
import Hledger.Cli.Script
|
||||
import Hledger.Cli
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
cmdmode :: Mode RawOpts
|
||||
cmdmode = hledgerCommandMode
|
||||
[s| check-postable
|
||||
Check that no postings are made to accounts with a postable:(n|no) tag.
|
||||
|
||||
_FLAGS
|
||||
|]
|
||||
[]
|
||||
[generalflagsgroup1]
|
||||
@ -36,7 +38,7 @@ Check that no postings are made to accounts with a postable:(n|no) tag.
|
||||
main :: IO ()
|
||||
main = do
|
||||
opts@CliOpts{reportspec_=_rspec} <- getHledgerCliOpts cmdmode
|
||||
withJournal opts $ \j -> do
|
||||
withJournalDo opts $ \j -> do
|
||||
let
|
||||
postedaccts = journalAccountNamesUsed j
|
||||
checkAcctPostable :: Journal -> AccountName -> Either AccountName ()
|
||||
|
||||
@ -16,12 +16,12 @@ $ hledger check-tagfiles # compiles every time (?)
|
||||
-}
|
||||
|
||||
import Control.Monad
|
||||
import Data.Text qualified as T
|
||||
import Hledger.Cli.Script
|
||||
import qualified Data.Text as T
|
||||
import Hledger.Cli
|
||||
import System.Directory
|
||||
import System.Exit
|
||||
|
||||
main = withJournal defcliopts $ \j -> do
|
||||
main = withJournalDo defcliopts $ \j -> do
|
||||
let filetags = [ (t,v)
|
||||
| (t',v') <- concatMap transactionAllTags $ jtxns j
|
||||
, let t = T.unpack t'
|
||||
|
||||
@ -17,12 +17,12 @@ $ hledger check-tagfiles # compiles if there's no compiled version
|
||||
-}
|
||||
|
||||
import Control.Monad
|
||||
import Data.Text qualified as T
|
||||
import Hledger.Cli.Script
|
||||
import qualified Data.Text as T
|
||||
import Hledger.Cli
|
||||
import System.Directory
|
||||
import System.Exit
|
||||
|
||||
main = withJournal defcliopts $ \j -> do
|
||||
main = withJournalDo defcliopts $ \j -> do
|
||||
let filetags = [ (t,v)
|
||||
| (t',v') <- concatMap transactionAllTags $ jtxns j
|
||||
, let t = T.unpack t'
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
{-# OPTIONS_GHC -Wno-missing-signatures #-}
|
||||
|
||||
import System.Environment (getArgs)
|
||||
import Hledger.Cli.Script
|
||||
import Data.Map qualified as M
|
||||
import Hledger.Cli
|
||||
import qualified Data.Map as M
|
||||
import Data.Map.Merge.Strict
|
||||
import Data.Text.Lazy.IO qualified as TL
|
||||
import qualified Data.Text.Lazy.IO as TL
|
||||
|
||||
appendReports :: MultiBalanceReport -> MultiBalanceReport -> MultiBalanceReport
|
||||
appendReports r1 r2 =
|
||||
@ -69,5 +69,5 @@ main = do
|
||||
where
|
||||
mbReport args = do
|
||||
opts@CliOpts{reportspec_=rspec} <- getHledgerCliOpts' cmdmode args
|
||||
report <- withJournal opts (return . multiBalanceReport rspec)
|
||||
report <- withJournalDo opts (return . multiBalanceReport rspec)
|
||||
return (rspec,report)
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# hledger-dc JOURNALFILE CMD [ARGS]
|
||||
# run a hledger command on a journal file which also supports Dr/Cr before the account name,
|
||||
# instead of/in addition to amount signs.
|
||||
|
||||
# If a posting begins with Dr<WHITESPACE>, remove that.
|
||||
# If it begins with Cr<WHITESPACE> and contains no number, remove that.
|
||||
# If it begins with Cr<WHITESPACE>, remove that and add a minus sign before the next number, and if that leaves a double minus, cancel those out.
|
||||
dc2sign() { sed -E -e 's/^(\s+)Dr\s+/\1/i' -e 's/^(\s+)Cr\s+([^0-9]+)$/\1\2/i' -e 's/^(\s+)Cr\s+([^0-9]+)([0-9])/\1\2-\3/i' -e 's/--([0-9])/\1/'; }
|
||||
# Or with a two space delimiter after Dr/Cr, allowing account names like "Dr Michael:checkup":
|
||||
#dc2sign() { sed -E -e 's/^(\s+)Dr\s\s+/\1/i' -e 's/^(\s+)Cr\s\s+([^0-9]+)$/\1\2/i' -e 's/^(\s+)Cr\s\s+([^0-9]+)([0-9])/\1\2-\3/i' -e 's/--([0-9])/\1/'; }
|
||||
|
||||
dc2sign <"$1" | hledger -f- "${@:2}"
|
||||
|
||||
|
||||
# Example:
|
||||
#
|
||||
# $ cat sample.journaldc
|
||||
# 2025-01-01 salary
|
||||
# Cr revenues 800 USD
|
||||
# Dr assets
|
||||
#
|
||||
# $ hledger -f sample.journaldc print
|
||||
# 2025-01-01 salary
|
||||
# Cr revenues 800 USD
|
||||
# Dr assets
|
||||
#
|
||||
# $ hledger dc sample.journaldc print
|
||||
# 2025-01-01 salary
|
||||
# revenues -800 USD
|
||||
# assets
|
||||
|
||||
# Dev notes:
|
||||
# This is syntactic sugar.
|
||||
# If useful, it should be possible to add this to journal format without too much breakage.
|
||||
#
|
||||
# Showing debits/credits separately in output, with a --dc flag, is more work.
|
||||
# It could be prototyped as a single new report, eg an addon script providing variant of the simple balance report.
|
||||
# I think both the report calculation and display code would need to change, to sum and show the positive amounts and negative amounts separately.
|
||||
# It would be a nice feature: offering a more traditional view of things, and reducing sign vs dc doubts.
|
||||
# "In France, you have to use a debit and a credit column, and can't use the positive/negative notation."
|
||||
# Would it provide any real new error checking power ? I'm not sure.
|
||||
# See also https://github.com/simonmichael/hledger/issues/71.
|
||||
@ -10,16 +10,13 @@ A git repo in the main file's directory will be autocreated if needed.
|
||||
|
||||
Subcommands:
|
||||
|
||||
hledger git [-h|--help] - show this help
|
||||
hledger git record [MSG] - record changes to journal's files (as listed by 'files')
|
||||
hledger git status - show unrecorded changes in journal's files (after first record)
|
||||
hledger git log - list recorded changes in journal's files (after first record)
|
||||
hledger git GITARGS - run another git command in this repo, on all files
|
||||
hledger git record [MSG] - record the journal's files (as listed by 'files')
|
||||
hledger git status - show unrecorded changes (after first record)
|
||||
hledger git log - list the journal's change history (after record)
|
||||
hledger git - show this help
|
||||
|
||||
The shorter r, s, l command aliases may be used instead.
|
||||
Extra/unrecognised arguments are passed to git. Git-specific flags should be preceded by --.
|
||||
|
||||
You can install this as more convenient top-level commands by creating
|
||||
Extra arguments are passed to git (git-specific flags should be preceded by --).
|
||||
You can install these as more convenient top-level commands by creating
|
||||
hledger-record, hledger-status, hledger-log scripts like:
|
||||
|
||||
#!/bin/sh
|
||||
@ -27,10 +24,9 @@ hledger-record, hledger-status, hledger-log scripts like:
|
||||
|
||||
Examples:
|
||||
|
||||
$ hledger git s # briefly show status of journal's files
|
||||
$ hledger git l -10 # briefly list last 10 commits to journal's files
|
||||
$ hledger git l -- --stat # list commits to journal's files, with summaries
|
||||
$ hledger git r 'txns' -- -n # commit changes, ignoring any pre-commit hooks
|
||||
hledger git status
|
||||
hledger git log -10
|
||||
hledger git log -- -10 --stat
|
||||
|
||||
EOF
|
||||
}
|
||||
@ -62,8 +58,9 @@ EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# TODO: also look in parent directories
|
||||
ensure_git_repo() {
|
||||
if [[ $($GIT -C "$DIR" rev-parse --is-inside-work-tree 2> /dev/null) != true ]]; then
|
||||
if [[ ! -d "$DIR/.git" ]]; then
|
||||
$GIT init "$DIR"
|
||||
echo "Created git repo in $DIR"
|
||||
fi
|
||||
@ -76,24 +73,15 @@ record() {
|
||||
ensure_git
|
||||
ensure_git_repo
|
||||
cd "$DIR"
|
||||
for F in $FILES; do $GIT add "$F"; done || echo "(ignored)" >&2
|
||||
MSG=${1:-$(date +'%Y-%m-%d %H:%M:%S %Z')}
|
||||
if [ $# -ge 1 ]; then
|
||||
shift
|
||||
fi
|
||||
$GIT commit -m "$MSG" "$@" || (echo "error: commit failed" >&2; $GIT reset -q)
|
||||
for F in $FILES; do $GIT add -f "$F"; done
|
||||
MSG=${1:-$(date +'%Y-%m-%d %H:%M:%S %Z')}; shift
|
||||
$GIT record -m "$MSG" "$@" -- "$FILES"
|
||||
}
|
||||
r() { record "$@"; }
|
||||
|
||||
status() {
|
||||
ensure_git
|
||||
# short status
|
||||
$GIT --work-tree "$DIR" status -sb "$@" -- $FILES
|
||||
echo
|
||||
# diff
|
||||
$GIT --work-tree "$DIR" diff "$@" -- $FILES
|
||||
$GIT --work-tree "$DIR" status -sb "$@" -- "$FILES"
|
||||
}
|
||||
s() { status "$@"; }
|
||||
|
||||
log() {
|
||||
ensure_git
|
||||
@ -103,14 +91,8 @@ log() {
|
||||
# TODO: limit to hledger files
|
||||
$GIT log --format='%ad %h %s' --date=short "$@"
|
||||
}
|
||||
l() { log "$@"; }
|
||||
|
||||
# * Main
|
||||
|
||||
# NOTE intended to run Commands but will run any function above
|
||||
if [[ "$1" == "-h" || "$1" == "--help" || $# == 0 ]]; then usage
|
||||
elif declare -f "$1" > /dev/null; then "$@"
|
||||
else
|
||||
ensure_git
|
||||
$GIT -C "$DIR" "$@"
|
||||
fi
|
||||
if declare -f "$1" > /dev/null; then "$@"; else usage; fi
|
||||
|
||||
122
bin/hledger-jj
122
bin/hledger-jj
@ -1,122 +0,0 @@
|
||||
#!/usr/bin/env ysh # -*- sh -*-
|
||||
# Tested with ysh 0.24
|
||||
# https://oils.pub/release/latest/doc/ysh-tour.html
|
||||
# https://oils.pub/release/latest/doc/ref/
|
||||
# Tested with jj 0.26 with auto-track disabled, ie in ~/.jjconfig.toml:
|
||||
# [snapshot]
|
||||
# auto-track = "none()"
|
||||
|
||||
const HELP = '''
|
||||
-------------------------------------------------------------------------------
|
||||
hledger-jj [COMMAND [OPTS]] - easy version control for hledger journals
|
||||
|
||||
An easy CLI for keeping your data in version control, using jj and a git repo.
|
||||
Works for $LEDGER_FILE and its subfiles only (-f is not yet supported).
|
||||
A repo will be created if needed, in $LEDGER_FILE's directory.
|
||||
You can run this tool from any directory. Commands may be abbreviated.
|
||||
Options are passed to jj; you may need to write -- first.
|
||||
''' #'
|
||||
|
||||
const HELP2 = '''
|
||||
|
||||
Examples:
|
||||
$ hledger jj status
|
||||
$ hledger jj diff
|
||||
$ hledger jj commit
|
||||
$ hledger jj c "new txns"
|
||||
$ hledger jj log -- -n5
|
||||
$ hledger-jj l -n5 --stat
|
||||
'''
|
||||
|
||||
# You could install this as more convenient top level hledger commands by
|
||||
# making hledger-commit, hledger-diff, hledger-status, hledger-log scripts like
|
||||
#
|
||||
# #!/bin/sh
|
||||
# #hledger-commit
|
||||
# hledger-jj commit "$@"
|
||||
|
||||
const S = /%start/
|
||||
const E = /%end/
|
||||
# const WS = /%word_start/
|
||||
# const WE = /%word_end/
|
||||
const FILE1 = ENV.LEDGER_FILE
|
||||
const DIR = $(dirname "$FILE1")
|
||||
const FILES = split( $(hledger -f "$FILE1" files) => replace(/ DIR '/' /, '') )
|
||||
|
||||
proc help() {
|
||||
write -n -- """
|
||||
$HELP
|
||||
Commands:
|
||||
"""
|
||||
# grep -E '^(proc +)?\w.*\(\) *{ *#+' "$0" | sed -E -e 's/^proc +//' -e 's/\(\) *\{//' -e 's/#+ /\t /'
|
||||
redir < $0 {
|
||||
for l in (io.stdin) {
|
||||
if (l ~ /S ('proc' space+)? <capture w dot* as name> '(' (![')'])* ')' dot* '###' space* <capture dot* as help>/) {
|
||||
echo "$[_group('name')] $[_group('help')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
write -n $HELP2
|
||||
}
|
||||
|
||||
proc setup() { # do initial checks/setup
|
||||
check_jj
|
||||
ensure_journal_repo
|
||||
}
|
||||
|
||||
proc check_jj() { # check that jj is installed
|
||||
if ! hash jj 2>/dev/null {
|
||||
write -n >&2 '''
|
||||
This command requires jj, but it is not installed in $PATH.
|
||||
Please install it and try again. https://jj-vcs.github.io
|
||||
'''
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
proc ensure_journal_repo() { # ensure that the journal file has a jj/git repo
|
||||
cd "$DIR" {
|
||||
if ! jj status >/dev/null 2>&1 {
|
||||
jj git init --colocate
|
||||
write "Created new colocated jj/git repo in $DIR"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc status(...opts) { ### [OPTS] - show status of journal files
|
||||
cd "$DIR" { jj status --color=always @opts @FILES | grep -vE '^Untracked paths:|\?' }
|
||||
}
|
||||
|
||||
proc diff(...opts) { ### [OPTS] - show unrecorded changes in journal files
|
||||
cd "$DIR" { jj diff @opts @FILES }
|
||||
}
|
||||
|
||||
proc commit(...opts) { ### [MSG [OPTS]] - record changes to journal files
|
||||
cd "$DIR" {
|
||||
jj file track @FILES
|
||||
var msg=${2:-$(date +'%Y-%m-%d %H:%M')}
|
||||
# if [ $# -ge 1 ]; then
|
||||
# shift
|
||||
# fi
|
||||
# shift
|
||||
jj commit -m "$msg" @opts @FILES #"$@"
|
||||
}
|
||||
}
|
||||
|
||||
proc log(...opts) { ### [OPTS] - list recorded changes to journal files
|
||||
cd "$DIR" { jj log @opts @FILES }
|
||||
}
|
||||
|
||||
if (len(ARGV) < 1) {
|
||||
help
|
||||
} else {
|
||||
var args = ARGV[1:]
|
||||
case (ARGV[0]) {
|
||||
/S ('h'('e'('l'('p')?)?)? | '-h' | '-'? '-help') E/ { help }
|
||||
/S 's'('t'('a'('t'('u'('s')?)?)?)?)? E/ { setup; status @args }
|
||||
/S 'd'('i'('f'('f')?)?)? E/ { setup; diff @args }
|
||||
/S 'c'('o'('m'('m'('i'('t')?)?)?)?)? E/ { setup; commit @args }
|
||||
/S 'l'('o'('g')?) ?E/ { setup; log @args }
|
||||
(else) { echo "Unknown command: $[ARGV[0]]"; return 1 }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user