Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Lint, run the suite, build the package.
#
# The suites drive real GTK objects against a real X display -- they never map
# a window, but they do need a server -- so everything runs under xvfb. They
# also read real GSettings schemas rather than stubbing them, which is why
# three schema packages are installed: gnome-settings-daemon-common owns
# org.gnome.settings-daemon.plugins.media-keys and gnome-shell-common owns
# org.gnome.shell.keybindings (both looked up by the hotkey suite), and
# gsettings-desktop-schemas owns org.gnome.desktop.sound (the sound suite).
# alsa-utils is there for aplay: the sound suite checks that a player the
# package recommends is actually on the machine, and the runner has none.
name: CI

on: [push, pull_request]

permissions:
contents: read

jobs:
check:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4

# Deliberately no actions/setup-python: the suites import gi, which
# belongs to the system python3 that python3-gi installs into. Another
# interpreter cannot see it.
- name: Install the dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
python3-gi python3-gi-cairo python3-cairo \
gir1.2-gtk-3.0 gir1.2-gdkpixbuf-2.0 gir1.2-notify-0.7 \
gir1.2-wnck-3.0 gsettings-desktop-schemas \
gnome-settings-daemon-common gnome-shell-common \
xvfb desktop-file-utils alsa-utils

# Pinned: an unrelated pull request should not go red because a new
# ruff release added a rule.
- name: Lint
run: pipx run --spec ruff==0.16.6 ruff check src tests

- name: Tests
run: xvfb-run -a python3 tests/run.py

- name: Build
run: ./build.sh
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ containing folder with the file selected.
./build.sh --install
```

That produces `dist/programmers-screenshot_0.27.0_all.deb` and installs it with
apt (which pulls in the dependencies). To build without installing, drop the
flag and install by hand:
That produces `dist/programmers-screenshot_<version>_all.deb` and installs it
with apt (which pulls in the dependencies). The version is whatever the
program says it is; the current number is on the
[Releases page](https://github.com/shubshub/programmers-screenshot/releases).
To build without installing, drop the flag and install by hand:

```bash
./build.sh
sudo apt install ./dist/programmers-screenshot_0.27.0_all.deb
sudo apt install ./dist/programmers-screenshot_<version>_all.deb
```

## Bind it to a key
Expand Down
14 changes: 12 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@
# ./build.sh --install -> build, then install it with apt
set -euo pipefail

VERSION="0.27.0"
PACKAGE="programmers-screenshot"
ARCH="all"

HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# One place the version is written: the program itself. Everything that needs
# it reads it from there, so a bump cannot leave the package, the man page and
# the program disagreeing about what this is.
VERSION="$(sed -n 's/^VERSION = "\(.*\)"$/\1/p' "$HERE/src/programmers_screenshot/cli.py")"
if [ -z "$VERSION" ]; then
echo "no VERSION found in src/programmers_screenshot/cli.py" >&2
exit 1
fi

BUILD="$HERE/build/$PACKAGE"
DIST="$HERE/dist"
DEB="$DIST/${PACKAGE}_${VERSION}_${ARCH}.deb"
Expand All @@ -36,7 +45,8 @@ install -m 0644 "$HERE"/src/programmers_screenshot/tools/*.py "$TOOLS_DIR/"
install -m 0644 "$HERE/packaging/shutter.wav" "$SOUND_DIR/shutter.wav"
install -m 0644 "$HERE/packaging/$PACKAGE.desktop" "$BUILD/usr/share/applications/$PACKAGE.desktop"
install -m 0644 "$HERE/packaging/$PACKAGE.svg" "$BUILD/usr/share/icons/hicolor/scalable/apps/$PACKAGE.svg"
gzip -9nc "$HERE/packaging/$PACKAGE.1" > "$BUILD/usr/share/man/man1/$PACKAGE.1.gz"
sed "s/@VERSION@/$VERSION/" "$HERE/packaging/$PACKAGE.1" \
| gzip -9nc > "$BUILD/usr/share/man/man1/$PACKAGE.1.gz"
chmod 0644 "$BUILD/usr/share/man/man1/$PACKAGE.1.gz"

# --- control ---------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion packaging/programmers-screenshot.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH PROGRAMMERS\-SCREENSHOT 1 "2026-09-03" "programmers-screenshot 0.27.0" "User Commands"
.TH PROGRAMMERS\-SCREENSHOT 1 "2026-09-03" "programmers-screenshot @VERSION@" "User Commands"
.SH NAME
programmers\-screenshot \- region screenshot tool for hotkey binding
.SH SYNOPSIS
Expand Down
24 changes: 16 additions & 8 deletions release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ bad() { printf ' FAIL %s\n' "$*"; problems=$((problems + 1)); }
note() { printf ' -- %s\n' "$*"; }

# --- 1. what are we releasing ----------------------------------------------
VERSION="$(sed -n 's/^VERSION="\(.*\)"$/\1/p' build.sh)"
VERSION="$(sed -n 's/^VERSION = "\(.*\)"$/\1/p' src/programmers_screenshot/cli.py)"
step "Releasing $PACKAGE $VERSION"

# --- 2. the tree is in a fit state ------------------------------------------
Expand Down Expand Up @@ -71,13 +71,14 @@ fi

# --- 3. the version agrees with itself --------------------------------------
step "Version consistency"
check_version() {
if grep -q "$2" "$1"; then ok "$1"; else bad "$1 does not mention $VERSION"; fi
}
check_version src/programmers_screenshot/cli.py "VERSION = \"$VERSION\""
check_version packaging/programmers-screenshot.1 "$PACKAGE $VERSION"
check_version README.md "${PACKAGE}_${VERSION}_all.deb"
check_version packaging/changelog "($VERSION)"
# The man page and the README no longer carry the number -- build.sh puts it
# into the one and the other points at the Releases page -- so the changelog
# is the only place left that has to be kept in step by hand.
if grep -q "($VERSION)" packaging/changelog; then
ok "packaging/changelog"
else
bad "packaging/changelog has no entry for $VERSION"
fi

# --- 4. it does what it says ------------------------------------------------
step "Tests"
Expand Down Expand Up @@ -142,6 +143,13 @@ else
bad "man page has warnings"
fi

# Generated now, so worth checking the substitution actually happened.
titled="$(gzip -dc "$STAGE/usr/share/man/man1/$PACKAGE.1.gz" | head -1)"
case "$titled" in
*"$PACKAGE $VERSION"*) ok "man page says $VERSION" ;;
*) bad "man page title line says: $titled" ;;
esac

if desktop-file-validate "$STAGE/usr/share/applications/$PACKAGE.desktop" 2>/dev/null; then
ok "desktop entry valid"
else
Expand Down
1 change: 0 additions & 1 deletion src/programmers_screenshot/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,6 @@ def load_input(path):
all -- so the browser takes its own picture of the tab it means, and this
annotates that. Every other way round is a guess about which tab was in
front.

"""
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
Expand Down
Loading