ownfoil 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ownfoil-2.4.0/.devcontainer/devcontainer.json +29 -0
- ownfoil-2.4.0/.devcontainer/post-create.sh +58 -0
- ownfoil-2.4.0/.github/dependabot.yml +31 -0
- ownfoil-2.4.0/.github/release.yml +21 -0
- ownfoil-2.4.0/.github/workflows/build_check.yml +20 -0
- ownfoil-2.4.0/.github/workflows/docker.yml +68 -0
- ownfoil-2.4.0/.github/workflows/docker_pr.yml +32 -0
- ownfoil-2.4.0/.github/workflows/pypi.yml +27 -0
- ownfoil-2.4.0/.github/workflows/region_titles.yml +136 -0
- ownfoil-2.4.0/.github/workflows/stale.yml +21 -0
- ownfoil-2.4.0/.github/workflows/test.yml +37 -0
- ownfoil-2.4.0/.gitignore +27 -0
- ownfoil-2.4.0/Dockerfile +25 -0
- ownfoil-2.4.0/Install.md +208 -0
- ownfoil-2.4.0/LICENSE.md +661 -0
- ownfoil-2.4.0/PKG-INFO +79 -0
- ownfoil-2.4.0/README.md +45 -0
- ownfoil-2.4.0/Usage.md +311 -0
- ownfoil-2.4.0/app/app.py +545 -0
- ownfoil-2.4.0/app/auth.py +370 -0
- ownfoil-2.4.0/app/clients/__init__.py +9 -0
- ownfoil-2.4.0/app/clients/client.py +171 -0
- ownfoil-2.4.0/app/clients/cyberfoil.py +137 -0
- ownfoil-2.4.0/app/clients/sphaira.py +154 -0
- ownfoil-2.4.0/app/clients/tinfoil.py +189 -0
- ownfoil-2.4.0/app/constants.py +158 -0
- ownfoil-2.4.0/app/containers/__init__.py +8 -0
- ownfoil-2.4.0/app/containers/cnmt.py +67 -0
- ownfoil-2.4.0/app/containers/compression.py +182 -0
- ownfoil-2.4.0/app/containers/container.py +28 -0
- ownfoil-2.4.0/app/containers/verification.py +156 -0
- ownfoil-2.4.0/app/db.py +691 -0
- ownfoil-2.4.0/app/file_watcher.py +323 -0
- ownfoil-2.4.0/app/gql/README.md +550 -0
- ownfoil-2.4.0/app/gql/__init__.py +5 -0
- ownfoil-2.4.0/app/gql/cache.py +77 -0
- ownfoil-2.4.0/app/gql/context.py +40 -0
- ownfoil-2.4.0/app/gql/docs.py +44 -0
- ownfoil-2.4.0/app/gql/filters.py +665 -0
- ownfoil-2.4.0/app/gql/mutations.py +238 -0
- ownfoil-2.4.0/app/gql/resolvers.py +1174 -0
- ownfoil-2.4.0/app/gql/scalars.py +15 -0
- ownfoil-2.4.0/app/gql/schema.py +227 -0
- ownfoil-2.4.0/app/gql/selection.py +43 -0
- ownfoil-2.4.0/app/gql/types.py +557 -0
- ownfoil-2.4.0/app/gql/view.py +111 -0
- ownfoil-2.4.0/app/library.py +381 -0
- ownfoil-2.4.0/app/local.py +76 -0
- ownfoil-2.4.0/app/migrations/README +1 -0
- ownfoil-2.4.0/app/migrations/alembic.ini +51 -0
- ownfoil-2.4.0/app/migrations/env.py +111 -0
- ownfoil-2.4.0/app/migrations/script.py.mako +23 -0
- ownfoil-2.4.0/app/migrations/versions/78c33e9bffce_drop_old_files_table_and_create_new_.py +109 -0
- ownfoil-2.4.0/app/migrations/versions/a1b2c3d4e5f6_add_tasks_and_ignored_events.py +63 -0
- ownfoil-2.4.0/app/migrations/versions/a7b8c9d0e1f2_add_title_overrides.py +61 -0
- ownfoil-2.4.0/app/migrations/versions/b2c3d4e5f6a7_add_organized_column_to_files.py +22 -0
- ownfoil-2.4.0/app/migrations/versions/b8c9d0e1f2a3_add_added_at_to_files.py +29 -0
- ownfoil-2.4.0/app/migrations/versions/c3d4e5f6a7b8_add_worker_id_to_tasks.py +22 -0
- ownfoil-2.4.0/app/migrations/versions/c9d0e1f2a3b4_add_verification_to_files.py +37 -0
- ownfoil-2.4.0/app/migrations/versions/d4e5f6a7b8c9_add_temp_files.py +28 -0
- ownfoil-2.4.0/app/migrations/versions/e5f6a7b8c9d0_add_release_date_to_apps.py +25 -0
- ownfoil-2.4.0/app/migrations/versions/f6a7b8c9d0e1_add_app_files_file_id_index.py +25 -0
- ownfoil-2.4.0/app/realtime.py +233 -0
- ownfoil-2.4.0/app/run.py +101 -0
- ownfoil-2.4.0/app/settings.py +334 -0
- ownfoil-2.4.0/app/static/favicon/apple-touch-icon.png +0 -0
- ownfoil-2.4.0/app/static/favicon/favicon-96x96.png +0 -0
- ownfoil-2.4.0/app/static/favicon/favicon.ico +0 -0
- ownfoil-2.4.0/app/static/favicon/favicon.svg +5 -0
- ownfoil-2.4.0/app/static/favicon/site.webmanifest +21 -0
- ownfoil-2.4.0/app/static/favicon/web-app-manifest-192x192.png +0 -0
- ownfoil-2.4.0/app/static/favicon/web-app-manifest-512x512.png +0 -0
- ownfoil-2.4.0/app/static/js/format.js +9 -0
- ownfoil-2.4.0/app/static/js/realtime.js +87 -0
- ownfoil-2.4.0/app/static/logo/logo-1024.png +0 -0
- ownfoil-2.4.0/app/static/logo/logo-128.png +0 -0
- ownfoil-2.4.0/app/static/logo/logo-256.png +0 -0
- ownfoil-2.4.0/app/static/logo/logo-512.png +0 -0
- ownfoil-2.4.0/app/static/logo/logo-64.png +0 -0
- ownfoil-2.4.0/app/static/logo/logo.svg +3 -0
- ownfoil-2.4.0/app/static/style.css +411 -0
- ownfoil-2.4.0/app/task_events.py +150 -0
- ownfoil-2.4.0/app/tasks.py +1089 -0
- ownfoil-2.4.0/app/templates/base.html +36 -0
- ownfoil-2.4.0/app/templates/index.html +707 -0
- ownfoil-2.4.0/app/templates/login.html +34 -0
- ownfoil-2.4.0/app/templates/nav.html +43 -0
- ownfoil-2.4.0/app/templates/profile.html +7 -0
- ownfoil-2.4.0/app/templates/settings.html +1469 -0
- ownfoil-2.4.0/app/templates/settings_layout.html +33 -0
- ownfoil-2.4.0/app/templates/setup.html +542 -0
- ownfoil-2.4.0/app/templates/stats.html +169 -0
- ownfoil-2.4.0/app/templates/tasks.html +467 -0
- ownfoil-2.4.0/app/titledb/__init__.py +9 -0
- ownfoil-2.4.0/app/titledb/schema.py +142 -0
- ownfoil-2.4.0/app/titledb/store.py +611 -0
- ownfoil-2.4.0/app/titledb/update.py +106 -0
- ownfoil-2.4.0/app/titles.py +177 -0
- ownfoil-2.4.0/app/utils.py +397 -0
- ownfoil-2.4.0/app/worker.py +153 -0
- ownfoil-2.4.0/app/worker_pool.py +89 -0
- ownfoil-2.4.0/chart/Chart.yaml +8 -0
- ownfoil-2.4.0/chart/readme.md +2 -0
- ownfoil-2.4.0/chart/templates/deploy.yaml +51 -0
- ownfoil-2.4.0/chart/templates/ingress.yaml +34 -0
- ownfoil-2.4.0/chart/templates/pvc.yaml +24 -0
- ownfoil-2.4.0/chart/templates/services.yaml +19 -0
- ownfoil-2.4.0/chart/values.yaml +46 -0
- ownfoil-2.4.0/docker/run.sh +16 -0
- ownfoil-2.4.0/docker-compose.yml +22 -0
- ownfoil-2.4.0/ownfoil/__init__.py +0 -0
- ownfoil-2.4.0/ownfoil/cli.py +77 -0
- ownfoil-2.4.0/pyproject.toml +53 -0
- ownfoil-2.4.0/requirements.txt +15 -0
- ownfoil-2.4.0/tests/capture/README.md +47 -0
- ownfoil-2.4.0/tests/capture/fixture.py +105 -0
- ownfoil-2.4.0/tests/capture/run_capture.py +128 -0
- ownfoil-2.4.0/tests/capture/sanitize.py +137 -0
- ownfoil-2.4.0/tests/capture/scenarios.py +150 -0
- ownfoil-2.4.0/tests/capture/server.py +217 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/admin-browse.json +537 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/authenticated-browse.json +537 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/client-disabled.json +275 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/content-filter.json +375 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/download-repeat.json +243 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/download.json +833 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/free-browsing.json +46 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/no-shop-access.json +275 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/private-no-credentials.json +263 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/public-browse.json +517 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/unknown-user.json +275 -0
- ownfoil-2.4.0/tests/captures/cyberfoil/wrong-password.json +275 -0
- ownfoil-2.4.0/tests/captures/sphaira/admin-browse.json +97 -0
- ownfoil-2.4.0/tests/captures/sphaira/authenticated-browse.json +97 -0
- ownfoil-2.4.0/tests/captures/sphaira/client-disabled.json +97 -0
- ownfoil-2.4.0/tests/captures/sphaira/content-filter.json +97 -0
- ownfoil-2.4.0/tests/captures/sphaira/download-repeat.json +195 -0
- ownfoil-2.4.0/tests/captures/sphaira/download.json +297 -0
- ownfoil-2.4.0/tests/captures/sphaira/free-browsing.json +673 -0
- ownfoil-2.4.0/tests/captures/sphaira/no-shop-access.json +97 -0
- ownfoil-2.4.0/tests/captures/sphaira/private-no-credentials.json +93 -0
- ownfoil-2.4.0/tests/captures/sphaira/public-browse.json +93 -0
- ownfoil-2.4.0/tests/captures/sphaira/unknown-user.json +97 -0
- ownfoil-2.4.0/tests/captures/sphaira/wrong-password.json +97 -0
- ownfoil-2.4.0/tests/captures/tinfoil/admin-browse.json +127 -0
- ownfoil-2.4.0/tests/captures/tinfoil/authenticated-browse.json +127 -0
- ownfoil-2.4.0/tests/captures/tinfoil/client-disabled.json +127 -0
- ownfoil-2.4.0/tests/captures/tinfoil/content-filter.json +127 -0
- ownfoil-2.4.0/tests/captures/tinfoil/download-repeat.json +125 -0
- ownfoil-2.4.0/tests/captures/tinfoil/download.json +127 -0
- ownfoil-2.4.0/tests/captures/tinfoil/free-browsing.json +437 -0
- ownfoil-2.4.0/tests/captures/tinfoil/no-shop-access.json +127 -0
- ownfoil-2.4.0/tests/captures/tinfoil/private-no-credentials.json +123 -0
- ownfoil-2.4.0/tests/captures/tinfoil/public-browse.json +123 -0
- ownfoil-2.4.0/tests/captures/tinfoil/tinfoil-plaintext.json +133 -0
- ownfoil-2.4.0/tests/captures/tinfoil/unknown-user.json +127 -0
- ownfoil-2.4.0/tests/captures/tinfoil/wrong-password.json +127 -0
- ownfoil-2.4.0/tests/conftest.py +69 -0
- ownfoil-2.4.0/tests/test_clients.py +592 -0
- ownfoil-2.4.0/tests/test_compression.py +794 -0
- ownfoil-2.4.0/tests/test_containers.py +66 -0
- ownfoil-2.4.0/tests/test_db_paths.py +31 -0
- ownfoil-2.4.0/tests/test_download_count.py +109 -0
- ownfoil-2.4.0/tests/test_file_watcher.py +439 -0
- ownfoil-2.4.0/tests/test_first_run.py +137 -0
- ownfoil-2.4.0/tests/test_gql_app_cards.py +212 -0
- ownfoil-2.4.0/tests/test_gql_catalogue.py +160 -0
- ownfoil-2.4.0/tests/test_gql_etag.py +178 -0
- ownfoil-2.4.0/tests/test_gql_graph.py +755 -0
- ownfoil-2.4.0/tests/test_gql_mutations.py +257 -0
- ownfoil-2.4.0/tests/test_gql_schema_docs.py +58 -0
- ownfoil-2.4.0/tests/test_gql_verification_status.py +174 -0
- ownfoil-2.4.0/tests/test_lan_ip.py +99 -0
- ownfoil-2.4.0/tests/test_network_path.py +67 -0
- ownfoil-2.4.0/tests/test_open_browser.py +77 -0
- ownfoil-2.4.0/tests/test_organizer_paths.py +189 -0
- ownfoil-2.4.0/tests/test_realtime.py +230 -0
- ownfoil-2.4.0/tests/test_task_display_names.py +60 -0
- ownfoil-2.4.0/tests/test_task_events.py +321 -0
- ownfoil-2.4.0/tests/test_titledb_lifecycle.py +348 -0
- ownfoil-2.4.0/tests/test_titledb_schedule.py +75 -0
- ownfoil-2.4.0/tests/test_titledb_update.py +188 -0
- ownfoil-2.4.0/tests/test_verification.py +408 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Ownfoil",
|
|
3
|
+
"image": "mcr.microsoft.com/devcontainers/base:bookworm",
|
|
4
|
+
|
|
5
|
+
// Install uv, Python and the virtualenv once, when the container is created.
|
|
6
|
+
"postCreateCommand": "bash .devcontainer/post-create.sh",
|
|
7
|
+
|
|
8
|
+
// Make the virtualenv the default interpreter for every process in the container.
|
|
9
|
+
"remoteEnv": {
|
|
10
|
+
"PATH": "${containerWorkspaceFolder}/.venv/bin:${containerEnv:PATH}"
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
// Ownfoil web UI
|
|
14
|
+
"forwardPorts": [8465],
|
|
15
|
+
"portsAttributes": {
|
|
16
|
+
"8465": {
|
|
17
|
+
"label": "Ownfoil",
|
|
18
|
+
"onAutoForward": "notify"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
"customizations": {
|
|
23
|
+
"vscode": {
|
|
24
|
+
"extensions": [
|
|
25
|
+
"eamodio.gitlens"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Prepare the development environment: uv, Python, virtualenv and dependencies.
|
|
3
|
+
# Runs once when the dev container / Codespace is created.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
PYTHON_VERSION="3.14"
|
|
7
|
+
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
VENV_DIR="${REPO_DIR}/.venv"
|
|
9
|
+
|
|
10
|
+
# uv installs itself in ~/.local/bin
|
|
11
|
+
export PATH="${HOME}/.local/bin:${PATH}"
|
|
12
|
+
|
|
13
|
+
# 1. Install uv (the base image may already provide it)
|
|
14
|
+
if ! command -v uv >/dev/null 2>&1; then
|
|
15
|
+
echo "Installing uv..."
|
|
16
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
17
|
+
fi
|
|
18
|
+
uv --version
|
|
19
|
+
|
|
20
|
+
# 2. Install the Python version used by the Ownfoil image (see Dockerfile)
|
|
21
|
+
echo "Installing Python ${PYTHON_VERSION}..."
|
|
22
|
+
uv python install "${PYTHON_VERSION}"
|
|
23
|
+
|
|
24
|
+
# 3. Create the virtualenv
|
|
25
|
+
echo "Creating virtualenv in ${VENV_DIR}..."
|
|
26
|
+
uv venv --python "${PYTHON_VERSION}" --allow-existing "${VENV_DIR}"
|
|
27
|
+
|
|
28
|
+
# 4. Install the application requirements, plus pytest to run the test suite
|
|
29
|
+
echo "Installing requirements..."
|
|
30
|
+
uv pip install --python "${VENV_DIR}/bin/python" --requirement "${REPO_DIR}/requirements.txt" pytest
|
|
31
|
+
|
|
32
|
+
# 5. Activate the virtualenv in interactive shells
|
|
33
|
+
for rc in "${HOME}/.bashrc" "${HOME}/.zshrc"; do
|
|
34
|
+
[ -f "${rc}" ] || continue
|
|
35
|
+
grep -qxF "source ${VENV_DIR}/bin/activate" "${rc}" || {
|
|
36
|
+
printf '\n# Activate the Ownfoil virtualenv\nsource %s/bin/activate\n' "${VENV_DIR}" >> "${rc}"
|
|
37
|
+
}
|
|
38
|
+
done
|
|
39
|
+
|
|
40
|
+
echo "Environment ready: $(${VENV_DIR}/bin/python --version)"
|
|
41
|
+
|
|
42
|
+
# 6. Install the Claude Code CLI.
|
|
43
|
+
if ! command -v claude >/dev/null 2>&1; then
|
|
44
|
+
echo "Installing Claude Code CLI..."
|
|
45
|
+
curl -fsSL https://claude.ai/install.sh | bash
|
|
46
|
+
fi
|
|
47
|
+
# Skip onboarding
|
|
48
|
+
cat > ~/.claude.json << EOF
|
|
49
|
+
{
|
|
50
|
+
"hasCompletedOnboarding": true,
|
|
51
|
+
"theme": "dark",
|
|
52
|
+
"projects": {
|
|
53
|
+
"${REPO_DIR}": {
|
|
54
|
+
"hasTrustDialogAccepted": true
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
EOF
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
# Maintain dependencies for GitHub Actions
|
|
9
|
+
- package-ecosystem: "github-actions"
|
|
10
|
+
directory: "/"
|
|
11
|
+
target-branch: "develop"
|
|
12
|
+
schedule:
|
|
13
|
+
interval: "weekly"
|
|
14
|
+
labels:
|
|
15
|
+
- "type/build"
|
|
16
|
+
|
|
17
|
+
- package-ecosystem: "docker"
|
|
18
|
+
directory: "/"
|
|
19
|
+
target-branch: "develop"
|
|
20
|
+
schedule:
|
|
21
|
+
interval: "weekly"
|
|
22
|
+
labels:
|
|
23
|
+
- "type/build"
|
|
24
|
+
|
|
25
|
+
- package-ecosystem: "pip"
|
|
26
|
+
directory: "/"
|
|
27
|
+
target-branch: "develop"
|
|
28
|
+
schedule:
|
|
29
|
+
interval: "weekly"
|
|
30
|
+
labels:
|
|
31
|
+
- "type/build"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
changelog:
|
|
2
|
+
categories:
|
|
3
|
+
- title: New Features
|
|
4
|
+
labels:
|
|
5
|
+
- 'type/feat'
|
|
6
|
+
- title: Fixes and Improvements
|
|
7
|
+
labels:
|
|
8
|
+
- 'type/fix'
|
|
9
|
+
- 'type/improv'
|
|
10
|
+
- title: Other Changes
|
|
11
|
+
labels:
|
|
12
|
+
- '*'
|
|
13
|
+
exclude:
|
|
14
|
+
labels:
|
|
15
|
+
- 'type/feat'
|
|
16
|
+
- 'type/fix'
|
|
17
|
+
- 'type/improv'
|
|
18
|
+
- 'type/build'
|
|
19
|
+
- title: Dependencies
|
|
20
|
+
labels:
|
|
21
|
+
- 'type/build'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: Validate Python package build
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- '**'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: uv build
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout
|
|
14
|
+
uses: actions/checkout@v7
|
|
15
|
+
|
|
16
|
+
- name: Install uv
|
|
17
|
+
uses: astral-sh/setup-uv@v7
|
|
18
|
+
|
|
19
|
+
- name: Build package
|
|
20
|
+
run: uv build
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Publish multi arch Docker image
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- '**'
|
|
8
|
+
tags:
|
|
9
|
+
- '*.*.*'
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
push_to_registry:
|
|
13
|
+
name: Push Docker image to Docker Hub
|
|
14
|
+
if: startsWith(github.ref, 'refs/tags/') || (!startsWith(github.ref, 'refs/heads/master') && !startsWith(github.ref, 'refs/heads/dependabot') && !startsWith(github.event.head_commit.message, 'ci') && !startsWith(github.event.head_commit.message, 'doc'))
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
# Get the repository's code
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v7
|
|
20
|
+
# with:
|
|
21
|
+
# submodules: recursive
|
|
22
|
+
|
|
23
|
+
# https://github.com/docker/setup-qemu-action
|
|
24
|
+
- name: Set up QEMU
|
|
25
|
+
uses: docker/setup-qemu-action@v4
|
|
26
|
+
|
|
27
|
+
# https://github.com/docker/setup-buildx-action
|
|
28
|
+
- name: Set up Docker Buildx
|
|
29
|
+
id: buildx
|
|
30
|
+
uses: docker/setup-buildx-action@v4
|
|
31
|
+
|
|
32
|
+
- name: Log in to Docker Hub
|
|
33
|
+
uses: docker/login-action@v4
|
|
34
|
+
with:
|
|
35
|
+
username: ${{ secrets.DOCKER_USERNAME }}
|
|
36
|
+
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
37
|
+
|
|
38
|
+
- name: Extract metadata (tags, labels) for Docker
|
|
39
|
+
id: meta
|
|
40
|
+
uses: docker/metadata-action@v6
|
|
41
|
+
with:
|
|
42
|
+
images: a1ex4/ownfoil
|
|
43
|
+
flavor: |
|
|
44
|
+
latest=auto
|
|
45
|
+
tags: |
|
|
46
|
+
type=ref,event=tag
|
|
47
|
+
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/') }}
|
|
48
|
+
type=ref,event=branch,enable=${{ github.ref != 'refs/heads/master' }}
|
|
49
|
+
type=semver,pattern={{version}}
|
|
50
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
51
|
+
type=semver,pattern={{major}}
|
|
52
|
+
|
|
53
|
+
- name: Set platforms based on branch or tag
|
|
54
|
+
run: |
|
|
55
|
+
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
|
56
|
+
echo "PLATFORMS=linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6" >> $GITHUB_ENV
|
|
57
|
+
else
|
|
58
|
+
echo "PLATFORMS=linux/amd64,linux/arm64" >> $GITHUB_ENV
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
- name: Build and push Docker image
|
|
62
|
+
uses: docker/build-push-action@v7
|
|
63
|
+
with:
|
|
64
|
+
context: .
|
|
65
|
+
platforms: ${{ env.PLATFORMS }}
|
|
66
|
+
push: true
|
|
67
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
68
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Build multi arch Docker image on PR
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
push_to_registry:
|
|
8
|
+
name: Build multi arch Docker image on PR
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
# Get the repository's code
|
|
12
|
+
- name: Checkout
|
|
13
|
+
uses: actions/checkout@v7
|
|
14
|
+
# with:
|
|
15
|
+
# submodules: recursive
|
|
16
|
+
|
|
17
|
+
# https://github.com/docker/setup-qemu-action
|
|
18
|
+
- name: Set up QEMU
|
|
19
|
+
uses: docker/setup-qemu-action@v4
|
|
20
|
+
|
|
21
|
+
# https://github.com/docker/setup-buildx-action
|
|
22
|
+
- name: Set up Docker Buildx
|
|
23
|
+
id: buildx
|
|
24
|
+
uses: docker/setup-buildx-action@v4
|
|
25
|
+
|
|
26
|
+
- name: Build Docker images
|
|
27
|
+
uses: docker/build-push-action@v7
|
|
28
|
+
with:
|
|
29
|
+
context: .
|
|
30
|
+
# platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
|
|
31
|
+
platforms: linux/amd64,linux/arm64
|
|
32
|
+
push: false
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Publish Python package to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- '*.*.*'
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build_and_publish:
|
|
11
|
+
name: Build and publish to PyPI
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v7
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v7
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: uv build
|
|
25
|
+
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# This is a basic workflow to help you get started with Actions
|
|
2
|
+
|
|
3
|
+
name: Build titledb
|
|
4
|
+
|
|
5
|
+
# Controls when the workflow will run
|
|
6
|
+
on:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: '0 */4 * * *'
|
|
9
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
force:
|
|
13
|
+
description: 'Rebuild even if blawar/titledb has not moved'
|
|
14
|
+
type: boolean
|
|
15
|
+
default: false
|
|
16
|
+
|
|
17
|
+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
|
18
|
+
jobs:
|
|
19
|
+
# This workflow contains a single job called "build"
|
|
20
|
+
build:
|
|
21
|
+
# The type of runner that the job will run on
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
|
|
24
|
+
permissions:
|
|
25
|
+
contents: write
|
|
26
|
+
actions: write
|
|
27
|
+
|
|
28
|
+
# Steps represent a sequence of tasks that will be executed as part of the job
|
|
29
|
+
steps:
|
|
30
|
+
# A no-op run must not conclude as a success: nightly.link serves the latest *successful*
|
|
31
|
+
# run's artifact to pre-release Ownfoil versions, so it has to keep pointing at a run that
|
|
32
|
+
# actually uploaded one. Cancelling leaves that resolution untouched.
|
|
33
|
+
- name: Skip when blawar/titledb has not moved
|
|
34
|
+
env:
|
|
35
|
+
GH_TOKEN: ${{ github.token }}
|
|
36
|
+
# This step runs before the checkout, so gh has no local repo to infer from
|
|
37
|
+
GH_REPO: ${{ github.repository }}
|
|
38
|
+
run: |
|
|
39
|
+
set -euo pipefail
|
|
40
|
+
remote=$(git ls-remote https://github.com/blawar/titledb.git HEAD | cut -f1)
|
|
41
|
+
published=$(curl -sfL "https://github.com/${{ github.repository }}/releases/download/titledb/latest" || true)
|
|
42
|
+
echo "upstream=${remote} published=${published:-<none>}"
|
|
43
|
+
echo "titledb_sha=${remote}" >> "$GITHUB_ENV"
|
|
44
|
+
if [ "$remote" = "$published" ] && [ "${{ inputs.force }}" != "true" ]; then
|
|
45
|
+
echo "titledb unchanged, cancelling this run"
|
|
46
|
+
gh run cancel "${{ github.run_id }}"
|
|
47
|
+
sleep 60
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
|
51
|
+
- uses: actions/checkout@v7
|
|
52
|
+
- uses: actions/setup-python@v7
|
|
53
|
+
with:
|
|
54
|
+
python-version: '3.10'
|
|
55
|
+
|
|
56
|
+
# Runs a set of commands using the runners shell
|
|
57
|
+
- name: Setup folders
|
|
58
|
+
run: |
|
|
59
|
+
set -euo pipefail
|
|
60
|
+
sudo apt update && sudo apt install -y libcurl4-openssl-dev libssl-dev
|
|
61
|
+
git clone https://github.com/blawar/nut
|
|
62
|
+
cd nut
|
|
63
|
+
pip install -r requirements.txt
|
|
64
|
+
mkdir build_artefacts titledb
|
|
65
|
+
curl -fsSL --retry 3 "https://github.com/blawar/titledb/archive/${titledb_sha}.tar.gz" \
|
|
66
|
+
| tar -xz --strip-components=1 -C titledb \
|
|
67
|
+
--exclude=ncas.json --exclude=cheats.json
|
|
68
|
+
echo "formatted_date=$(date +"%Y-%m-%d_%H%M%S")" >> $GITHUB_ENV
|
|
69
|
+
# Short hash inside the artefact: consumed by Ownfoil < 2.4 through nightly.link.
|
|
70
|
+
# Explicitly 7 chars, matching what --short gave on the old shallow clone.
|
|
71
|
+
touch "build_artefacts/latest_${titledb_sha:0:7}"
|
|
72
|
+
# Full hash outside the artefact: the release marker, and what the skip check compares.
|
|
73
|
+
# Both are now the sha the tarball was pinned to, so they agree by construction.
|
|
74
|
+
echo "$titledb_sha" > latest
|
|
75
|
+
|
|
76
|
+
- uses: jannekem/run-python-script-action@v1
|
|
77
|
+
name: Generate region titles
|
|
78
|
+
with:
|
|
79
|
+
script: |
|
|
80
|
+
import os, sys
|
|
81
|
+
import json
|
|
82
|
+
|
|
83
|
+
os.chdir('nut')
|
|
84
|
+
sys.path.append(os.getcwd())
|
|
85
|
+
import nut
|
|
86
|
+
|
|
87
|
+
with open('titledb/languages.json') as f:
|
|
88
|
+
languages = json.load(f)
|
|
89
|
+
languages = dict(sorted(languages.items()))
|
|
90
|
+
for region in languages.keys():
|
|
91
|
+
for language in languages[region]:
|
|
92
|
+
print(region, language)
|
|
93
|
+
nut.importRegion(region, language)
|
|
94
|
+
os.rename('titledb/titles.json', f'build_artefacts/titles.{region}.{language}.json')
|
|
95
|
+
|
|
96
|
+
for f in [
|
|
97
|
+
'cnmts.json',
|
|
98
|
+
'languages.json',
|
|
99
|
+
'versions.json',
|
|
100
|
+
'versions.txt',
|
|
101
|
+
]:
|
|
102
|
+
os.rename(f'titledb/{f}', f'build_artefacts/{f}')
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# Must stay ahead of the compression step: pre-release versions read the uncompressed
|
|
106
|
+
# JSON straight out of this zip.
|
|
107
|
+
- uses: actions/upload-artifact@v7
|
|
108
|
+
with:
|
|
109
|
+
name: titledb
|
|
110
|
+
path: nut/build_artefacts/*
|
|
111
|
+
compression-level: 9
|
|
112
|
+
|
|
113
|
+
- name: Compress artefacts
|
|
114
|
+
run: zstd -12 -T0 --rm -q nut/build_artefacts/*.json nut/build_artefacts/versions.txt
|
|
115
|
+
|
|
116
|
+
- name: Publish to the titledb release
|
|
117
|
+
env:
|
|
118
|
+
GH_TOKEN: ${{ github.token }}
|
|
119
|
+
run: |
|
|
120
|
+
set -euo pipefail
|
|
121
|
+
gh release view titledb >/dev/null 2>&1 || \
|
|
122
|
+
gh release create titledb --prerelease --latest=false --title 'titledb data' \
|
|
123
|
+
--notes 'Rolling titledb dataset consumed by Ownfoil. Assets are replaced in place; `latest` holds the blawar/titledb commit they were built from and is always written last.'
|
|
124
|
+
uploaded=false
|
|
125
|
+
for attempt in 1 2 3; do
|
|
126
|
+
if gh release upload titledb nut/build_artefacts/*.zst --clobber; then
|
|
127
|
+
uploaded=true
|
|
128
|
+
break
|
|
129
|
+
fi
|
|
130
|
+
echo "upload attempt ${attempt} failed, retrying"
|
|
131
|
+
sleep 30
|
|
132
|
+
done
|
|
133
|
+
# Guards the invariant below: never publish the marker over a half-uploaded dataset
|
|
134
|
+
[ "$uploaded" = true ]
|
|
135
|
+
# Written last, alone: a client that sees a new hash knows every asset is already in place
|
|
136
|
+
gh release upload titledb nut/latest --clobber
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: 'Close stale issues'
|
|
2
|
+
on:
|
|
3
|
+
workflow_dispatch:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '30 1 * * *'
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
stale:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- name: Close stale issues
|
|
12
|
+
uses: actions/stale@v11
|
|
13
|
+
with:
|
|
14
|
+
days-before-stale: 30
|
|
15
|
+
days-before-close: 7
|
|
16
|
+
stale-issue-label: 'status/stale'
|
|
17
|
+
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.'
|
|
18
|
+
close-issue-message: 'Closing this issue due to inactivity. Feel free to reopen if necessary.'
|
|
19
|
+
any-of-labels: 'status/waiting-for-info'
|
|
20
|
+
operations-per-run: 200
|
|
21
|
+
debug-only: false
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
name: Tests on ${{ matrix.os }}
|
|
11
|
+
if: ${{ !startsWith(github.event.head_commit.message, 'ci') && !startsWith(github.event.head_commit.message, 'doc') }}
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest, windows-latest]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout
|
|
20
|
+
uses: actions/checkout@v7
|
|
21
|
+
|
|
22
|
+
- name: Set up uv
|
|
23
|
+
uses: astral-sh/setup-uv@v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: '3.14'
|
|
26
|
+
enable-cache: true
|
|
27
|
+
cache-dependency-glob: requirements.txt
|
|
28
|
+
|
|
29
|
+
- name: Create virtualenv
|
|
30
|
+
run: uv venv
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: uv pip install --requirement requirements.txt pytest
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: uv run pytest tests -v
|
|
37
|
+
timeout-minutes: 20
|
ownfoil-2.4.0/.gitignore
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
__pycache__
|
|
2
|
+
config
|
|
3
|
+
data
|
|
4
|
+
|
|
5
|
+
# capture harness workdir: fixture db, settings and the pseudonym map
|
|
6
|
+
tests/capture/.workdir
|
|
7
|
+
|
|
8
|
+
# venv
|
|
9
|
+
/bin
|
|
10
|
+
/venv
|
|
11
|
+
/include
|
|
12
|
+
/lib
|
|
13
|
+
/lib64
|
|
14
|
+
/pyvenv.cfg
|
|
15
|
+
/share
|
|
16
|
+
/Scripts
|
|
17
|
+
|
|
18
|
+
# pyenv
|
|
19
|
+
.python-version
|
|
20
|
+
|
|
21
|
+
# uv build/tool artifacts
|
|
22
|
+
/dist
|
|
23
|
+
ownfoil.bat
|
|
24
|
+
uv.lock
|
|
25
|
+
|
|
26
|
+
.claude
|
|
27
|
+
CLAUDE.local.md
|
ownfoil-2.4.0/Dockerfile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
FROM python:3.14-alpine
|
|
2
|
+
|
|
3
|
+
# Install platform-specific build dependencies
|
|
4
|
+
ARG TARGETPLATFORM
|
|
5
|
+
RUN apk update && apk add --no-cache bash sudo \
|
|
6
|
+
&& if [ "$TARGETPLATFORM" = "linux/arm/v6" ] || [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \
|
|
7
|
+
apk add --no-cache build-base gcc musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev; \
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
COPY requirements.txt /tmp/
|
|
11
|
+
RUN pip install --no-cache-dir --requirement /tmp/requirements.txt && rm /tmp/requirements.txt
|
|
12
|
+
RUN if [ "$TARGETPLATFORM" = "linux/arm/v6" ] || [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \
|
|
13
|
+
apk del build-base gcc musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev; \
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
RUN mkdir /app
|
|
17
|
+
COPY ./app /app
|
|
18
|
+
COPY ./docker/run.sh /app/run.sh
|
|
19
|
+
|
|
20
|
+
RUN mkdir -p /app/data
|
|
21
|
+
|
|
22
|
+
WORKDIR /app
|
|
23
|
+
|
|
24
|
+
ENTRYPOINT [ "/app/run.sh" ]
|
|
25
|
+
|