diff --git a/.github/actions/setup-project/action.yml b/.github/actions/setup-project/action.yml index 7a9b7f4..756a2af 100644 --- a/.github/actions/setup-project/action.yml +++ b/.github/actions/setup-project/action.yml @@ -6,6 +6,14 @@ inputs: description: 'If true, sets up Node.js and installs Yarn dependencies' required: false default: 'false' + setup-system-deps: + description: 'If true, installs system dependencies for GNOME/Flatpak builds' + required: false + default: 'false' + meson-version: + description: 'Meson version to install via pip (optional)' + required: false + default: '' runs: using: 'composite' @@ -22,6 +30,18 @@ runs: node-version: '24' cache: 'yarn' + - name: Install system dependencies + if: inputs.setup-system-deps == 'true' + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y ninja-build gjs python3-pip desktop-file-utils appstream libglib2.0-dev libgjs0g gettext + + - name: Install Meson + if: inputs.meson-version != '' + shell: bash + run: pip3 install --break-system-packages "meson==${{ inputs.meson-version }}" + - name: Install dependencies if: inputs.setup-node == 'true' shell: bash diff --git a/.github/workflows/flatpak-bundle-validation.yml b/.github/workflows/bundle-validation.yml similarity index 61% rename from .github/workflows/flatpak-bundle-validation.yml rename to .github/workflows/bundle-validation.yml index 6b29e60..da38e3e 100644 --- a/.github/workflows/flatpak-bundle-validation.yml +++ b/.github/workflows/bundle-validation.yml @@ -1,4 +1,4 @@ -name: '[build] flatpak validation' +name: '[build] bundle validation' on: workflow_call: @@ -9,6 +9,8 @@ on: paths-ignore: - 'po/**' push: + tags: + - 'v*' branches: - main paths-ignore: @@ -18,39 +20,6 @@ permissions: contents: read jobs: - i18n-update: - name: '[build] update translations' - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' && github.event_name != 'workflow_call' - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 1 - - - name: Install system dependencies - run: sudo apt-get update && sudo apt-get install -y meson ninja-build gjs - - - name: Setup Project - uses: ./.github/actions/setup-project - with: - setup-node: 'true' - - - name: Update POT files - run: yarn pot-generator - - - name: Commit changes - uses: stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403 - with: - commit_message: 'lang: update pot files' - file_pattern: 'po/*.po po/*.pot' - - - name: Clean up credentials - if: always() - run: | - rm -rf ~/.gnupg ~/.gnupg/private-keys-v1.d || true - find ~/.gnupg -delete 2>/dev/null || true - bundle-prod: name: '[build] validate prod bundle' runs-on: ubuntu-latest @@ -67,7 +36,7 @@ jobs: fetch-depth: 1 - name: Setup Project - uses: ./.github/actions/setup-project + uses: andrepg/do-it/.github/actions/setup-project with: setup-node: 'true' @@ -100,7 +69,7 @@ jobs: fetch-depth: 1 - name: Setup Project - uses: ./.github/actions/setup-project + uses: andrepg/do-it/.github/actions/setup-project with: setup-node: 'true' @@ -116,8 +85,3 @@ jobs: run: | rm -rf ~/.gnupg ~/.gnupg/private-keys-v1.d || true find ~/.gnupg -delete 2>/dev/null || true - - test-and-coverage: - name: '[build] test and coverage' - if: github.event_name != 'workflow_call' - uses: ./.github/workflows/test-coverage.yml diff --git a/.github/workflows/flatpak-bundle.yml b/.github/workflows/flatpak-bundle.yml index 437e6f0..c762b65 100644 --- a/.github/workflows/flatpak-bundle.yml +++ b/.github/workflows/flatpak-bundle.yml @@ -20,7 +20,7 @@ env: jobs: flatpak-validation: - uses: ./.github/workflows/flatpak-bundle-validation.yml + uses: ./.github/workflows/bundle-validation.yml flatpak-bundle: name: '[build] create flatpak bundle' @@ -37,8 +37,15 @@ jobs: with: fetch-depth: 1 + - name: Checkout flatpak keys + uses: actions/checkout@v6 + with: + sparse-checkout: | + flatpak/io.github.andrepg.Doit-latest.pub + sparse-checkout-cone-mode: false + - name: Setup Project - uses: ./.github/actions/setup-project + uses: andrepg/do-it/.github/actions/setup-project - name: Setup GPG run: | @@ -72,16 +79,48 @@ jobs: - name: Generate flatpakref run: | - cat << 'FLATPAKREF' > "${{ env.FLATPAK_NAME }}-latest.flatpakref" + # Import separate public key for distribution (not the signing key) + gpg --batch --yes --import flatpak/io.github.andrepg.Doit-latest.pub + + # Filter by email to get specific key fingerprint + DIST_KEY_FP=$(gpg --list-public-keys --with-colons "andrepg@protonmail.com" 2>/dev/null | grep "^fpr" | cut -d: -f10) + + # Validate fingerprint was extracted + if [ -z "$DIST_KEY_FP" ]; then + echo "ERROR: No key found for andrepg@protonmail.com" + exit 1 + fi + + # Export as BINARY (no --armor!), then base64 encode + GPG_PUB_KEY=$(gpg --export "$DIST_KEY_FP" | base64 -w0) + + # Validate base64 output is not empty + if [ -z "$GPG_PUB_KEY" ]; then + echo "ERROR: Failed to export or encode GPG key" + exit 1 + fi + + # Generate flatpakref with base64-encoded key + cat << FLATPAKREF > "${{ env.FLATPAK_NAME }}-latest.flatpakref" [Flatpak Ref] Title=Do It Name=${{ env.FLATPAK_NAME }} Branch=main Url=https://github.com/${{ github.repository }}/releases/download/${{ env.RELEASE_TAG }}/${{ env.FLATPAK_NAME }}-latest.flatpak IsRuntime=False - GPGKey=${{ secrets.FLATPAK_GPG_KEY }} + GPGKey=$GPG_PUB_KEY FLATPAKREF + - name: Verify flatpakref GPGKey format + run: | + # Use robust grep without anchor for INI file format + GPG_KEY_VAL=$(grep "GPGKey=" "${{ env.FLATPAK_NAME }}-latest.flatpakref" | cut -d= -f2) + if ! echo "$GPG_KEY_VAL" | base64 -d >/dev/null 2>&1; then + echo "ERROR: GPGKey is not valid base64" + exit 1 + fi + echo "Verified: GPGKey is valid base64" + - name: Upload bundle to release uses: softprops/action-gh-release@v2 with: diff --git a/.github/workflows/i18n-update.yml b/.github/workflows/i18n-update.yml new file mode 100644 index 0000000..ecc2212 --- /dev/null +++ b/.github/workflows/i18n-update.yml @@ -0,0 +1,48 @@ +name: '[build] i18n update' + +on: + pull_request: + branches: ['main'] + paths: + - 'src/**' + - 'package.json' + - 'yarn.lock' + +permissions: + contents: write + +jobs: + i18n-update: + name: '[build] update translations' + runs-on: ubuntu-latest + steps: + - name: Setup Project + uses: andrepg/do-it/.github/actions/setup-project + with: + setup-node: 'true' + setup-system-deps: 'true' + meson-version: '1.4.0' + + - name: Update POT files + run: yarn pot-generator + + - name: Create new branch for translations + run: | + git checkout -b "i18n-update/$(git rev-parse --short HEAD)" + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403 + with: + commit_message: 'lang: update pot files' + file_pattern: 'po/*.po po/*.pot' + + - name: Create PR + if: github.event_name == 'pull_request' + run: | + BRANCH_NAME="i18n-update/$(git rev-parse --short HEAD)" + git push -u origin "$BRANCH_NAME" + gh pr create --base "$GITHUB_REF_NAME" --head "$BRANCH_NAME" \ + --title "lang: update pot files" \ + --body "Automated POT file update from i18n-update workflow" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/quality-checks.yml similarity index 72% rename from .github/workflows/pr-checks.yml rename to .github/workflows/quality-checks.yml index 1d633ff..f03a7e7 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/quality-checks.yml @@ -1,4 +1,4 @@ -name: '[ci] pr checks' +name: '[ci] quality checks' on: pull_request: @@ -12,11 +12,8 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - name: Checkout code - uses: actions/checkout@v6 - - name: Setup Project - uses: ./.github/actions/setup-project + uses: andrepg/do-it/.github/actions/setup-project with: setup-node: 'true' @@ -28,11 +25,8 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - name: Checkout code - uses: actions/checkout@v6 - - name: Setup Project - uses: ./.github/actions/setup-project + uses: andrepg/do-it/.github/actions/setup-project with: setup-node: 'true' diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml index d95f6b6..47df8ae 100644 --- a/.github/workflows/test-coverage.yml +++ b/.github/workflows/test-coverage.yml @@ -12,11 +12,8 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - name: Checkout code - uses: actions/checkout@v6 - - name: Setup Project - uses: ./.github/actions/setup-project + uses: andrepg/do-it/.github/actions/setup-project with: setup-node: 'true' diff --git a/.gitignore b/.gitignore index 3688f40..fb642d7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ repo/ **/_build +**/build **/_build-*/** **/_repo-*/** **/*.json~ diff --git a/.prettierignore b/.prettierignore index ed4eb15..614a4c4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,3 +6,4 @@ _build_pot flatpak/generated-sources.json package-lock.json **.code-workspace +build diff --git a/.qlty/qlty.toml b/.qlty/qlty.toml index 394709e..17a1bfb 100644 --- a/.qlty/qlty.toml +++ b/.qlty/qlty.toml @@ -45,7 +45,7 @@ exclude_patterns = [ "**/.flatpak-builder/**", "flatpak/generated-sources.json", ".github/workflows/version-bump.yml", - ".github/workflows/pr-checks.yml", + ".github/workflows/quality-checks.yml", ] test_patterns = [ diff --git a/commitlint.static.ts b/commitlint.static.ts index c1fd7ae..3f59537 100644 --- a/commitlint.static.ts +++ b/commitlint.static.ts @@ -29,7 +29,7 @@ export const AllowedPrefixes = [ * @see https://commitlint.js.org/reference/configuration#rules */ export enum RuleConfigExecution { - always = 'always' + always = 'always', } /** @@ -38,6 +38,5 @@ export enum RuleConfigExecution { */ export enum RuleConfigName { typeEnum = 'type-enum', - headerCase = 'header-case' + headerCase = 'header-case', } - diff --git a/eslint.config.ts b/eslint.config.ts index ae9253c..ef1d057 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -13,6 +13,7 @@ export default defineConfig([ '.github/**', '.vscode/**', + '.opencode/**', 'flatpak/**', 'tests/**', diff --git a/po/POTFILES.in b/po/POTFILES.in index d6f1f37..19e38e8 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -12,7 +12,6 @@ src/app.wrapper.ts src/app.entrypoint.ts # Core files -src/core/persistence/gio-persistence.ts src/core/interfaces/task-view.ts src/core/interfaces/settings.ts src/core/interfaces/persistence.ts @@ -33,6 +32,7 @@ src/platform/gnome/actions/toast.ts src/platform/gnome/actions/quit.ts src/platform/gnome/actions/backup.ts src/platform/gnome/actions/about.ts +src/platform/gnome/persistence/gio-persistence.ts # Platform/GNOME - Views src/platform/gnome/views/doit.ts diff --git a/po/es.po b/po/es.po index 86fc4b8..8dc5391 100644 --- a/po/es.po +++ b/po/es.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: io.github.andrepg.Doit\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-12 08:48-0300\n" +"POT-Creation-Date: 2026-04-13 13:22-0300\n" "PO-Revision-Date: 2026-04-07 21:05-0300\n" "Last-Translator: André Paul Grandsire \n" "Language-Team: Spanish\n" diff --git a/po/io.github.andrepg.Doit.pot b/po/io.github.andrepg.Doit.pot index 2fce6a3..18f425c 100644 --- a/po/io.github.andrepg.Doit.pot +++ b/po/io.github.andrepg.Doit.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: io.github.andrepg.Doit\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-12 08:48-0300\n" +"POT-Creation-Date: 2026-04-13 13:22-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/po/meson.build b/po/meson.build index 0a6b0ae..1a942cc 100644 --- a/po/meson.build +++ b/po/meson.build @@ -1,7 +1,11 @@ i18n.gettext( app_id, - args: '--directory=' + meson.project_source_root() / 'po', preset: 'glib', + args: [ + '--keyword=C_:1c,2', + '--flag=C_:2:pass-c-format', + '--directory=' + meson.project_source_root() / 'po', + ], install_dir: 'share/locale' ) diff --git a/po/pt_BR.po b/po/pt_BR.po index 7cce06c..790f94d 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: io.github.andrepg.Doit\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-12 08:48-0300\n" +"POT-Creation-Date: 2026-04-13 13:22-0300\n" "PO-Revision-Date: 2026-04-07 21:15-0300\n" "Last-Translator: André Paul Grandsire \n" "Language-Team: Portuguese \n" diff --git a/src/platform/gnome/actions/backup.ts b/src/platform/gnome/actions/backup.ts index a5e4b5c..e3db793 100644 --- a/src/platform/gnome/actions/backup.ts +++ b/src/platform/gnome/actions/backup.ts @@ -64,7 +64,6 @@ const backup = () => { * Handles the export process by opening a file dialog and saving the DB contents. */ const exportJson = (parent: Adw.ApplicationWindow) => { - const dialog = createFileChooser(AppLocale.app.backup.export); dialog.save(parent, null, (dialog, result) => { @@ -88,7 +87,6 @@ const backup = () => { * Handles the import process by opening an existing JSON file and overriding the DB. */ const importJson = (parent: Adw.ApplicationWindow) => { - const dialog = createFileChooser(AppLocale.app.backup.import); dialog.open(parent, null, (dialog, result) => { diff --git a/src/platform/gnome/views/task-list-store.ts b/src/platform/gnome/views/task-list-store.ts index d3f3cb0..5742c27 100644 --- a/src/platform/gnome/views/task-list-store.ts +++ b/src/platform/gnome/views/task-list-store.ts @@ -202,9 +202,7 @@ export class TaskListStore extends Gio.ListStore { async load() { log(TaskListStore.$gtype.name, 'Loading tasks from database'); - (await this.persistence.load()).forEach( - (item) => this.append_task(item) - ); + (await this.persistence.load()).forEach((item) => this.append_task(item)); log(TaskListStore.$gtype.name, `Loaded ${this.get_count()} tasks from database`); }