diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index a60ec99..dfc69db 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -39,6 +39,11 @@ jobs: distribution: temurin java-version: "25" + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install native build dependencies shell: bash run: | @@ -47,6 +52,7 @@ jobs: apt-get update apt-get install -y --no-install-recommends \ zsh \ + python3 \ pkg-config \ libx11-dev \ libx11-xcb-dev \ @@ -58,6 +64,12 @@ jobs: libxcursor-dev \ libxfixes-dev + - name: Install web-ext + shell: bash + run: | + set -euo pipefail + npm install -g web-ext + - name: Lint shell: bash run: | @@ -74,6 +86,12 @@ jobs: trap 'rm -rf -- "$state_dir"' EXIT KEEPASSGO_STATE_DIR="$state_dir" go test -tags nox11,nowayland,novulkan ./... + - name: Firefox extension lint + shell: bash + run: | + set -euo pipefail + make browser-extension-firefox-lint + build: needs: lint-test runs-on: keepassgo-android @@ -92,6 +110,11 @@ jobs: distribution: temurin java-version: "25" + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "22" + - name: Install native build dependencies shell: bash run: | @@ -100,6 +123,7 @@ jobs: apt-get update apt-get install -y --no-install-recommends \ zsh \ + python3 \ pkg-config \ libx11-dev \ libx11-xcb-dev \ @@ -111,6 +135,12 @@ jobs: libxcursor-dev \ libxfixes-dev + - name: Install web-ext + shell: bash + run: | + set -euo pipefail + npm install -g web-ext + - name: Prepare dist directory shell: bash run: | @@ -159,6 +189,13 @@ jobs: make apk-release RELEASE_SIGNKEY="$signkey_path" RELEASE_SIGNPASS_FILE="$signpass_path" cp build/keepassgo.apk "${DIST_DIR}/keepassgo.apk" + - name: Build Firefox extension + shell: bash + run: | + set -euo pipefail + make browser-extension-firefox-build + cp build/browser-extension/*.zip "${DIST_DIR}/" + - name: Upload CI artifacts uses: christopherhx/gitea-upload-artifact@v4 env: @@ -171,6 +208,7 @@ jobs: dist/keepassgo-windows-amd64.exe dist/keepassgo-windows-arm64.exe dist/keepassgo.apk + dist/*.zip retention-days: 30 - name: Publish release artifacts @@ -193,4 +231,5 @@ jobs: "${DIST_DIR}/keepassgo-linux-amd64" \ "${DIST_DIR}/keepassgo-windows-amd64.exe" \ "${DIST_DIR}/keepassgo-windows-arm64.exe" \ - "${DIST_DIR}/keepassgo.apk" + "${DIST_DIR}/keepassgo.apk" \ + "${DIST_DIR}"/*.zip diff --git a/Makefile b/Makefile index 2c29c83..3bfe151 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ ARCH_PKG_TMPL ?= $(ARCH_PKG_DIR)/PKGBUILD.tmpl ARCH_PKGBUILD ?= $(ARCH_PKG_DIR)/PKGBUILD ARCH_PKGVER ?= $(shell printf 'r%s.%s' "$$(git rev-list --count HEAD 2>/dev/null || echo 0)" "$$(git rev-parse --short HEAD 2>/dev/null || echo dev)") ARCH_REPO_DIR ?= $(CURDIR) +WEB_EXT ?= web-ext +FIREFOX_EXTENSION_DIR ?= build/firefox-extension +FIREFOX_EXTENSION_ARTIFACT_DIR ?= build/browser-extension GOGIO_SIGN_FLAGS := ifneq ($(strip $(SIGNKEY)),) @@ -44,7 +47,7 @@ CONTAINER_SIGNPASSFILE_MOUNT += -v "$(dir $(abspath $(SIGNPASS_FILE))):$(dir $(a CONTAINER_SIGN_ARGS += SIGNPASS_FILE="$(abspath $(SIGNPASS_FILE))" endif -.PHONY: apk apk-local apk-release apk-container apk-container-image archlinux-pkgbuild browser-bridge browser-extension-validate +.PHONY: apk apk-local apk-release apk-container apk-container-image archlinux-pkgbuild browser-bridge browser-extension-validate browser-extension-firefox-dir browser-extension-firefox-lint browser-extension-firefox-build browser-extension-firefox-run browser-extension-firefox-sign apk: @if [ -x "$(JAVA_HOME)/bin/java" ] && "$(JAVA_HOME)/bin/java" -version 2>&1 | grep -q 'version "25'; then \ $(MAKE) apk-local JAVA_HOME="$(JAVA_HOME)"; \ @@ -132,6 +135,23 @@ archlinux-pkgbuild: $(ARCH_PKG_TMPL) Makefile browser-bridge: go build ./cmd/keepassgo-browser-bridge +browser-extension-firefox-dir: + @mkdir -p "$(dir $(FIREFOX_EXTENSION_DIR))" + @python3 scripts/prepare_firefox_extension.py "$(FIREFOX_EXTENSION_DIR)" + +browser-extension-firefox-lint: browser-extension-firefox-dir + $(WEB_EXT) lint --source-dir "$(FIREFOX_EXTENSION_DIR)" + +browser-extension-firefox-build: browser-extension-firefox-dir + @mkdir -p "$(FIREFOX_EXTENSION_ARTIFACT_DIR)" + $(WEB_EXT) build --source-dir "$(FIREFOX_EXTENSION_DIR)" --artifacts-dir "$(FIREFOX_EXTENSION_ARTIFACT_DIR)" + +browser-extension-firefox-run: browser-extension-firefox-dir + $(WEB_EXT) run --source-dir "$(FIREFOX_EXTENSION_DIR)" + +browser-extension-firefox-sign: browser-extension-firefox-dir + $(WEB_EXT) sign --source-dir "$(FIREFOX_EXTENSION_DIR)" + browser-extension-validate: @command -v xvfb-run >/dev/null 2>&1 || { echo "xvfb-run is required"; exit 1; } @command -v firefox >/dev/null 2>&1 || { echo "firefox is required"; exit 1; } diff --git a/scripts/prepare_firefox_extension.py b/scripts/prepare_firefox_extension.py new file mode 100644 index 0000000..a01c0af --- /dev/null +++ b/scripts/prepare_firefox_extension.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +import argparse +import json +import shutil +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[1] +SOURCE_DIR = REPO_ROOT / "browser" / "extension" + + +def main() -> int: + parser = argparse.ArgumentParser(description="Prepare a Firefox extension directory for web-ext.") + parser.add_argument("output_dir", help="directory to write the prepared extension into") + args = parser.parse_args() + + output_dir = Path(args.output_dir).resolve() + if output_dir.exists(): + shutil.rmtree(output_dir) + shutil.copytree(SOURCE_DIR, output_dir) + + manifest = json.loads((output_dir / "manifest.firefox.json").read_text(encoding="utf-8")) + (output_dir / "manifest.json").write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())