diff --git a/.ansible-lint b/.ansible-lint index 6f6bc1c..f91c1a8 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,3 +1,6 @@ --- +profile: production skip_list: - fqcn +exclude_paths: + - config.sops.yml diff --git a/.github/images/banner.png b/.github/images/banner.png new file mode 100644 index 0000000..adfcbc6 Binary files /dev/null and b/.github/images/banner.png differ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index cbd65da..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,73 +0,0 @@ ---- -name: CI -on: # yamllint disable-line rule:truthy - workflow_dispatch: - push: - pull_request: - schedule: - - cron: "0 0 * * 0" - -jobs: - - integraton-tests: - name: Integration Tests - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: [macos-13, macos-12] - - defaults: - run: - shell: zsh {0} - - env: - ANSIBLE_FORCE_COLOR: '1' - ANSIBLE_HOME: $HOME/.local/share/ansible - - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: 3.11 - - - name: Uninstall GitHub Actions' built-in Homebrew - run: curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh | NONINTERACTIVE=1 bash - - - - name: Install dependencies and set environment - run: | - sudo pip3 install -r requirements.txt - ansible-galaxy install -r requirements.yml - - - name: Linting - run: | - yamllint . - ansible-lint - - - name: Test playbook's syntax - run: ansible-playbook main.yml --syntax-check - - # - name: Playbook dry-run - # run: ansible-playbook main.yml --check - - - name: Test playbook with config.default.yml - run: | - cp config.default.yml config.yml - ansible-playbook main.yml - - - name: Test playbook - run: | - cp test/config.yml config.yml - bash test/setup.sh - ansible-playbook main.yml --skip-tags dock - - - name: Idempotence check - run: | - idempotence=$(mktemp) - ansible-playbook main.yml --skip-tags dock | tee -a ${idempotence} - tail ${idempotence} | grep -q 'changed=0.*failed=0' \ - && (echo 'Idempotence test: pass' && exit 0) \ - || (echo 'Idempotence test: fail' && exit 1) diff --git a/.github/workflows/ci.yml_ b/.github/workflows/ci.yml_ new file mode 100644 index 0000000..f53010b --- /dev/null +++ b/.github/workflows/ci.yml_ @@ -0,0 +1,87 @@ +--- +name: CI +on: # yamllint disable-line rule:truthy + workflow_dispatch: + pull_request: + push: + branches: + - master + schedule: + - cron: "0 0 * * 0" + +jobs: + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + activate-environment: "true" + + - name: Install dependencies + run: uv sync --dev + + - name: Lint YAML + run: yamllint . + + - name: Lint Ansible + run: ansible-lint + + - name: Check playbook syntax + run: ansible-playbook main.yml --syntax-check + + integration-tests: + name: Integration Tests + runs-on: ${{ matrix.os }} + needs: lint + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-26] + env: + ANSIBLE_FORCE_COLOR: "1" + + steps: + - name: Checkout repo + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + activate-environment: "true" + + - name: Install dependencies + run: uv sync --dev + + - name: Playbook dry-run + run: ansible-playbook main.yml --check + + - name: Execute playbook + run: ansible-playbook main.yml + + - name: Check idempotence + run: | + ansible-playbook main.yml --skip-tags dock | tee /tmp/idempotence.log + grep -q 'changed=0.*failed=0' /tmp/idempotence.log \ + && echo "✓ Playbook is idempotent" \ + || (echo "✗ Playbook is not idempotent" && exit 1) + + - name: Upload test logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: ansible-logs-${{ matrix.os }} + path: /tmp/idempotence.log + retention-days: 7 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..5326277 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,41 @@ +name: Lint + +on: # yamllint disable-line rule:truthy + workflow_dispatch: + pull_request: + types: [ready_for_review, reopened] # synchronize makes CI too chatt + pull_request_review: + types: [submitted] + +jobs: + lint: + name: Lint & Syntax Checks + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up Python # Leverage caching + uses: actions/setup-python@v6 + with: + python-version-file: .python-version + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + activate-environment: true + + - name: Sync dependencies + run: uv sync --dev + + - name: Install Ansible Galaxy collections + run: ansible-galaxy install -r requirements.yml + + - name: YAML lint + run: yamllint . + + - name: Ansible lint + run: ansible-lint + + - name: Check playbook syntax + run: ansible-playbook main.yml --syntax-check diff --git a/.gitignore b/.gitignore index 51dad9b..693a493 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .DS_Store ._* -venv +.venv/ +.ansible/ +.vscode/ +.decrypted~* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..a01c115 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,26 @@ +--- +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-merge-conflict + - id: check-yaml + - id: detect-private-key + - id: debug-statements + - id: double-quote-string-fixer + - id: name-tests-test + - id: requirements-txt-fixer + - repo: local + hooks: + - id: yamllint + name: yamllint + entry: .venv/bin/yamllint + language: python + types: [yaml] + - id: ansible-lint + name: ansible-lint + entry: .venv/bin/ansible-lint + language: python + types: [yaml] diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..6324d40 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.14 diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..6f58482 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,10 @@ +--- +creation_rules: + - path_regex: "config.sops.yml" + encrypted_regex: ^(dotfiles_auth_home|dotfiles_repo|dotfiles_secrets_src|dotfiles_secrets)$ + key_groups: + - age: [age1n2g0g2z9jdgnqx826e8d0d78y8z0lc7ngdadm3jw9gzpxj2nf5rs0hm6p6] + - path_regex: "config.work.sops.yml" + key_groups: + - age: [age1n2g0g2z9jdgnqx826e8d0d78y8z0lc7ngdadm3jw9gzpxj2nf5rs0hm6p6] + - age: age1n2g0g2z9jdgnqx826e8d0d78y8z0lc7ngdadm3jw9gzpxj2nf5rs0hm6p6 diff --git a/.yamllint b/.yamllint index 71dfde8..cd5d58e 100644 --- a/.yamllint +++ b/.yamllint @@ -1,10 +1,20 @@ --- extends: default +ignore: + - .venv/ + - .ansible/ + - "*.sops.y*ml" + rules: + comments: + min-spaces-from-content: 1 + comments-indentation: false + document-start: disable line-length: - max: 180 - -ignore: - - '*.enc.yml' - - venv/ + max: 160 + braces: + max-spaces-inside: 1 + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..524625b --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Afonso Costa + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 5284ab1..f9b81b8 100644 --- a/README.md +++ b/README.md @@ -2,113 +2,204 @@ [![CI](https://github.com/afonsoc12/ready-set-develop/actions/workflows/ci.yml/badge.svg)](https://github.com/afonsoc12/ready-set-develop/actions/workflows/ci.yml) -Ready, Set, Develop™ is a collection of automation scripts to streamline setting up new machines (almost) from scratch or to synchronising configs across computers, powered by [Ansible](https://ansible.com). +**Ready, Set, Develop™** is an opinionated, reproducible workstation bootstrap system built with [Ansible](https://www.ansible.com/). -## Motivation +![](./.github/images/banner.png) -Throughout my journey as a human being, I've setup enough servers and computers to ignite a profound appreciation for automation. I treat all my machines like trusty tools, but I'm not one to rely entirely on them. -In case Murphy's Law pays a visit, I take comfort in knowing my data is backed up, and I can bounce back in no time. +Automate setting up macOS development machines from scratch and keep configuration consistent across computers — including dotfiles, tooling, system preferences, and development environments. -Now, this repository? It's all about automating setting up my personal computers and synchronise configurations across them, so that I have the same dev environment across computers. +--- +## About +Over the years, I've set up enough machines to understand that **manual setup doesn't scale**. I treat computers as disposable tools: everything important is backed up, and the environment itself should be reproducible on demand. + +This repository codifies workstation setup with version-controlled configuration and repeatable, idempotent automation. In case Murphy's Law pays a visit, get productive in **minutes**, not days! + +--- ## Features -- dotfiles setup ([afonsoc12/dotfiles](https://github.com/afonsoc12/dotfiles)) -- Install homebrew and packages (formulae and casks) -- Mac App Store apps -- Python environment (pyenv, it's plugins and pip packages) -- git configuration and git clone -- macOS defaults configuration -- macOS Dock icons setup and order -- [Oh My Zsh](https://ohmyz.sh/) installation -- Configure code editors/IDEs/terminal +### 💻 Workstation Provisioning +- **Homebrew** installation and package management (formulae & casks) +- **Mac App Store** applications +- **Python environment** (pyenv, uv, plugins, pip packages) +- **Git** configuration and repository cloning +- **Zsh** shell setup with Oh My Zsh +- **Editor / IDE / terminal** configuration + +### 📁 Dotfiles Management +Dotfiles are now **first-class citizens** of this project. + +- 📂 XDG Base Directory compliant (where possible) +- 🏠 Minimal `$HOME` clutter +- 🔗 Deploy via symlink or copy +- ⚙️ Templated with Ansible +- 🔐 Secrets management via SOPS + +**Pre-configured for:** +- zsh, Git, GnuPG, VS Code, rclone, rsync, k9s, and more + +### 🎨 macOS Customization +- 🔧 System defaults +- 📌 Dock layout and ordering +- 💡 Developer-focused tweaks + +--- +## Getting Started + +### Prerequisites + +- macOS 12 or later (tested only on 26+) +- Approximately 30 minutes +- Internet connection + +## Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `RSD_REPO_URL` | `https://github.com/afonsoc12/ready-set-develop.git` | Git URL of the repository to clone. | +| `RSD_REPO_DIR` | `$XDG_DATA_HOME/ready-set-develop` | Local path where the repository is cloned. | +| `RSD_REPO_VERSION` | master | Optional branch, tag, or commit hash to checkout after cloning. | +| `RSD_FORCE_REPO` | `false` | If `true`, removes existing repository before cloning and re-clones. | +| `SOPS_AGE_KEY_FILE` | _required_ | Path to your AGE key for decrypting SOPS secrets. Must exist before running the script. | +| `RSD_SOPS_FILE` | _none_ | Optional SOPS-encrypted configuration file inside the repository, passed to Ansible as `-e sops_file=`. | +| `XDG_DATA_HOME` | `$HOME/.local/share` | Base directory for application data (XDG standard). | +| `RSD_ANSIBLE_HOME` | `$XDG_DATA_HOME/ansible` | Directory for Ansible runtime, roles, and collections. | +| `PATH` | `$HOME/Library/Python/3.9/bin:/opt/homebrew/bin:$PATH` | Ensures user Python and Homebrew binaries are available. | + +## Installation Options + +### ⚡ One-Command Bootstrap + +This method is ideal if you want a **fully automated setup**. It will: +- Install XCode Command Line Tools +- Clone this repository to `~/.local/share/ready-set-develop` (XDG-compliant) +- Install Python packages and Ansible with system python +- Install Ansible Galaxy packages +- Run the full playbook -## Installation (virgin machine) +**Run:** -1. Install Apple's Command Line Tools: +```bash +curl -sSL https://raw.githubusercontent.com/afonsoc12/ready-set-develop/main/bootstrap.sh | SOPS_AGE_KEY_FILE= zsh -s -- - ```bash - xcode-select --install - # Agree with Xcode's license - ``` +# With sops encrypted config +curl -sSL https://raw.githubusercontent.com/afonsoc12/ready-set-develop/main/bootstrap.sh | SOPS_AGE_KEY_FILE= zsh -s -- -e sops_file= +``` -2. Setup environment variables: +### Step-by-step Installation - ```shell - export PATH="$HOME/Library/Python/3.9/bin:/opt/homebrew/bin:$PATH" - export ANSIBLE_HOME="$HOME/.local/share/ansible" - ``` +#### 1️⃣ Install Command Line Tools -3. Install Ansible using the system Python: +```bash +xcode-select --install +``` - ```bash - sudo pip3 install --upgrade pip - pip3 install ansible - ``` +Accept the license when prompted. -4. Clone or download this repository +#### 2️⃣ Set Environment Variables - ```bash - git clone https://github.com/afonsoc12/ready-set-develop.git - ``` +```bash +export PATH="$HOME/Library/Python/3.9/bin:/opt/homebrew/bin:$PATH" +export ANSIBLE_HOME="$HOME/.local/share/ansible" +``` -5. Install Ansible requirements +#### 3️⃣ Install Ansible - ```bash - ansible-galaxy install -r requirements.yml - ``` +```bash +/usr/bin/pip3 install --upgrade pip +/usr/bin/pip3 install ansible +``` -6. Run playbook +#### 4️⃣ Clone Repository - ```bash - ansible-playbook main.yml --ask-become-pass --ask-vault-password - # Enter your macOS account password - ``` +```bash +git clone https://github.com/afonsoc12/ready-set-develop.git +cd ready-set-develop +``` -> Note: Alternatively, the Ansible Vault password file can be passed by the environment variable -`ANSIBLE_VAULT_PASSWORD_FILE`. However, since this is likely not in the new machine, it will be -prompted at runtime. +#### 5️⃣ Install Ansible Requirements -## Usage +```bash +ansible-galaxy install -r requirements.yml +``` -By default, the playbook will look for a `config.yml` variables file in the root of the repository. It contains my default settings for most of my machine. -However, since some of these cannot be shared, they are encrypted with [ansible-vault](https://docs.ansible.com/ansible/latest/vault_guide/index.html). +#### 6️⃣ Run Playbook -To override these, you can either replace the `config.yml` with the contents of `config.default.yml` or append the argument `-e myconfig.yml` to `ansible-playbook` command, pointing to your new config file. +```bash +export SOPS_AGE_KEY_FILE= +ansible-playbook main.yml --ask-become-pass -### Extra Tasks +# If passing a sops encrypted vars +ansible-playbook main.yml -e sops_file= --ask-become-pass +``` -These extras tasks that can be placed in `extra_tasks/`, will be executed after all roles in the playbook, without any particular order. -To skip all roles and jump straight to the extra tasks, the flag `--tags extra` can be added to the playbook. -This folder is excluded in `.gitignore`. This is where I specify a few tasks that are only specific to one machine, if any. +--- -### Potential Problems +## Running -- Issues with docker plugins not linked: [GitHub Issue](https://github.com/docker/for-mac/issues/6569#issuecomment-1312244210) +### Standard Execution -## Roles Overview +Run the full playbook: + +```bash +ansible-playbook main.yml --ask-become-pass +``` + +### Custom Configuration > TODO +Override default settings: + +```bash +ansible-playbook main.yml -e @myconfig.yml --ask-become-pass +``` + +Or replace `config.yml` with your own configuration file. + +--- + +## Development + +### Prerequisites + +- [uv](https://docs.astral.sh/uv/) + +### Installation + +#### 1️⃣ Setup development environment + +This project uses [uv](https://docs.astral.sh/uv/) to manage Python dev dependencies and sync them. + +```bash +uv sync --dev +pre-commit install +``` + +#### 2️⃣ Activate virtual environment + +```bash +source .venv/bin/activate +``` -## Testing +#### 3️⃣ Linting & syntax checks -This repo uses [GitHub Actions](https://github.com/afonsoc12/ready-set-develop/actions) for CI. This workflow runs linting and integration tests against macOS 12 and 13. I cannot guarantee this will work in Linux, and it will definitely not work in windows. +Before committing changes, run the following checks: -Linting and tests overview: -- yamllint -- ansible-lint -- ansible's `--syntax-check` -- ansible-playbook with default vars -- ansible-playbook with vars from `test/config.yml` -- [Idempotence](https://en.wikipedia.org/wiki/Idempotence) test +```bash +pre-commit run --all-files -## Credits +# OR -Copyright 2023 Afonso Costa +yamllint . +ansible-lint . +ansible-playbook main.yml --syntax-check +``` -Licensed under the Apache License, Version 2.0 (the "License") +--- +## License -Thanks to Jeff Geerling for two excellent books: [Ansible for DevOps](https://www.ansiblefordevops.com) and [Ansible for Kubernetes](https://www.ansibleforkubernetes.com). Also, for unknowingly allowing me to borrow some pieces from [geerlingguy/mac-dev-playbook](https://github.com/geerlingguy/mac-dev-playbook). The perks of [OSS](https://en.wikipedia.org/wiki/Open-source_software)! +**Copyright © 2023–2026 [Afonso Costa](https://github.com/afonsoc12)** +Licensed under the Apache License 2.0. See the [LICENSE](./LICENSE) file for details. diff --git a/ansible.cfg b/ansible.cfg index 0b40b2e..44fde30 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,8 +1,7 @@ [defaults] nocows = True -stdout_callback = yaml +result_format = yaml localhost_warning=False -ansible_python_interpreter = /usr/bin/python3 [inventory] inventory_unparsed_warning=False diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100644 index 0000000..1b51c11 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,136 @@ +#!/bin/zsh +set -euo pipefail + +# ----------------------------- +# Defaults +# ----------------------------- +RSD_REPO_URL="${RSD_REPO_URL:-https://github.com/afonsoc12/ready-set-develop.git}" + +export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" +export RSD_ANSIBLE_HOME="${RSD_ANSIBLE_HOME:-$XDG_DATA_HOME/ansible}" + +# Repo defaults +RSD_REPO_DIR="${RSD_REPO_DIR:-$XDG_DATA_HOME/ready-set-develop}" + +export PATH="$HOME/Library/Python/3.9/bin:/opt/homebrew/bin:$PATH" + +# Optional SOPS file +RSD_SOPS_FILE="${RSD_SOPS_FILE:-}" + +echo +echo "🚀 Ready, Set, Develop — bootstrap" +echo + +# ----------------------------- +# 1. Sanity checks +# ----------------------------- +if [[ "$(uname -s)" != "Darwin" ]]; then + echo "❌ This bootstrap script is intended for macOS only." + exit 1 +fi + +# ----------------------------- +# 2. Command Line Tools +# ----------------------------- +if ! xcode-select -p >/dev/null 2>&1; then + echo "🔧 Installing Apple Command Line Tools..." + xcode-select --install + echo + echo "⚠️ Complete the installation and re-run this script." + exit 1 +else + echo "✅ Command Line Tools installed" +fi + +# ----------------------------- +# 3. SOPS check +# ----------------------------- +if [[ -z "${SOPS_AGE_KEY_FILE:-}" ]]; then + echo "❌ SOPS_AGE_KEY_FILE is not set." + echo "Export your AGE key file before running:" + echo " export SOPS_AGE_KEY_FILE=" + exit 1 +fi + +if [[ ! -f "$SOPS_AGE_KEY_FILE" ]]; then + echo "❌ SOPS_AGE_KEY_FILE does not exist: $SOPS_AGE_KEY_FILE" + exit 1 +fi + +echo "🔐 SOPS AGE key detected" + +# ----------------------------- +# 4. Ensure directories exist +# ----------------------------- +echo "📁 Ensuring directories exist" +mkdir -p "$XDG_DATA_HOME" "$RSD_ANSIBLE_HOME" + +# ----------------------------- +# 5. Install Ansible (user) +# ----------------------------- +if ! command -v ansible >/dev/null 2>&1; then + echo "📦 Installing Ansible (user install)" + /usr/bin/pip3 install --upgrade pip + /usr/bin/pip3 install ansible +else + echo "✅ Ansible already installed" +fi + +# ----------------------------- +# 6. Clone repository +# ----------------------------- +if [[ -d "$RSD_REPO_DIR" && "${RSD_FORCE_REPO:-false}" == "true" ]]; then + echo "⚠️ RSD_FORCE_REPO=true, removing existing repo: $RSD_REPO_DIR" + rm -rf "$RSD_REPO_DIR" +fi + +if [[ ! -d "$RSD_REPO_DIR" ]]; then + echo "📥 Cloning ready-set-develop into: $RSD_REPO_DIR" + git clone "$RSD_REPO_URL" "$RSD_REPO_DIR" +else + echo "📂 Repository already exists: $RSD_REPO_DIR" +fi + +cd "$RSD_REPO_DIR" + +# ----------------------------- +# Checkout version if specified +# ----------------------------- +if [[ -n "${RSD_REPO_VERSION:-}" ]]; then + echo "🔀 Checking out version: $RSD_REPO_VERSION" + git fetch --all + git checkout "$RSD_REPO_VERSION" +fi + +# ----------------------------- +# 7. SOPS file (inside repo) +# ----------------------------- +if [[ -n "$RSD_SOPS_FILE" ]]; then + if [[ ! -f "$RSD_SOPS_FILE" ]]; then + echo "❌ Provided SOPS file does not exist inside repo: $RSD_SOPS_FILE" + exit 1 + fi + echo "🗝 Using SOPS file: $RSD_SOPS_FILE" +fi + +# ----------------------------- +# 8. Install Ansible requirements +# ----------------------------- +echo "📚 Installing Ansible Galaxy requirements" +ansible-galaxy install -r requirements.yml + +# ----------------------------- +# 9. Run playbook +# ----------------------------- +echo +echo "▶️ Running Ansible playbook" +echo + +ANSIBLE_CMD="ansible-playbook main.yml --ask-become-pass -v" +[[ -n "$RSD_SOPS_FILE" ]] && ANSIBLE_CMD+=" -e sops_file=$RSD_SOPS_FILE" + +eval "$ANSIBLE_CMD" + +echo +echo "🎉 Ready, Set, Develop completed successfully" +echo "You may want to restart your terminal or log out/in" diff --git a/config.default.yml b/config.default.yml index f16d3e1..6ffe72f 100644 --- a/config.default.yml +++ b/config.default.yml @@ -2,18 +2,14 @@ # ================================================== # Role: dotfiles # ================================================== -# dotfiles_repo: https://github.com/afonsoc12/dotfiles -# dotfiles_version: HEAD -# dotfiles_repo_dest: "{{ lookup('env','HOME') }}/.config/dotfiles" # dotfiles_use_links: true -# dotfiles_extra_zshrc: # If set, must set dotfiles_use_links to true # ================================================== # Role: geerlingguy.mac.homebrew # - docs: https://github.com/geerlingguy/ansible-collection-mac/blob/master/roles/homebrew/README.md # ================================================== # homebrew_upgrade_all_packages: false -homebrew_taps: [] # don't install default taps to avoid warnings in brew doctor +homebrew_taps: [] # don't install default taps to avoid warnings in brew doctor # homebrew_installed_packages: # - git # - gh @@ -67,12 +63,12 @@ mas_installed_apps: [] # ================================================== # Role: dock # ================================================== -# dock_persistent_apps: +# dockitems_persist: # - {name: "iTerm", path: "/Applications/iTerm.app"} # - {name: "Activity Monitor", path: "/System/Applications/Utilities/Activity Monitor.app"} # - {name: "Google Chrome", path: "/Applications/Google Chrome.app"} -# dock_persistent_others: +# dockitems_remove: # - {name: Applications, path: /Applications} # - {name: Downloads, path: "/Users/{{ ansible_env.USER }}/Downloads"} @@ -98,24 +94,6 @@ mas_installed_apps: [] # proxy_command: ssh -W %h:%p jumphost # strict_host_key_checking: false -# ================================================== -# Role: git -# ================================================== -# git_global_name: John Doe -# git_global_email: johndoe@test.com -# git_global_signing_key: ~/.ssh/my-ssh-key.pub -# git_global_present_configs: -# - { name: user.email, value: "{{ git_global_email }}" } -# - { name: user.signingkey, value: "{{ git_global_signing_key }}" } -# - { name: pull.rebase, value: "true" } -# - { name: commit.gpgsign, value: "true" } -# - { name: tag.gpgsign, value: "true" } -# - { name: init.defaultBranch, value: master } -# git_global_absent_configs: -# - gpg.format -# git_clone_repos: -# - { repo: git@github.com:/.git, dest: $HOME/git/ } - # ================================================== # Role: vscode # ================================================== diff --git a/config.enc.yml b/config.enc.yml deleted file mode 100644 index 534aa5e..0000000 --- a/config.enc.yml +++ /dev/null @@ -1,365 +0,0 @@ -$ANSIBLE_VAULT;1.1;AES256 -36613231336334633331623166643738343132306563643063343338656238336564396538346335 -3764633763353464323864393565366465313732366638650a663562313139326130613431616263 -37323634306166363033326366613139613337626465623532336130313232333265383731373030 -6436393838373434650a343165346462306634663930636336633965343833373838613733326438 -31343330373539363635313035303539343736633536326435366436666539353636653662643735 -33316539643564373465326539386466373164626261303461343266316138633936343465633263 -36336566356265343535313532383137353633656135313532373538316137343236376333323932 -32666230623739366235323138383237376362326363623131626661646336373262396561653366 -33323137623731383565363630616437616630326133356231333139393339376365643934626333 -34376266383038363166643761643936656662393633613966396536636561376338303132613962 -66656263383939373232663763363635356165316565613136346238623638636538666232396530 -35623131643034356333336432373239393365383462393531346564376462343737316130643666 -62386632666635333561646233343630366635396136393031653038346563396163656238376532 -32646132623439616135303962363166653531336664613137333330656365323263636635623264 -38386434633330633635396535386131646165323632343761376662653738656662613732643764 -63373138393830316466383662383338333639643561386137326264363665376365653066336232 -38363965353664633730353336303534353766393566396530396138376239363731333863303265 -33643536633330633037643238656637373030616130373934633063653165663334396662383436 -30633734373433356331303338353966623466313331633436356430323731303761373264343735 -37653635373464313265303664363539323266393433366364663035333164616638636331316461 -38363663323963616466346562303566353361343364613761656333396237323564363131303563 -32616430326434313866646337306633623537353436326439646565343265643131623938373436 -62376666316536636264343866613930383935323936383539346339343263343730663232646665 -63306665383131643233353130313132353936316330356539313634663766353866306431646130 -66623831303138663034343766613139623063373266623531336239346536383833376536363264 -36633637633130616431613637326134336637653733343664663932306336383661663535653131 -38646466366663343761643663653232316630356334363939636261616534356433373566323936 -36313861613234373263326363633236303332376366663437343632363465663965303638633633 -35376366366632636262343135623439346134346538343238396139643537383733316265666264 -63316362623131613938643762356232636331373438383463343734383234613233373262333838 -38623262376437356563353234333031396437333835323936653933653430646163643730333130 -32363135383963343935346566303364316636363565636266383737323066643330303335366234 -36663639663061336636336135353432333332303432336434333234643035316638633636323635 -38646634663534646563663631393739356233653265653735613966356330306561366661326237 -63343135333336333330306561646465316265323762396165303661383930623561393730326461 -65333461373738333233383639393032393435663536333264353735383335666335663333613161 -32363962363762346566623236656439326638343832323364363463366666626136353661353062 -36343363333165636466633537626565313639616262356637363264313031656632373566323037 -38616663336236613033383230616533356635656365313337326233633139336330396634323135 -66633739303863386235626236383938333166343363616330356462623933383630373035356336 -33316237656636626637656436306338656166376461323933656663623632363462363837316263 -64396635666438363364653635383063376432626331333730663939383364393433636535306330 -35393861366466333038313133666535333538333035653437373865336330653565656363353964 -38363533636430643537666261366636383930663633313038356162303463393230356532333236 -38323234326637653132353539643432393831333638623262636137666263363866323330633763 -66643036373364313832616536353664336463663831653462333565343933306363373537323535 -34626536393362616461643363333463616538636538316137663638316666313239306634343763 -30313136306439353436366631376338376662383132386564373465333162636639373230623166 -30623438363936633061623963333832623738626635626662393830303162386231643764303638 -64626439323366383731373363393738616363656430616336386162373532333736396337623961 -63346332623732613861623564656563373731363439313937373139386666323234646633613630 -66366535353166303036353732323564346361646566383762303334353161623164633065363363 -39323332346630346264613865313737396465336465333734613639323534653836366131666536 -62303333346630626261373636653166326636356362636135636335643665613362663531333131 -64306262353164643031306434636262366237336133333930313533323138353062323034666638 -62666233663639656330663338613466616532303033613730386462633139653235656639303834 -65343438326334626262663634636166336464383834373033666363646465656337303034376336 -38303839323138663338323564343131346136363232373063393639663530623565303561663832 -66303065626437386231663866326337633830633637633735303032343461303762653936666331 -65346661386132383731646366386562353331356366633733376266303963336633333033336634 -37613463323231326466303363643766356365613663303465373962396263623862393066626161 -64363332356135643361363332376135636439646132383835313039336233653430303861643166 -33613334623139653330363561346362663935326132643136383033373536346466613361663261 -33646533343561633738333639643965366362323738626661653865313437333463663431353966 -34303661323035323938376637326335353234643339363731383233656239623636633535366533 -33633866343734386465623064663861373464376636376462613361376333646639306232626632 -61303634656331336138323236393535343537363133333965386135313230386365393164373934 -66323664626662393263386139336339303362633562333937303765623430623062666631613430 -37373963396438653461313034653064306632396432346661626263306466353537343162626438 -61303065623161383135313161643965396337386266613734333862343933623631616330376531 -36666663616534323134373839643239323262613336333064383265376163396165386330616661 -63373763306231363130313236353739383437306166313234383536666561383837646462626133 -30396466646630623861353137326434383239626432653339323431323835356134633132626234 -65353666393065386165656637666133656139656266396464343464623037376262623231613762 -31636564353335366362313936653166626435353939313333616662376133363732626537613566 -33653936633631633966613930393162386333343231323131326631313832303766643266396264 -33306561666234366461623133353931363136306362333138303061373333346162663836353736 -66353738646664653066643435646364343564383735316265613030653136383732336164383532 -64383733643564646136313465346231356137313866393531396566623032366539396161353466 -35633335383464663838613463306530373734363330346132386238356332373665353265633036 -39323637303737663866663439613062333365643135373265353934613331303634616363386438 -33373137313937333939303866366264353434343861663762646166643764343331356165656264 -39393139386162323439646633383162333864626236646463653335396166626333636665303861 -31313735366364656634313435623562663837636532393339333964356237333238616535663531 -65626138313337353430613035303061323832653139643532393638313366363039626266633237 -66366638633464636333356362366566343430633963636536613766653461333761383134363930 -66356665306162346335636438343762336230363934356238313065643762626331313531613663 -31646337386633383265393166636139373664343762656132333239326137333231353135643036 -31323132633131343162383664316364323930373061386236316633623631646430333938373138 -33356563633435656564613539633434326236333763323366326234643634653136373961336134 -66666638356465356336643638653836343338646638663931616361343366333666323465663966 -61623564386264326534646231646331333261383964616532383561393036313633333733343963 -30623063396439643666626436373464643461363163346136643965326630656233653036663564 -36363633363638316161323164643432353035313536343531393762306430363965383365613034 -65386564393031333036383965373830383339613035386365393334356162333063306538383066 -35646165663231353539326437306466656265326437616365306365666565653732626263626337 -61363364373035643264383738663335343737363234343165383035313166376437376232656432 -36636462663633613238383730313036316337366631336134363063373732623332383465326438 -65313036613939306262623761336363613863643661326430653038366630343662623262383862 -35643233303636383330333931643463643564373963316232343464313831303939356337656337 -63373633346166646661633636316330326665643963313739646331346632646565303263613737 -33393866373235666331663139626161313764643938616362356239343663633865363864353963 -66616366366635616361313730303330363766366335666164656435653637326332396335353964 -61303834396566323237313732316561633739363765623634636536366565383165646134323038 -35373338633637366335366164343236326265316335633864373530653866646130653138313661 -66376166313636363339613031633032663339323138393864313030346136376135346233323264 -37366265326432333431303037663437646362383938323961626134643463386665353263306463 -65323863353962383839363862323565343061373565613436353261303563393434363366306631 -34626261323766653361336430613065343966333665613033363734363066303363333261623835 -33376636626265653736316230643766633862626533383031336565613962616164613462616438 -34316166363835336536336238336132336331616335303566643132393331396236313636323165 -34636535303964396163326265376636666332666139356361316532316535346137306562373966 -33396535306430626436366266633464633965343066316635656538626266313536613935323039 -31333534323431363563616633393564333965323436346537343831303036356663393130666163 -32316464643630303762633462333933333838313032356263303665303430623135613030633036 -35623337633865323234373666356239393266393934313039643363393165656433393366643363 -30653735363930373861633762643833623264666339366633636130633232643836356665336665 -30363735373634363130386631616333643562323235303031303965626330376234353632326139 -66363936393234376361353164343734386237366132373030343430303562336635393565666164 -63346463303338333966623137653731613032623736313531363032623936376236303064633534 -38373333306532653439376636656436623064373536633335303038646437373163326662396433 -61316262666365303538663862653236643564636338396338663162633633353864393434396461 -64656463373137656230666166316338623464316164326135363333383366393135376533616436 -62303537376139363365326461623665373232373133393532363966333361313762613633633866 -32313463623464336638336233306234373538383239653164656233613834323539363661343335 -35626363366238643761316231313632383032623262656535393364346464326336666566346262 -34636432666534326537386561666665393432623530306339343366633164623333643664393361 -37383166363133616637316262323838333736343831356533393132376432373639386232623865 -35363939323662326133616636353763383665626630653733626537663030346439383261633936 -38323030386435626535373032396263316237633136333965336565623030633566333365326363 -38643233363463383530386336303962343139316565636339613737613334623833626362306461 -64366334636133393733353939313766633137313063353461353532353462656265303536623638 -30326366623331643535383061356232653239323235373139636639333964366362633835383632 -35393561316561623032363666643232343963326539616565333032373937626362333862623165 -31643035656433666332353332616237363462613434336139323039336634633935653033366437 -64633737313163333063306331323663366437626635646464376234336364623061666262383164 -33386162393138363633393861306638326336313234376566383739646239386134363066346364 -38343330653831306336323736386465366165326234326231663261366466306633326336646333 -39653033623437386265613865383565343633653737346165313466306137633533343830633663 -30623861393134376561383436643263316262373538613361646339306136613634373334353531 -36393866636462316333366230613765326332353632363230626630386363633531666162653930 -32653530623237666338646335336130343936393130633866363438656432663565353035656633 -61303036343937333061653038633430303866663336636130373863656438336265663964343837 -34393163343738623236303035313266646431303338306465656536373835646536393365666436 -36353562316464383839336635336237663831636532633161326235346235346239323232343939 -31343663376335653066653763636630643337396231336636643533616432623235646331353162 -38333138616235373561613263353830616564373131636533666661376465303039663436393531 -64653061343036653362326366643731633938353536396636666365626135383963373466626266 -63383262306339323634396634323331336664396362623861376234396466636335313037386136 -35376232633462616339306264356634653634643837363537306438356262333536376631376538 -39383464396365643766386665386361656630303435666133353137623234663132373063323863 -34326636663062303764376661353436373863623234333932343135616363626133333139346631 -61326465343637353166356531346132373333353132616130336465373861366331663166653964 -30353264326366633935316566633066666532373365336661363635333563366261306461356535 -61373861663634303538633533323063643736666263326331663464363830626165363130623764 -32633130353636613666643933333231313063623632656335643434353332346332343866616439 -35616434373936616665663935396435373463363263323763636130383339656336633538393830 -34663935333862646535653765343536663164383061363761656431343563303863363662373361 -66396562343961313835383936386564373434313738393532396336663333333032333961363431 -37396431343537666438653736353234326337363739646437336438386138373630653064653935 -38333961636666383064623866653730353166663835666265653762643139313931653333623664 -30653134666436393263646636346163316130623637663639343863643062306464303538646337 -33626630386138306362353639626335633965396463353038306565336166306366636230623861 -36396334316133333763373964666236323736346366653065343031356166356563396464323338 -63613863643438636663663665353834356430353339363639326661386232306639633966666332 -37336562633238656531393361353631366334303733633865343963626565363762616138646530 -39643161633063343939643361363961616432386535333663353031356264303964386337633136 -65383262363565626335653162353163376334373430343062333562303262626338646237636462 -33343638633062316466623230326164383264353965353835393364343862316166366561376464 -66656263393363663832616162396632623333383435613231643733636561626437396261636138 -35343639643630316661323634303966386539636436396330386331383937366536313436393031 -61643231623236303765653962386636666165633939396632353265643965393638646230393439 -36663063643266393063383034373337323933313738646264616332663332353631666530653862 -65613235393764383139323133346431363364636464303333646231366536353932653336613433 -65343839306437323830353763353030313862363735383034316663656263373263663632326538 -65663533323634393935646162373430623737633931383964353965396364636331633334353536 -63643365656631393031343661306435383337316233663035303932616233333037343133623431 -33373730333030303965333565333236613539343335616665363863623762333238346566323863 -34633330313237306238663835643138653136376237366432383131336439653336636137316437 -32323764626664366562656432666663336130626430346263343662386361373334653666326461 -36633432313931316334316163306537646366343037363031353639323635663932386137376365 -37643536313761653732326236383237336365366462363466663038343333356538663135333639 -62323466366134383161653762353861356365666334343639623337336664613363356162303332 -30626265316265323537336335363934316239623061376531393839356464346536393532336637 -66313536636364353034363638656162313963623635356337646433666336386533383633373161 -66323865393131373833643131656337383735623533323162626637386165393832316538636332 -35363661633935636334383961393735656530303638356161333139663134346439616561653334 -39356661326437653134373430643731393036393731633630653932386333306364646133646165 -61313937356666613937323837666538386464383165343263313361363764333163363032636536 -66303163303835313538313130303063373262383739363933363239613661333533343933646634 -33613361343963656264343531656262336338356531343061396137393965396639353233356362 -65623566363035373062343461306165626237376263373537613666333861363534373562386465 -62623265616338313566653639356536393033316332353638626337646339313934356163633766 -33633766343165373166303038393237663963386239353737373261376539613436373031643662 -36306265663861613938613636623931336530356666363561383563386562313530623738373834 -39323432343334646136396134623532353564306535393733313738636238663864393265356238 -64646530333364623361613132333932336463653265313466356139643963353664613431656635 -64633534326232636461346233323231323464393962326533356630663238393861646664323932 -61663439333461666466303864333635323864383662636438366438386437653266386433663531 -63373437333264626533323963653036316339663831366565633637363964336435656535366161 -62663033346432366233643034613662633661653236373334306431303134333561643330633535 -30666366346338393135623237653233363465396133636163353230306663643265386463623562 -35383436353335303661623135323031306161363331653931656330383032633030626235346262 -61363131393163396465646561313538646131353333386432353464373336356236646434653832 -61363838653633356464346161393666393631383336653430383331363036313637326366646361 -35346530643438313737316235323565633865363939653864666237346130376331643732373030 -32666331636161396338666635323365623961626662316439363034343530333163326638623966 -65343061333331653762376462633734626338373031613635396564643765663531343261636232 -30323232303937313235373530323566633362313836633434353864396432376366353464633262 -30383231396462666561633835333234303363386662316664363165313361623663313938313630 -34383936623239343464643633333130613735356362333563623434656636333636616362393462 -33373836626561626533386464383764373330323933356431303164316163643535663665653361 -35373839356136643134653638356133636666316430303433396464626639306163643038383066 -61343064646532663537356263653733343464633063366366316339333363373065656434353332 -30373062306330343832396438336533333932356439323563336331353661373632653462303162 -35356433663365346134303233633064626330326632616137346234333039336463663965666238 -30336262613463396236336362663932646564666238636333373937393932346138303864616134 -63623963313161616465646133373137646165396331333765323034346432616361643633653331 -65633832623936313237323736353436323762356663663737353063663131386361353963666434 -33323634323765636265323431626333353134653263623735393364303862383036303935633838 -63366561643337363337303762653731303837393830366135306330353366663861373034646234 -31333533616362393634363238636664613532346131323964386133373861393430313964393835 -32333732366239353834393231653632613263313133366330373864643465653162396439353665 -34376134343435356530343239343437346537643763316138663739373039303465353165373438 -35313161356636643332333430356662396638616461623435643864666165363639663164343965 -65356535623334346539363865383163363836386161633330343261336531316165376563613966 -61336235383162346634373539633837626635633039323965303566323034396136653731663237 -63663138366565613434326166663730323366396532653630623337323133363564323338383265 -61366335623632363066376233656133633636343130333035613435393661366435346432633766 -38303533303463633163396338306161656430656434396432616532373365363736636332386536 -32343465376432623432313063656231343961613364623834663338306336323538373630383531 -33653539653563323361366333633031353165336265383532316131666532393235393161326531 -32663036386363323838633863313837616265326162313133343630356562663639626534306462 -39386137313935313536363230393533366231383832306363376634326666333664663533343962 -31313833633530323235666661613037313036306561343838646438323535323633386439613061 -38376433313936333537366531396264373337616461353434666139663533666130343737623965 -38326436333164323537363064396561366233663838623765303364613865646362373533373764 -66396362343562366532396335646437313137353232343438666564373266643264393736313931 -66313666613731333162363465346562333165653636316433303231663333366562353638626663 -34386539303266353661303930633238363962353665623261643338366235373638323737636165 -38623762376663336133363532393135393265353162306430653361656636396635663339333536 -33653937623637396634626332626133373937376333316236666539303639663038636365336137 -61323530376365633833613536666363373939643830336263356631626132613766333632653938 -62353139386461333365363861316534393037306135613839663335326466346137653431373131 -32323735303161623462666132663932303064373632353733643731373263393539356534653931 -64643164326431356333636637316362663366373434346139396161646433353436636434383238 -36346634383462623862383536343164626562373262643136613936343033626366343561646261 -39643732613630353366356463343331633363383938366462373034343637623536646161323332 -65656537623561643834316532336136383263373865613330396165313738323863346533393633 -66663635323930326538323065353134393132306162663263343265326530653835366166636364 -30613934393862356538663939353934393266653561663032353433396135646463373832303834 -36363234313336656236383937643164623261363431333530623264643566643231373334326666 -38316165393963373138363464633161326634663439306437313566613434313363326466363933 -34623366656263636534393231346434313562623063646464336633396662313037646264633231 -32346366303132353562303038353438616433303061653132366633353562326264336562333736 -38636135303365656434323936633264613366323539373964366631366161656338613361346563 -39363739623631346532326134643532323761663535393863633333386363313131633363333165 -65393631656533663233636665633731613736613534326664396236333765656238373162363331 -37303466623536343438373461633537613834306435356131333863643566306533316665616636 -64626264316661363430626466633039363664346432386539626666346166323331386534333366 -62303037343661326665386638343765666566626464366637386533336536623332393262383461 -31303431636533323234356133393061623438633266646161353163613061383436633362613664 -62616461336333363164653437616430383061366162396363626430656261353338383135346562 -33396364346364393131343337636666643232346133393666643163616464623936623637303539 -35626232666634656164303863396436636236303465303035353239363661323062326636343335 -66346636323666353464333162623037393562633737303236646461623537333437643930613036 -34653537646334393234303762633763303861386661346132643565636232396239373565623132 -61646361343933316133616534623766613465353261326265623066383364643838373162336539 -34633666373964653433643738366130663237303136346139613961623264643234643031653835 -61653265623161323137383964626163343733613933303031373164396433396162666138363562 -31633062356631373463356261326166663761373638643661643538643335633863643464663937 -39373830643833613962633163323737376332316564653638356165666335656437343633646437 -30663239343738636433613862343139633037326237623331663733383665386234303535376137 -66306532336630666131306135363030646530373063333266306433653262633666306264316237 -33393533633330393137613430633861393563653062316231383631623338323662623030356337 -33323739353636643738616265346262376361646562646363633135326463343262333432636331 -30363738373034643132333138353630643036663666313130363932376533383332363861363662 -32353535653466306264646164346462656232623234636362653264333864613038383136333963 -61646161663561613332666533323564626666376639386131366161663833383561323162616164 -38666632663230366332363334303233626533373837316662336163613630313838663236346132 -33366535623139646464303634363735626261393663316537393562666138666431343535623833 -33376531653035343261353766303931623537623864356565323164313563633536326663346266 -31326131366133653033383734626561646334643231383436636334396166316336323763613964 -63616263643432646139306339323132323263373561336231323737353330393536633763393434 -37326462303666333638616461323135636664303939323030646634643864343062353061303630 -38613031356362646234636562313032386233626464623833623266653130363835613235633835 -31656137333663636637363834356134313034336339303833383730333239363530303834636337 -64613163396166326437633031336664653931636639383334663833383666633533633361313434 -36666565336439313562666365383136613434666264393966373261633232623563303831653166 -64383961353035396565653539376138373139633563616364626361393031306564393166323338 -64636564666435316165373831373534356435373139313765373964366562323361363962646133 -63396261636334333461666437653434303134653366333662313138343930663262366434383962 -65393939623639346565653362373764356363336365303131356438623438646238623465643034 -39616231333031633239636631633263643430613234333434383264353736663562613266653466 -39303361623831643962623631306232336134366662646362643938646437323031323064653333 -66383737623830393563303439363238323234643931373532366531623439356163396266326364 -34373738313366343262363933653930616262663135306336363938306633386435613139613638 -64623330363033393130393461666336363965326233616330643530333636373031616362383365 -63363931336365313065353730393931353765616164316132323631323734346465656461656339 -34363538643931666137653632386538353032663564663231376136373564613366313966666230 -37333836626231303736653734386530393763333266373463653365306137346333663532383232 -62333564316262356530376635326330626266393234346239376339376166663435346262653138 -34363963353332326239386564373039663633353564363333643962613062313265346234306263 -64326165313436376133376236326138353163343062356434313031323330363431636362366136 -61643131306163633631646138383862663237353864646237376430633833646462633466616661 -63633564353039613339643131353835663037616566656165666164326233613063346634323763 -37613138396662313338623839626437303734323432653261376166383734303239373137363838 -32616231363362643632396431343536653830613530623335623238303533643435646330383866 -35643735666561323565363832666462363538323066303938643266656361666666363537396531 -38643366646434643335623066306632633432303934646132613164323862636135636562323630 -30353766643966653033313737346661363631306535356233303061333066333032303735306665 -34343433393463303931313130313033353334633330376164333162376261663937623136326435 -61626563616665393631313361376164643234623462366537303033633964653836383233646136 -30353235386137363031346630646630343736303038666161383432616530616164393964303463 -63663837393137623131616230376436346234323638316465323766663934663063393637353562 -61393735666463336537353438356161353139396561323666363932626633303831353530363637 -30313664323362336364653362613866666666613930303730653139353763336535616166373565 -61363834336232623964663236336530303631376461393361633032616233646533623365323430 -30666165623766356462366264666264333962636564663537626363333238343636306631663633 -64373862643538353037373663646536313037383135323834393838373332353633663865353264 -39336639306162653034356631353636366635396264363239663236313533363635653961616131 -64626433666337373134383764666431333832396237666161366361376334636633656264663162 -64363161383936653638353235343635323630323736656638633732313232316238336263333333 -63363434353264653962393837336466383539633365633765376265616239383335363438366563 -35373166613962623064323732653461393638343765616262643963646662393932653337366436 -64343938356532623837303137363636313765366366316164386534646564613538653963353163 -38303361326233356437356464323466356232646634313032653739386137363961613136363862 -32626262363564663637623035353564336132653537643735313834306637353931323532306331 -62396437633533323865313862613230316661383363343232366165623432636332336534663966 -37653162393438666634323761363938313362366534326633393665303165333231383336313936 -32343338613038653135633665353265636530373966653864356464633731366337393662303134 -34386436356137616539623738313736663538333030613937353133333633313663366432613562 -35326538666236363739623638326535323135323936306634353664643063323732616632343831 -65623661643732626162393936353063343033356264306332353539313530376532306565333966 -35613238616235656365643631353665373561343237663763313962306139306365666133636339 -34356130643531313439663035613634386638626363626632623366353639343532376631386138 -62616364313962353134393933323466623262373630663636343030643435366336656365633634 -38316236383833643366633861306164356238656663653733313032323236346638616535333036 -63653633623837636438383133613862643363643232663531393432343338376532333165313830 -30646561356164646166666238333864623039373637313631666130653136636437363261353935 -36616562653631363263616265356338396263613839393030636132336430323465336637376662 -37313464313663653963353935646231623162633161353936336138303932313066636366356562 -62613266326635386437356530303533643535396562313737623630636166343339373135343262 -36393238373565363961653739613932643563653534393430626436303661333430643865623362 -63333965373465343833386430623562656437646531313562336333376132383765326234353263 -64656638323835323531656465616631396330386434333362643436613639376366316438343864 -37313164366431643834353536656264663563313330303265353035383735336530323537333535 -63386433643639323436373964366337386231363839306136636634326232666236323564613437 -39613162626436303932616439343036333936616338646330363530323166373438666132393363 -63326665336165373538323766626464333839363764303639316230656466346333386166396665 -65313961633964323264303166366238303933346364646164626463373165333164626163356436 -32623138633335383062346235643735666335346236343632663838373861396633633239363763 -62656663386133653631373439656638663633633732356439663135656561363861346261373430 -39666563386363643435303632323634396663303137663765353035643939643534643338616332 -35663935646531363335653730643035653437313733303364626562373664303365623030346162 -39663564323738393337343664343633656431653936376634663833643032663061303839633836 -61613938636539393561333037393365633030383266653264353763376336663437393765613237 -61323031386164356439623136363466306364643833383638396239323962386433333334363566 -30613331643135393964643238316132653265303166376637653933386334336335636639366663 -37663061363532323231353631666266316665663934306664373138356361323266633438333733 -31323638363064653337383961316332366138306634303361306634386565656338366166356661 -32386338396138363138323830643733353265656433333564626363313939356131626532663332 -65333735623365383730396635323663653330343434313862393463373064323364303562333862 -31343038663862353336 diff --git a/config.sops.yml b/config.sops.yml new file mode 100644 index 0000000..636306a --- /dev/null +++ b/config.sops.yml @@ -0,0 +1,402 @@ +# ================================================== +# SOPS encrypted variables file +# ================================================== +# Recursively merges itself with the unencrypted +# variables in this file +# Add this flag when running the playbook: +# -e sops_file=config.sops.yml +# ================================================== +# Role: dotfiles +# ================================================== +dotfiles_auth_home: ENC[AES256_GCM,data:UM3lDorFJ+TbUVc=,iv:NxZZtldyZMhYvtwttdagt9XzlANyd+8OYCtWcx6xaMQ=,tag:OmBSTNVAIOV/DYA0BNVQFw==,type:str] +dotfiles_secrets_src: ENC[AES256_GCM,data:TQDNo2oTU15/lqcUiuBC0LL3E+mOY0ThMQ==,iv:ctPgOi2JMo6DNXpja1NV1wIP9veVqHKziD/LX6Ts6dI=,tag:zGdmqMJTR/V09UIig8SJXw==,type:str] +dotfiles_secrets: + git: + email: ENC[AES256_GCM,data:utnhj+BNEf2PY0Ac+y89JYYMwI7VqMzYhIXubtlULvgp8yT3tWpFxkKAGw==,iv:xc23TQXhp6EOPXazZR8Rjh4vFccXPBAB94oGkXyyIqg=,tag:6y+FSKORxBNr2BIHwb6Xgg==,type:str] + signing_key: ENC[AES256_GCM,data:UWfSnN3ECfgErbHL/V0+Ag==,iv:E1ukvftoEOUZ0hlzHr9kEV2MQVbgKxl+VZRE66Sjwtk=,tag:NERv2hNd3bqYjTbQCIpuhQ==,type:str] +# ================================================== +# Role: geerlingguy.mac.homebrew +# - docs: https://github.com/geerlingguy/ansible-collection-mac/blob/master/roles/homebrew/README.md +# ================================================== +homebrew_upgrade_all_packages: true +homebrew_taps: + - cirruslabs/cli + - derailed/k9s + - teamookla/speedtest +homebrew_installed_packages: + # CLI Utilities + - bat + - eza + - fzf + - htop + - iftop + - jq + - make + - pure + - rsync + - tree + - watch + - yq + # Git / Version Control + - gh + - ghorg + - git + - gnupg + - pinentry-mac + - sops + # Kubernetes / Cloud / DevOps + - ansible + - argocd + - cirruslabs/cli/cirrus + - cmctl + - cloudflared + - cf-terraforming + - derailed/k9s/k9s + - age + - helm + - influxdb-cli + - kind + - kopia + - ktop + - kubectx + - oci-cli + - rclone + - sops + - stern + - cirruslabs/cli/tart + - terraform + - velero + - etcd + # Network / Monitoring + - iperf3 + - nmap + - teamookla/speedtest/speedtest + - telnet + - wakeonlan + # Media / Download tools + - exiftool + - yt-dlp +homebrew_cask_apps: + # Development / IDEs + - arduino + - balenaetcher + - bruno + - cyberduck + - datagrip + - docker-desktop + - iterm2 + - lens + - macfuse + - mqtt-explorer + - pycharm + - raspberry-pi-imager + - tailscale-app + - veracrypt + - visual-studio-code + - yubico-authenticator + # Communication / Collaboration + - discord + - obs + - vlc + - whatsapp + - zoom + # Utilities / Productivity + - drawio + - firefox + - google-chrome + - keepassxc + - kopiaui + - logi-options-plus + - megasync + - obsidian + - openboardview + - rectangle + - sigil + - spotify + - surfshark + - tor-browser + - trezor-suite + - transmission +# ================================================== +# Role: mas (prefer brew cask when possible) +# ================================================== +mas_upgrade_all_apps: true +mas_installed_apps: + - name: AmorphousDiskMark + id: 1168254295 + - name: GeoTag + id: 1465180184 + - name: Keynote + id: 409203825 + - name: Microsoft Excel + id: 462058435 + - name: Microsoft PowerPoint + id: 462062816 + - name: Microsoft Word + id: 462054704 + - name: Numbers + id: 409203825 + - name: Pages + id: 409201541 + - name: Panorama Stitcher Mini + id: 1062350226 + - name: Spherical Viewer + id: 1489700765 + - name: Surfshark + id: 1437809329 + - name: Trello + id: 1278508951 + - name: WireGuard + id: 1451685025 +mas_uninstalled_apps: + - name: GarageBand + id: 682658836 + - name: iMovie + id: 408981434 +# ================================================== +# Role: python +# ================================================== +python_pyenv_versions: + - 3.11.14 + - 3.14.2 +python_pyenv_global: 3.14.2 +python_uv_versions: [] +python_uv_tools: + - ansible + - black + - pre-commit + - firefly-cli + - isort + - versioneer +# ================================================== +# Role: java +# ================================================== +java_versions: [] +java_jenv_global: [] +# ================================================== +# Role: dock +# ================================================== +dockitems_persist: + - name: iTerm + path: /Applications/iTerm.app + pos: 1 + - name: Activity Monitor + path: /System/Applications/Utilities/Activity Monitor.app + pos: 2 + - name: Firefox + path: /Applications/Firefox.app + pos: 3 + - name: KeePassXC + path: /Applications/KeePassXC.app + pos: 4 + - name: Messages + path: /System/Applications/Messages.app + pos: 5 + - name: FaceTime + path: /System/Applications/FaceTime.app + pos: 6 + - name: WhatsApp + path: /Applications/WhatsApp.app + pos: 7 + - name: Calendar + path: /System/Applications/Calendar.app + pos: 8 + - name: Reminders + path: /System/Applications/Reminders.app + pos: 9 + - name: Stickies + path: /System/Applications/Stickies.app + pos: 10 + - name: Obsidian + path: /Applications/Obsidian.app + pos: 11 + - name: Spotify + path: /Applications/Spotify.app + pos: 12 + - name: Photos + path: /System/Applications/Photos.app + pos: 14 + - name: VSCode + path: /Applications/Visual Studio Code.app + pos: 15 + - name: PyCharm + path: /Applications/PyCharm.app + pos: 16 + - name: Docker + path: /Applications/Docker.app + pos: 17 + - name: Bruno + path: /Applications/Bruno.app + pos: 18 + - name: Adobe Lightroom Classic + path: /Applications/Adobe Lightroom Classic/Adobe Lightroom Classic.app + pos: 19 + - name: Adobe Bridge 2023 + path: /Applications/Adobe Bridge 2023/Adobe Bridge 2023.app + pos: 20 + - name: System Settings + path: /System/Applications/System Settings.app + pos: 21 + - name: Applications + path: /Applications + pos: 22 + - name: Downloads + path: /Users/{{ ansible_env.USER }}/Downloads + pos: 23 +# ================================================== +# Role: macos +# ================================================== +macos_config_files: + - src: files/smb/nsmb.conf + dest: /etc + become: true + - src: files/rectangle/com.knollsoft.Rectangle.plist + dest: $HOME/Library/Preferences +macos_ini_properties: + # KeePassXC + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: AutoReloadOnChange + value: "false" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: AutoSaveAfterEveryChange + value: "false" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: AutoSaveNonDataChanges + value: "false" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: AutoSaveOnExit + value: "false" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: AutoTypeDelay + value: 50 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: AutoTypeStartDelay + value: 300 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: BackupBeforeSave + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: ConfigVersion + value: 2 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: GlobalAutoTypeKey + value: 80 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: GlobalAutoTypeModifiers + value: 201326592 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: General + option: UpdateCheckMessageShown + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: GUI + option: TrayIconAppearance + value: monochrome + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: AdvancedMode + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: ExcludeAlike + value: "false" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: ExcludedChars + value: '^`~;:' + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: Length + value: 20 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: Logograms + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: LowerCase + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: Math + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: Type + value: 0 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: PasswordGenerator + option: WordCount + value: 2 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: Security + option: ClearClipboardTimeout + value: 60 + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: Security + option: EnableCopyOnDoubleClick + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: Security + option: HidePasswordPreviewPanel + value: "false" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: Security + option: IconDownloadFallback + value: "true" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: Security + option: PasswordsHidden + value: "false" + - path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini + section: Security + option: PasswordsRepeatVisible + value: "false" +# macos_hosts: +# - {ip: 127.0.0.1, hosts: tst} +# - {ip: 127.0.0.1, hosts: tst2} +# - {ip: 127.0.0.1, hosts: tst3} +# - {ip: 127.0.0.1, hosts: tst4} +macos_add_adobe_hosts: true +# macos_ssh_config: # Moved to vars/ssh_config.enc.yml +# ================================================== +# Role: ide +# ================================================== +ide_vscode_extensions: + - Anan.jetbrains-darcula-theme + - github.copilot + - github.copilot-chat + - github.vscode-github-actions + - james-yu.latex-workshop + - ms-kubernetes-tools.vscode-kubernetes-tools + - ms-python.debugpy + - ms-python.python + - redhat.ansible + - redhat.vscode-yaml + - signageos.signageos-vscode-sops + - vscode-icons-team.vscode-icons +sops: + age: + - recipient: age1n2g0g2z9jdgnqx826e8d0d78y8z0lc7ngdadm3jw9gzpxj2nf5rs0hm6p6 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4SmFVdzM2WDR4MmxxSFlG + UWdDUzM5R0RzRkgzQXZvUGhzVmF4TU9mSmhjCkxlU2ZWWGhYS1ZpM3BHZHp3d01v + Y1Azb3lYdjJyTzdhRVZJSmVsTlpST3MKLS0tIGgvcG4vbGNVd3RiS1ZOTFUxNFpE + QVJaRmNIS3pkeFZJMTYwenhyemJ2Z1EKO0sv8VtyfEsuN51R3fR+6rkkrTbdvZjG + 07jWmJjRDoYmQrle5ERGKf9PJRiUFPo9ztvWs+9j009Iw6rSJrAW+Q== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-01-27T00:08:14Z" + mac: ENC[AES256_GCM,data:4GWBPHWZzzbK+RW/hvJ7KsWhJS1kt4uVQPQyrU++JWNAynjvKupXL4ggraWPHA5bzxj7t3Yh0w5BAw26Mjncg6TQKM9X5rsIrqax5SaGq4Ym3og12ChbciErXEHAeSw5eNbWbej1JIfji0NLImVQypGJ4pYDfvQD9x2mqRhet0o=,iv:s60huC9tjr19rvZly3TzhDuRowJ+F+OMeaCzWjNkr+Y=,tag:sVJg7X4pUc2Hq4xbN04dqw==,type:str] + encrypted_regex: ^(dotfiles_auth_home|dotfiles_repo|dotfiles_secrets_src|dotfiles_secrets)$ + version: 3.11.0 diff --git a/config.work.sops.yml b/config.work.sops.yml new file mode 100644 index 0000000..3035aa4 --- /dev/null +++ b/config.work.sops.yml @@ -0,0 +1,282 @@ +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:qErYj+evBUOtGKcrABWd6bJmym/uvv1KICFW9Btm,iv:NPS2bCzYx7JhE32MMA6brX4l+ty8pQqJW57t2UrbyIc=,tag:vWBMT6Y4QR6W7GEVKnCY8w==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:kOGDwm0eLra+fm8h4twrG81QPrmqVPnLI1mykM4smrI/kRmstqTcyoWkSTWcgh8=,iv:91nqYNVmAzLUnPUDUC/7DAUt0IwxdRHvlM+ZpdjC59M=,tag:PxCzFSsNhZLKBHZ2I6mf4A==,type:comment] +#ENC[AES256_GCM,data:6+8ATC0udERtc2FjxyuRonvMRkHYHQnH,iv:YUT2ZOGIoKCmSGbVPznJQS3HWaFIs4KD8nVkd3lS4fo=,tag:s6QOViuJU2yyFzbD8B9zhw==,type:comment] +#ENC[AES256_GCM,data:hnnMrOMZFFMaDvNdYv+Trxz2nI5bBwBm/dsjP1Ungx5EDK5JRB71pd0=,iv:q8YpFi4Se8EDtwG4tKa6L7rezqo1uFiRMdeANn5FZbc=,tag:VpUshY/8DO2ehdP8TqiXcQ==,type:comment] +#ENC[AES256_GCM,data:I8fma7KlzMwBjtB/bUTZIqcJJ6M5U33EYZPvwxKoA/fSjgYI,iv:kAbQeCYOlA7czC4Q4TYyZEn3z0mBZ6ygUYhaVOyYvb0=,tag:XOzohPlEfL+WNz9xnh5g8w==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:J17exn6sKZviCWXxK5G9,iv:5siNx0sfSkcBo8SmuhVAvAiLkpuQtqfOVQLd6w6Y6LE=,tag:aVXj7hKTC98pP40ZRUu8Eg==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +dotfiles_auth_home_name: ENC[AES256_GCM,data:lDBrFtY=,iv:fr6Jr7GHdvAg57r5UOVGJMoN3SYhPRdm2Tj1kI4eYX8=,tag:JGTXihfNqA3lPkU5EbZb9g==,type:str] +dotfiles_secrets: + git: + email: ENC[AES256_GCM,data:RspmyRq4nIfHtyjxYdO5YcVv,iv:YQjzHUnIwRQ+CyeNL3R4Gm+zLEu7zzcynn1cquiTKxQ=,tag:vma3cF1I8xbLIw+AexH3PA==,type:str] + signing_key: ENC[AES256_GCM,data:tPTOoEV6mcafvkh0GUmjnQ==,iv:wBORd5q/1quLCWDx2+xTrId/iriX98Og1H0JLKIkdwM=,tag:HxjvPMRUDJSL516JDUVwMA==,type:str] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:LjTPMALh4a8rzejQwIH0ETsu7LBg1h8rsje24MWAbA==,iv:SE99pKTkjxEwtKesugbYuDNi2eAXuqvPLXVXIrZWd64=,tag:y/U9Yz9BMfFZumA20hANTw==,type:comment] +#ENC[AES256_GCM,data:BfUmhmMatg4tGxaVg1wxoCMfvw7utN5j9oMWrctbnRKU506M7VG4EdaaHladhNBX/miXrD2Da9FP307tT68bXUWubm2gOQeE1eWyG+Is+SR+YL5oB5wrLKPCBVrNrMO77DYkSWY=,iv:fN8k9KdnoIcZY80hOmvdiFzFfoCPyPF5kEtijThD4A4=,tag:cL22C2+1zhCweM9fxDbipQ==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +homebrew_upgrade_all_packages: ENC[AES256_GCM,data:NqFiCg==,iv:k+pMlZHzXrTu5BUV8h6zT4ai+A3yllr8mWt1VKqSriA=,tag:NlDQpUFD6+iuK0Lc1jtbpQ==,type:bool] +homebrew_taps: + - ENC[AES256_GCM,data:bnrhV5U7WrkKOb4v,iv:bPQD2fsgR2zytXoR2gj7IlMIVUInFMppgycAe9XkxHs=,tag:kyOW9kKf0lV9b5g7I8xGKw==,type:str] + - ENC[AES256_GCM,data:zFvCJxpn/4lUjGLnxVAiqdSb6A==,iv:ileV9u6MjgXroMpwkpOuFNucElU2OsGD8F9O13EHPpo=,tag:nOlMlOC6LE3eeAOIDZSMQg==,type:str] +homebrew_installed_packages: + - ENC[AES256_GCM,data:Za56VqhPmrKGW3RTELo=,iv:CvmQhB8j7klmcU/6iGAzlxIbzPlwNmd715ajpxGvKQE=,tag:gSWm3ezETbwsJ1AnYiGh1w==,type:comment] + - ENC[AES256_GCM,data:tMvQ,iv:LsuaiwF3GdH4PRM6vTMAa3sLDEQf0rd8BkHOecCkjgA=,tag:JmLVYlqrm6Nb5pvfNyEegw==,type:str] + - ENC[AES256_GCM,data:8dcw,iv:pN9zmHEdgDdNC15QWyKtoeJgBA1j007SERCgjVKuriE=,tag:yESXhpOXQseZ2BIwrlpyxw==,type:str] + - ENC[AES256_GCM,data:1yFq,iv:cLajEjMH04NlwD5OGFLTExEh78TpGuvvBZACWjTE8S8=,tag:jXSWt9rtfJdsslsZFvscJQ==,type:str] + - ENC[AES256_GCM,data:OczArA==,iv:hsNV6h5uBTLiiJ8X8i0S//lCgDlusy7KBgYle5NUmQc=,tag:CMmiS/RxCfiUKjuj74+ERA==,type:str] + - ENC[AES256_GCM,data:CZ52uCo=,iv:1lFHQNOoKtEKusUCLPRWFH002hjHR5tB+g1qE81+0cU=,tag:OluOz1EPNYPIrl2O3cTSig==,type:str] + - ENC[AES256_GCM,data:HAs=,iv:96ql1VIDjJmpQt5gwDv3OEZDS4aGRo3BtYRRfOLE/IM=,tag:HzjdA2iwX605w2f9e4eeFw==,type:str] + - ENC[AES256_GCM,data:iLTdeg==,iv:wSR7FzHMlumwRXpThb7LVUgopTBDVs0Ts5IKkFyOZ6E=,tag:qPxQI8Nntd6aTmdv+2gSrQ==,type:str] + - ENC[AES256_GCM,data:awwIbQ==,iv:68hdhYONhMPPhV+zt7Z2HTcYFucPy79yH0iPcd+TpVQ=,tag:szfiGH8Mr3sNoCWuANNfKA==,type:str] + - ENC[AES256_GCM,data:BXiWDKw=,iv:4Rem97o7gWZnSTewv023HEEbVVtxL2ViDFVVUDs1khw=,tag:4uv/rvR1d+9VdYKuCWbqRw==,type:str] + - ENC[AES256_GCM,data:NUmMzw==,iv:sEhq1vlJiGACCx5hjIdFhqdQkwgJiZiUFM51gl/t3qA=,tag:0zxN2qpT0OFxVbyytOjl0g==,type:str] + - ENC[AES256_GCM,data:8EjLBzQ=,iv:Oj/zF+Rxffm7pDEjIEkY0Hk2KDHV9bkpM72qYJ8sH+k=,tag:qx4vWGLbO0YIqFqwGSInNQ==,type:str] + - ENC[AES256_GCM,data:JXY=,iv:TfYhX25qfxRJ24Ty9Fjcmp++ccid3dVJbLCxi2LfZNI=,tag:5dEQEUqftpKGLfQyXm0B7w==,type:str] + - ENC[AES256_GCM,data:HnJES/cJAuJ1AIv4r3Y/qMiSUNivWQ==,iv:5boyU4ZAn+Dv/NrBiB8DoECqQ68U7i5FuiY2XxNGNxE=,tag:MWsZeKkPknMqWM5wQLAruQ==,type:comment] + - ENC[AES256_GCM,data:hes=,iv:y0pUTnrKrxu2wKv3Bgox9Bynp2klD1YXoRofKZEU5oQ=,tag:eB3vSmgQq/6ve5OuAtQ+gw==,type:str] + - ENC[AES256_GCM,data:N+2y,iv:dBKXhLzQ1pPoyeaHm0hcAR7ZjH1WDyAvsFQQpwdQmp8=,tag:ixrLClPtAEC8rBTNS9gF7g==,type:str] + - ENC[AES256_GCM,data:0fmqAtI=,iv:ThWhJQH6xHD+gmVRKz9+T+TLNKApq2i9RE/TPRwMklQ=,tag:y/kuDxTjcw85LC1dDLRCaQ==,type:str] + - ENC[AES256_GCM,data:TiT467c1FXZBKrjI,iv:oAcR0AACnRGF2tec7y10/WKS8MARp78e+F9RbGQ1tHI=,tag:EutW7SkrrPuKmQ19r3H0kQ==,type:str] + - ENC[AES256_GCM,data:76usUA==,iv:QJx0sABJ3XuGsCtpx0piZ/B1isL2enYuxdG7t4ngiNw=,tag:E871b/a9i+oT/dVa8is+FQ==,type:str] + - ENC[AES256_GCM,data:JBIXYDu0AhrQhblDJ5Y4JYBqAtQLewScqh3PAA==,iv:T500wGJtmPzgoYKADzlibEQhk+dFE551HwX6uY92/JI=,tag:kMSjMQXFos1ZTPNhz5unBw==,type:comment] + - ENC[AES256_GCM,data:DocXwyW5,iv:p9HdwGhOXv7VtNuI1Q6GV8Ln5mbv6GJu2hT6KlAoE08=,tag:NrOaRhozTgCER0vf1UqONw==,type:str] + - ENC[AES256_GCM,data:4oC7rumQmhv2Xq+xRyKFrQ==,iv:piTs4LU9ikv6xt5ODXg6JQJguVYY4HN1+WxvRCL7ZF4=,tag:tDQTxqj4asz24LsE9yRgWQ==,type:str] + - ENC[AES256_GCM,data:+tkbVQ==,iv:DR3atR5MbosQ8HsvxB5HOKg+NsFm5VsmUGgVE0B1JgI=,tag:DQnLFxTMgCDV+WjNB4oHAw==,type:str] + - ENC[AES256_GCM,data:tbFk9w==,iv:CrBhf91ppSFvIauxcQQdn3mu/p/1gAGGYskRDwOU4hg=,tag:mEPOyviMfpRbQf/ysYzasw==,type:str] + - ENC[AES256_GCM,data:mI1j0w==,iv:wFgXzvHxb2iBHhAGTNtg9KIc+eGjtVe8dQ2tOZq02Ck=,tag:IV60Bpi1XSEHDhuONTZOMQ==,type:str] + - ENC[AES256_GCM,data:5gCnWrvcbw==,iv:ckX6mVI1jRwzhdA4cwIDid6IcMyg9Do8TDnEkjXZogI=,tag:3/tz1isg/DSAS4FK5XiP6A==,type:str] + - ENC[AES256_GCM,data:OWyhPCU=,iv:jymPLtuOOb3ljX4BzLHUAqHp/B5XOAW6WK89XOh4mQ8=,tag:np3VDxpONXlmuWT0mWBXEw==,type:str] + - ENC[AES256_GCM,data:qjbWphfn25Q/,iv:ZcBbsTCf/CRNRnpb+0Ig9qtnHVR597bOnM7kvSgqYV0=,tag:ID7WCwQEg35WYp0OiG5S1Q==,type:str] + - ENC[AES256_GCM,data:DvrJWBFgwRRfg5JewSQWCHtaa5JY,iv:n4/pww4CydmXyYKm+X9B0vTQOXLPkIeSnb3eKbbGNvs=,tag:11l7Gazt07XDgiDqSlX5rg==,type:comment] + - ENC[AES256_GCM,data:BSQnYyCL,iv:9vQNZp/VaVxy9Iyosn7v/dINoFSag70FmlzAXZsV3mg=,tag:oTYSUNajVbYUypA3a8kOyA==,type:str] + - ENC[AES256_GCM,data:8iFODjfZ4Md2iZ/zrHAmLanf4TseUXQ2yiH6UTE=,iv:ZtHX0CtYZ1ZcBFq1jmS45nFHwG5+o9iTely2AjVvjlM=,tag:wlAaeay21MCGGq0UzMq/vw==,type:str] + - ENC[AES256_GCM,data:bHaVu9XY,iv:OEcc9Ry7IuFDuHzJnAWBSuXvIavjnEyUYLdXV5IZBvc=,tag:mkKUyKgJ3ru/1TdNcp5l9A==,type:str] +homebrew_cask_apps: + - ENC[AES256_GCM,data:AZha+kHBbNtiG1auAb+x+G4k3g==,iv:zX1dr826pGzA9QJe/aUkdN27EASGAZqvJd0KtjoPThY=,tag:k4zqOVsCEkJCZoLrddWqhQ==,type:comment] + - ENC[AES256_GCM,data:sqyvOeM=,iv:HuSg8Aot3lLDMNsnNZLp6dEZzVExWPPnWHrL+Ev8MaI=,tag:JI+Hnuu01YkexaVqg9xnhw==,type:str] + - ENC[AES256_GCM,data:uDVHK3V0Kqgb,iv:dnYiZ4URb+gnl2ccWXIoU6pP1Lz037C1TiPVQBSXtCI=,tag:9x0VL65CpsipE6HhJtPCkw==,type:str] + - ENC[AES256_GCM,data:3wQiNJ1r3uev5op+et0=,iv:scB/9d0W2101oYjyqpRz8YUhuTgRXT8LBk4MkLSoI68=,tag:j2Xn6WHIK9H4rqeknoG7Xw==,type:str] + - ENC[AES256_GCM,data:YpcdSu5W,iv:mHdRVXJYl175RFhRI1+r7DFszDW4E1dRnJP6oEp0xBk=,tag:VkcL+uFlvA9BDTrfsQ1s5Q==,type:str] + - ENC[AES256_GCM,data:L2ymIZEihCG/c1FJVYMWXvae,iv:HSKXrPx3bfVCkwoGt7tCfGEoG2Z3mLeM3QBQwhp+dfQ=,tag:+SaR9lKf0fVf/YkTKUf8Hg==,type:str] + - ENC[AES256_GCM,data:E15x3Sdzfdy+swSDXHkUOA4xYj5dEYqiDgGB+TJ7,iv:cTH7hwlfVCIindgwuZP5Uf8n0/GHF/q2AooAROkzLmc=,tag:sx5mAwtur4HvdaMz42/tpw==,type:comment] + - ENC[AES256_GCM,data:OfV/wA==,iv:WTa9Skc3STmcbTyPuHV1b1vKYr/bCFXfDtvt4BP1jwo=,tag:KZdr/4QdWduQxrwYw1sCzQ==,type:str] + - ENC[AES256_GCM,data:LWlezZTm8mZD2hiUNRbg4SOhrKiolLnohw==,iv:J1HoQ+CFCW4PqxDnT5ARy3o8FCwRrT47VEHkbnWSiW0=,tag:2fBq3O/sTTpPimxnFJ05RQ==,type:comment] + - ENC[AES256_GCM,data:2NokIkJ2,iv:H+BaH8UFwtv8SCFxIxQ7onEQ4VSy0oaXWhjcVHkRQ1U=,tag:tCRmFw7BvV7HiUGnbba/oA==,type:str] + - ENC[AES256_GCM,data:68r6g1RgUTRtOQNyKw==,iv:PCmIWYTFHqm+ou/vA2sZwkaDSEeaWM0U8jnBB35C7qI=,tag:3R17WDpv9BbaIfZXp8C3Ig==,type:str] + - ENC[AES256_GCM,data:/4HjPD4aKRvF,iv:ebaE29J3do9T11VdTPF/dLrdZ0sDjXBerGnwuSdfNS0=,tag:c3WvqGkXBW8Ij0n7DtZPKA==,type:str] + - ENC[AES256_GCM,data:uWFqoI+UxrOXo6ACTM4j5N0=,iv:KshLl6XXtRBrGZC+pPNh64oNQQRmUZyF8LzAn95xqpU=,tag:78TW/n4FqBVbXDVhY1+LgQ==,type:str] + - ENC[AES256_GCM,data:5r4H5GwgdGkU,iv:grpkrKesUF3tKIJRmq/clRBNlkeRhcoz0znNQkWcnQc=,tag:Fn3btnjdmDQIDFuTFvBCiQ==,type:str] + - ENC[AES256_GCM,data:UHgIyl0eNQ==,iv:XODeesFlp/thtBLvewy2LAi56O6SVdd2L94DNP5OL7A=,tag:cZsJ6oVV008fAJiZCoGybQ==,type:str] + - ENC[AES256_GCM,data:q/UwwhAm3OG9ypqY,iv:Aup2ZTXKpQYDW3WgGy7VaryF77zap53lUO7667xQIy4=,tag:3gDs8L2H1k75PtflVkxU+A==,type:str] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:6CxIFUV5jXrAhTTrSB4pcYAisekbPafbOHk6Z9kS6dQlyoJCNDjZ2lmNmw==,iv:ePPNgXQ6R4ggkBwf+uYcSxFmBuveEBXFK/O6u9qYHAQ=,tag:PHwWgFpYiGq3Ue4I/Fy91A==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:kM9TdmJYXrVYTaYkgQ==,iv:W37//MAoHtvr+XMK0eXLHJ/AsKQtVgi7BlBMZEGrRdI=,tag:h0To+/22Q7ukfEbNU2HVGw==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +python_pyenv_versions: + - ENC[AES256_GCM,data:VuetLOjc,iv:O/x5fdn10TshtObRahmeb8RsogEAhnWpEYb3xNNCw/U=,tag:Bw7bWIoQMIOMaI7IcOHA2w==,type:str] + - ENC[AES256_GCM,data:qlJFjN4a,iv:CFVVLny1bJ0EuWtuMejs/lYFLKNEBcqFVcoatL8BYBM=,tag:ZekGR8S+10mmCzcveaX0Bw==,type:str] +python_pyenv_global: ENC[AES256_GCM,data:1UwPaxpV,iv:l64esjUP+ehAvRlb3UkF9Hdto6rZj8F4vQBPdxWtAHM=,tag:caP5cGINQaaEl1M3F8adug==,type:str] +python_uv_versions: [] +python_uv_tools: + - ENC[AES256_GCM,data:hF5KdimOeUbvWg==,iv:4GvmWyFn5MUohBnxzV7uLe/4z/qJLaOp0afJotAXbCQ=,tag:cpV8OyZ3mX8uyTeiwktptg==,type:str] + - ENC[AES256_GCM,data:iBB3g38=,iv:hF1pXo/in91FlSVRnD3v+Zmcrye5AOurCPNJdYMk/NE=,tag:/41cApbCh/s/kVW4qZVgtw==,type:str] + - ENC[AES256_GCM,data:9KSMje0=,iv:opLm8o7DJSgCdvGiRhYfsjo5lfYsJnWY4PlR3lhYKMY=,tag:bzLnS0pUqBBJsQCEFeuMUQ==,type:str] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:EFZsOtqJqsbb0yY=,iv:ozi/KJL0miEYeXIjIQUiOVWSU2IUwzgxcDNvc4Su0BE=,tag:RG1jwyFP8soVtvS9ImRavw==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +dockitems_persist: + - name: ENC[AES256_GCM,data:nbfq4P4=,iv:2xJuKKaS09Sz3lPFn7+QbfS37XXP8SKyFOjODe/SVFk=,tag:n6nXXlPLVfXw7cpfI/+yxA==,type:str] + path: ENC[AES256_GCM,data:PVATzALKnUTtlnqSnRqWO0kvikQkqpY=,iv:tgoXxGnTkXBp1w1H+EOCVlnTGDaG3Qa5Ba6ZmD0APVw=,tag:fQBT8MB/hciZhJGTLv1wNw==,type:str] + pos: ENC[AES256_GCM,data:qQ==,iv:De0U0ZGR5YIGj9lVGH3ESYYaKapi45LbgmdcRGi+dA0=,tag:XYPSnoMNkQwZ1QYvkh5hFw==,type:int] + - name: ENC[AES256_GCM,data:J9BK1bDjlAuYBX7QC7s+4Q==,iv:uqq9UZVocMA/qz2Z3lNcp2sC3tZAY+HcwhV/emhuLZE=,tag:nUKdUTTpSo4naKqn2s0e7w==,type:str] + path: ENC[AES256_GCM,data:NUYCV6ICoO2Bw7nur1Q6qEDdap84QqV0SPyjUmVNgniqdl7raefhWhaf5GphcxP8hx/u,iv:GA5Xpbdh2cUt3EgY27pmYgnh3XiLBeIw72hr//ysRGc=,tag:2UXBDtNflauLIeCVBKZ/Ng==,type:str] + pos: ENC[AES256_GCM,data:Wg==,iv:qxhcXiP4Pseca3NLqSlCoSmAxzv6xOGHtiPwiaThRek=,tag:3+A9Qb3uIwMQbmHsBQnR2w==,type:int] + - name: ENC[AES256_GCM,data:abWND4Wt1ejw,iv:Bmo5B0yVNq+4O8CAV2RueYFi5XvhmtygaUKX8/Lp3Vo=,tag:8lIzEGBFsdSiYuoBH47zTA==,type:str] + path: ENC[AES256_GCM,data:XKZRd0lfeH/QnnyvwukaR2hI5U1XpP8Y5jiq,iv:7mH6p85FiWeKc6hKse/R96LNf3blg9hAsjmPLku0gvo=,tag:9bQWuYx9vbdVhPjhSBEfeA==,type:str] + pos: ENC[AES256_GCM,data:Ww==,iv:pYEO+4o37UVTsdOtY2ontfTx9N8yV1JacX3+8/bAAjg=,tag:sou8ZzFb2tYNWGijrL0nGQ==,type:int] + - name: ENC[AES256_GCM,data:xtXRCxOkyfQ=,iv:3uZOFZohEDBDhIC6jL+aBDYnOkTtWv9baI3O/30Ey64=,tag:1SOCnCNeTERvpncwr+ZnCw==,type:str] + path: ENC[AES256_GCM,data:Xenq6x05ZzDh1pBuw0EZtGlUyxDxNsrwfYGOXCVNO9KP,iv:rcn0s0TH5dZ8s1O73R9afm4+fyzxxS2wQNBPC9WhSIQ=,tag:NGXsh5+07qQhseSf0X/E7Q==,type:str] + pos: ENC[AES256_GCM,data:pQ==,iv:BWXGkoWWrG+VpyM7Qjp0Xd7wB9hBYtyfqjJWo1CJROY=,tag:cEifmgeho9l/Sz6nAAVyZQ==,type:int] + - name: ENC[AES256_GCM,data:Cs8IQwi9vrs=,iv:awTHPjoDJwoBgcVvi/2uUErR6d54wEKHdL/KG303AQ8=,tag:8qmZNrXqc2sdGMt7v+OCOQ==,type:str] + path: ENC[AES256_GCM,data:R5YIvDJzHfz2eP/cfdxmCJnMNkER6MtcbCc=,iv:kqtMLfzNP0t9qjgFCDK7ykRSgbFio88498N7uWz8wNg=,tag:HVxOZbgc7uovvQ5NUA52XQ==,type:str] + pos: ENC[AES256_GCM,data:fg==,iv:vooVft/Thx9JJgPbiiqNnjlUHN4do0QGJ8ng8H1lbv8=,tag:AsJIPCtJQ/TVp/Qo9c6jFw==,type:int] + - name: ENC[AES256_GCM,data:32mabGR5XA==,iv:+ov7Cm5CCczbHTrC2Ob81x043vwIQOlgtUgWAeqaMaw=,tag:JBOLvBAbVJ4NZXYyUmz/WQ==,type:str] + path: ENC[AES256_GCM,data:Ka521gEBphv9Y83eC1M6rJDCrmyA8Eh0pQ==,iv:tiIySk69a/L3vImCnGuCh8wQ+18WsLnsqhiLasoJ8Z8=,tag:dBoyiuWpt00NbLCSGehfnA==,type:str] + pos: ENC[AES256_GCM,data:bw==,iv:er1Xqs8lEqQefJva4CHgegM/5c/UP8lOgUE2JaWyY64=,tag:nTDfX2TOdayRIxLqWl2TQg==,type:int] + - name: ENC[AES256_GCM,data:pqt+YrLf,iv:u8j0RxFvyZKP85MKOqYGD2AGUueTzdD9soWAy7ZDtlc=,tag:IKC0vL46o9CwoiGlGZIrvQ==,type:str] + path: ENC[AES256_GCM,data:QOVOyRxajWv4G93N2UvXWgnpfwPSTKVnEt4Q4mBONxMiKwZw,iv:Boeg1vZSfLSVcdE9fXs3t1Qwr93B07idn+9EBJadIiI=,tag:Kni8rPBRa/atN/Xs0annyw==,type:str] + pos: ENC[AES256_GCM,data:Kw==,iv:U5e2w4qQc82KFGNKMRaK6lMlzWaBrwVUoP7EP4wivVc=,tag:Xw/7p9RE9BlrGW4GhP+wiA==,type:int] + - name: ENC[AES256_GCM,data:URpkL6E0,iv:2lagQSgqYEOogynqBrySIS+HVrEQYGYITdGhv7hCGbE=,tag:8HZU6DqLWZRLNwlZw2+qlQ==,type:str] + path: ENC[AES256_GCM,data:7trE1ph43XTQiRj39R073ALuxN96heDP,iv:HSyFTJ+Py7mnyW4iDPlJFjitQFxcwR54DVjgttzm8G4=,tag:MrkxXNyzlhPdpPuoUBvifw==,type:str] + pos: ENC[AES256_GCM,data:+w==,iv:MwUtvmy5lEg0Kl/r/1DF6P4hyVNLE159UndNH+NpdYo=,tag:NccBwufZ5s+RVrgh/83wfw==,type:int] + - name: ENC[AES256_GCM,data:ooB2FQc=,iv:kEZcZwAGCVEKGQXOjBCdr0mxXSVadWZWoSeOwfKtRpE=,tag:kx96e2ENNiML6BtkvLwhcQ==,type:str] + path: ENC[AES256_GCM,data:xa+eY9XAEUFMNqeku/I0+v61ztv+qj8=,iv:qNwFyHX73qSrmT8LNhLyjVBiyDp0NvJX0ZSn2ZX3aaE=,tag:pg1yJD1JXGlMSrVn010Dmg==,type:str] + pos: ENC[AES256_GCM,data:dQ==,iv:ZZVuL3uxDJZFwQVMc57qX5QWIkCyMFZyQjIFWIcQ8YE=,tag:xkngJbKcS8fL6HXsFoHQYw==,type:int] + - name: ENC[AES256_GCM,data:WLR0AolBm0G1S58XvCfo,iv:kCMCemEDwnrwQquO38NZ+3TxUXCkIQslcseYGxs6Jjw=,tag:5vFu35F+AbUUoIgL5Wo5xg==,type:str] + path: ENC[AES256_GCM,data:LMix3VHAUn2P5DaevedTqUT/GwyCnMtK+MxfO7EMxuJPAWNv1FMTSQ==,iv:3s1HnLV9pCx6ckXP1BBmcgfAR4dl1TpTSMuVD08yp7A=,tag:lq9beZXLAiX8bcgsBbXGJg==,type:str] + pos: ENC[AES256_GCM,data:Gqw=,iv:jaEd17VuVOMc+Wl92RH0jtMXGprHbRtnJnia3cqAIa8=,tag:WpX1brwmTayr3K32gnRd6g==,type:int] + - name: ENC[AES256_GCM,data:5GKdVvbQ5IjE9YdX,iv:HE/RiKZmjVykSYnREWAKuZu9N6aC6gibw0gaViUWCs4=,tag:hjpy4HBEbVddbXD9s40N8A==,type:str] + path: ENC[AES256_GCM,data:Fdsupl5cl5j6z2ZBxg==,iv:x2pwosC2bdmOUbxVIlGG1BhD+B1ZzvHstkcqap+CN+U=,tag:ap3SGDBiC/2cbo9eKzSswg==,type:str] + pos: ENC[AES256_GCM,data:yfQ=,iv:shF9L1YSxPxaDJmEL69R1rTxOHRQI2fGAdRzMf9oWw4=,tag:Cph1ueCdD+ctzxCobb+N1w==,type:int] + - name: ENC[AES256_GCM,data:OPIi2o6JlWHv,iv:exj4g+ghsKKB1X/jrWLiOGZUgmSfuH9q2qRdx+D3mIo=,tag:PofNePW6I7oou9TkugmqtA==,type:str] + path: ENC[AES256_GCM,data:vYF0xyrSAHLk3m6och5NJ5l/itRPkNixJmq21r8L5NxRhgHAC52d,iv:0UCofu7HuKUJh3+hewIhXBFCktsRrFnMrzZdXMohJXc=,tag:rhOkRGgdfzDVYhMETLEaGw==,type:str] + pos: ENC[AES256_GCM,data:2TI=,iv:ae2boP4eGDOW/oPunk46EnWsIzcESz89f92YvMAfWSo=,tag:GvQiLPgaqKoRq9avY+l3Mg==,type:int] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:yf19lLfcsl8PsqeM,iv:Qk3zrjudaolQ1d3N/qGgbE2HzlnhiufPsUSdP43C/qU=,tag:uIOQx+QSHm2fKgBdPKQbbQ==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +macos_config_files: null +#ENC[AES256_GCM,data:X2/xnwQAmhYaNx9cBRct08nPt6EmyAxMaAam,iv:5Q7ZBx/iiurqhF2ZechQp/c8zwRf8isHMzDN4+OMdjk=,tag:5xwpeeIz5fj2MuLnt1nNOA==,type:comment] +#ENC[AES256_GCM,data:FMNWtgEiz/TsaTJpKQ==,iv:X9Maz/VcyCaIrQrfknvSCwREoJuOCMciOgbzh/Blrtk=,tag:+KQWhht8VoouFnm2Z85UDA==,type:comment] +#ENC[AES256_GCM,data:WA940Wvd4M2utUOPiGgP,iv:dXKiMajqXHcdQA8/Vd5E7Yrn/4nv5hDrC3vLYu2WK+I=,tag:23Hq/wHFRC2KOVMBNJmeCg==,type:comment] +#ENC[AES256_GCM,data:3CUEN3eVw08JNgQG5DbISccoMiBLu61lwG3FWlhpux0KWV3hHADz1KvYoEU/N3U5k+MJfWA=,iv:JKfFg+nyX0B2RbtOhhKnjPc4LJtq+F4eEOd73ocRyc0=,tag:g8wu7pnWVuaXqxkJlSVHIg==,type:comment] +#ENC[AES256_GCM,data:lxWQrp9yvcvhHghuB68tUV42UBJN30bFtCzUJzbmFxM1Pg==,iv:hqOqsLTfDHA2W4ZPD8/I21id2Wgzz7iiyBToMZ5DEFo=,tag:9O9BNcLsX0RccHnUy7diKA==,type:comment] +macos_ini_properties: null +#ENC[AES256_GCM,data:lW8dyZPpFwFbiw==,iv:iqHq7LAhFI3nZxlDzWhRhoKxFOcJqc2eWkxlY2qQmt0=,tag:nVa9fejTQPNSvcXBhCqL+A==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:a9qkOA1liy0ruXJMoeAHRAwCOvR74cxfsRU+ed0=,iv:p6+PIsXXRuG1YM+/+MfIC0GpRECqlpHWI6+3tEMqydY=,tag:7RscUpVHE8BLZge6RnjjAw==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:8onqRCALoRn0ZYIsL3SpjYjkCFrxBgoujO4CssqWlas22d8=,iv:apUO0jvTPeB4Em0kGCBPKm4RpGbI2z5DnLiZpY57CNY=,tag:jX/ORc7kkQLNyh6YqoPOMQ==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:aLYFEZXFTGErrnkUv2iOmUWd+Qp9vj3ZJCR/JPIjmm5K,iv:d9zSfirvZeUOkKbYlTW9ngizF4+xIqnLB0wnu5oGAdA=,tag:+NKRJQUd+CRJgi8phnlCtw==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:09SN/shLZiUiqqmOnp0H52hdYfqd0rPQ6A==,iv:6fkWmpM39hgRPJTJpzf+eLAAixDilXv2hw/0NNlqRZc=,tag:0bu6id40LW0XS6XpyT299g==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:+U3ApbFKuKgutEDjv2frI+lkry3Tm5zj,iv:FT0dVmV/cnPLHrqgvfmch55cgS7aedsOj23j8dbWUIQ=,tag:xYdoOyihFGHOPn8wuZ8QlQ==,type:comment] +#ENC[AES256_GCM,data:13gVkovEOHHo+wAH,iv:2dfniPjKluEy/Hpnsb5+w5Xuut+2C9sPxhoHDagI5CY=,tag:fYSLgkWt9S5C5dBivYv9/g==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:dcLngfIIUeVgVfrcW+n1cjAt6MoSJZXrq08216g=,iv:MbI6ZDbvz1uEm3K24wadImJOz/XleQDNBQMnMj3KhMA=,tag:RDnGFF3lOfVy26fYgv6Uug==,type:comment] +#ENC[AES256_GCM,data:+HiBpIGlp55oMw1iaA==,iv:wDdMAQxNkjoNaLyfyYK+w9+7PBfBVpJZUroMLm2LRlc=,tag:yFECOml8VURA8+xKiJO+oA==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:leNvyQNuuka3kC9/IAaHFLu0Y0jrkwzAjDB9,iv:yPuqtGKYPjhDgR8cjMo9NlwdvSB/1uxd9XDu9WZ6O+s=,tag:t0BvYsSfrcggd+15jYV09g==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:Wmw+0pukKRGII6S474HqWITGh91TtcvV,iv:oy1inwNuHXdaPpEnwbxsfHnvGFfomZ/ZuD8SAQLmopI=,tag:vtdhhA3TRrEDFDH4NcjU/g==,type:comment] +#ENC[AES256_GCM,data:yazxs9L9VhbgT5s=,iv:jT2sa0UY58TT9P5Lybs0q2PJeHR+82iCbrmnRZrtEo8=,tag:NaTAYvvKxLW87Na4+E3Rhw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:TL70xdi8k9A55OmiiCJ3lQ//8XjmjVY1Fv3AKA==,iv:8QPkuXoLytEdV42Y0fsAEfiXcomFPQmfA1lfZMKgwnc=,tag:+LIvRNssvZTYZlNaiN3L9g==,type:comment] +#ENC[AES256_GCM,data:AZaD/2uXe+291xZp,iv:i6GWRp75QvM6w6/jzErfVgz6qPVMQyrEkRkTJvO2XQI=,tag:TKIoGFY/HxmAh0aXHV0I/g==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:i+TEV4lWZ5pXcQPUudKaGtvYd1KyqHLuzR7qz6l7Z0lLZw==,iv:AewCEKKU5orNap+d4agb0a40yh0V6g+XbVNvE0AZwok=,tag:9G1XX1WhM2G5vDBycFKuSQ==,type:comment] +#ENC[AES256_GCM,data:JvCuClp6EMl9GvJZHC8K0ExvBA==,iv:4WMTvrlPe4TAW+Iokt4lkSmPoeo4IW5tWfolN3IYWOE=,tag:JY/6ilhF8XgeABhkfF5fNg==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:x/7VoBJTA7aG4+0FX6A8knkvJA==,iv:TCtjFBIH9d2gFeaHjDuVULqTDYoEkjiwIxG1mwzHXuc=,tag:oBBuFNbtKBtv76t9JTkudw==,type:comment] +#ENC[AES256_GCM,data:rPthcbGvN8lbbyIb5i/iHzNXP6ulRpi4z8VQByiIZ3ju/A==,iv:ChvfHjPebWbU45jl4sRfSO99hAvMNyFZn02vwVvgZhY=,tag:aWbV2CpXMgTdUXrFA3oBQg==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:rA7oWu6a2XSIbIfjA2Bh,iv:DicRlwwAD4aDoBFtQNp3YmcoIvCXhvIY/7GZ4cqJBA4=,tag:+eim30ZKqhixS70XeOtCpw==,type:comment] +#ENC[AES256_GCM,data:dUw1fLciqQTIfvw/P19VPp9iidNwKy0btJItHyg=,iv:2h6Rp7YCjkUovLF5IrQZW655A7W5AaLMmCCCBfVOEv4=,tag:mvdH36+NcBepxwDxbbBZ9g==,type:comment] +#ENC[AES256_GCM,data:lpe3udaAzAvWChs+JfG26SBtKbo=,iv:OedZ7QOrPwBaUm8z0uIfcnpS4vU+McNEvWkY8A+8LYc=,tag:h1slCSTKZKTGDqEGkGlY3A==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:N4/eKMv1hZeJB0UY3RoSBKLR86mppYY=,iv:uFxn2DkqS2OmUClVMbPBQ88o29M9yw4eLxo/VYIcMeE=,tag:HxEUeRt3GaQfKvGI+FLCNg==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:1dwqSSyvm7bzIvoEQMljmWdw52pnKXI=,iv:OrcS1l/Hgawf1ae0UDxdv2ksu/qDUNuSygoFTEW24n8=,tag:CJROGc3fh1Y1WnEw1gv76w==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:aG37uz8uw6e98gNWznsZ4MkPP4al/842,iv:cLTt/73o+mReeVjaR/BoWQMTjShuEdB+ybsaPKu+6as=,tag:9Yeefj6LQaR/SbyAMfN6Xg==,type:comment] +#ENC[AES256_GCM,data:R7+e7G8F1Ae1WcVluewg5AE=,iv:UiYv66L0Fakff8spnnMi1ACxuFtV83+LJ/4FGORO5yM=,tag:YS7ExyrsfFDEyJg9Qq2p+Q==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:ZcGteihbzf8VZxcARV4MNGI=,iv:Js2revitYUDYVVK57KdvQ1+xHnfv5962MnkH9XFbb+c=,tag:rmZ706AX2DJAqdPb+Rn8Rw==,type:comment] +#ENC[AES256_GCM,data:HnIidqqjYGQi6Xzk,iv:kShXXLRdfOnTdJWVAOKBOodn78lUKWTR/i7g8PSkHds=,tag:xAeUqMLyeXFSBDTfyUfk1w==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:JHVqQ7MbN0iv3q+xSnsTVqNxL/U=,iv:mK62jgIHgA6GTNjvkGhIoIVYLhsY5h+PJ2PuBKqetVE=,tag:JgujBeg2HJSMNP+iqGrGgg==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:W4yfngaX+2mP0rJvii01vRbjFj8=,iv:Oir+tpki9uJJ/1GWR6WMGPswEtvVCCCdYfu3jslpEIU=,tag:ft6F2zcskd7tteI11AoqPw==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:YVUPXxpfBzYH1gXLGFyj,iv:I0uytqoa4zfNyzJXgvIWXaDhvhHQYZogpkx5u7JAcKs=,tag:yn5nFaIwXHMFI2ykz9tt3g==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:2jJBu/1kikxmfs3TfXbc,iv:BfbcKkAgx+M/6ogYvLyBlcZt0GLoq0mANGlRqrZ4z5I=,tag:dRel3z2CrSeTMTKLJztgqg==,type:comment] +#ENC[AES256_GCM,data:hN95D9LLHeqRaOU=,iv:fUTb5lUSpxart1TcD+hdtQ9hCQrujA/yAuTar/M4Hi8=,tag:V+6k2avITN8n54FEel+0hA==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:BYPi446F1w+8tT0VfoED5ETTbJLVhxj5iPDqUUI=,iv:0Qv//7id+5wNz2VR4dsu8hzgf6657O4Jz1m75JXVONI=,tag:Y1TE6qCo7Pqr+/JGhwTZQA==,type:comment] +#ENC[AES256_GCM,data:GI5yCDZP6gruND5vzNkhOgdOkdk=,iv:QIvTmJoL+Bs3RdhRU25kPZ1Fd7Lq/+XmT4oVdZPOu8s=,tag:G3iMd7uJjplXWM4juGLzYQ==,type:comment] +#ENC[AES256_GCM,data:yazxs9L9VhbgT5s=,iv:jT2sa0UY58TT9P5Lybs0q2PJeHR+82iCbrmnRZrtEo8=,tag:NaTAYvvKxLW87Na4+E3Rhw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:kkpk2LekXwwgQ5OPQ/QGSGoC2v4=,iv:DRXEgYsECY9WO9Gm23JVt/+3Khbmt6cyQQNQ+R5AUns=,tag:S0rtvYg8pJX2qzDcwvdgwg==,type:comment] +#ENC[AES256_GCM,data:r4IdyK0+fKq2QM+R3YizCHcIBB0zw+tKl+2697U7GkM=,iv:UJBCmP/1KIRrzKm4PMydn3jqjR8GZgNPQkJB7v1SY9U=,tag:3ENB7OW1oDfDJqhCtJbU0A==,type:comment] +#ENC[AES256_GCM,data:wnlcEgynRIDZIpu0,iv:wc3UaDU0P+Qw6LimuCmGoCxlkeRR8MElYdpFDelO3hE=,tag:oc9gaNQQ+A1Yp0qY1uVpIA==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:kkpk2LekXwwgQ5OPQ/QGSGoC2v4=,iv:DRXEgYsECY9WO9Gm23JVt/+3Khbmt6cyQQNQ+R5AUns=,tag:S0rtvYg8pJX2qzDcwvdgwg==,type:comment] +#ENC[AES256_GCM,data:Tca0OZlH1YUw6Bq8JmHU9AcjD5c1OM/p1wO9L63YdU9jcw==,iv:odkBE+WZ63tH5c8i2tGCkVvxf4aVzLKg56cxsLeCMqQ=,tag:450tNJ38RIUkvCk7a898YA==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:kkpk2LekXwwgQ5OPQ/QGSGoC2v4=,iv:DRXEgYsECY9WO9Gm23JVt/+3Khbmt6cyQQNQ+R5AUns=,tag:S0rtvYg8pJX2qzDcwvdgwg==,type:comment] +#ENC[AES256_GCM,data:sUVtMbAGavBBzl03DV4iOfFrrXKQ3nNlJ4QehHECyuz0BZE=,iv:FOneKLeVuZirgReFrhNFIouC+ClZ2W+RRiRHgxJxTCM=,tag:05t9KjMJHz78zji9cP8+qg==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:kkpk2LekXwwgQ5OPQ/QGSGoC2v4=,iv:DRXEgYsECY9WO9Gm23JVt/+3Khbmt6cyQQNQ+R5AUns=,tag:S0rtvYg8pJX2qzDcwvdgwg==,type:comment] +#ENC[AES256_GCM,data:3jD3ImksDs3Qg6Z2hAD4YKoSAgDAOnwn3xQzM+hbvA==,iv:A4FDI75pnmd5aDr/PBkKF4IwtI50JeTCT9nvZoEKszo=,tag:5Ayx55xqkKBTsFehEoZoYw==,type:comment] +#ENC[AES256_GCM,data:NGORyLWDgvM4zJE+PzbVGw==,iv:V8+NzsKhV9TY6nNHu3VDi+2fNTmQp8EcAo1wj4lbx7Y=,tag:R0BbuoVIOdIkppHdqxHIkw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:kkpk2LekXwwgQ5OPQ/QGSGoC2v4=,iv:DRXEgYsECY9WO9Gm23JVt/+3Khbmt6cyQQNQ+R5AUns=,tag:S0rtvYg8pJX2qzDcwvdgwg==,type:comment] +#ENC[AES256_GCM,data:sqFNdnn2kI9JGwaGRBbywiwFEcQ39bNuO4E=,iv:zg2/94aO+T6xQFSYQmFeYGYYcYzqV62F2zPTHVmpIw8=,tag:LSBcwQfeNwCaFJ40YUhoNA==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:JC4dhwwJ8hNdTK9BLA7+V/yXvzfrBjefkM+/Crkefd8zvnJhz8Zhc5d96UFtq8iWAKTAtdHlNSYSed6kPnOD2R08,iv:0hnvaTj3ENOQ8tAj8+HQQaK2bjlxXpAeZgwgCpmnHss=,tag:FBUulYkwogwf6r+JnANbLg==,type:comment] +#ENC[AES256_GCM,data:kkpk2LekXwwgQ5OPQ/QGSGoC2v4=,iv:DRXEgYsECY9WO9Gm23JVt/+3Khbmt6cyQQNQ+R5AUns=,tag:S0rtvYg8pJX2qzDcwvdgwg==,type:comment] +#ENC[AES256_GCM,data:MO3sywEZqw3kfh9DUnVUnXY3L9ORdASu4u6I5VtnEHO2,iv:956JbWak7aPWFhmbXxtmk3L58qZ+/XQtidCioDeLFkU=,tag:0njmQs0Ok88elLlifhnZsA==,type:comment] +#ENC[AES256_GCM,data:zSbxXDHhro7mwEDkIN9LvxA=,iv:gR/etLQSb7Us6XEAFB/DzH+/f871NMmh3yBYPL9Ipus=,tag:KnyOKYhPREEkP3mLJ+d5iw==,type:comment] +#ENC[AES256_GCM,data:FZOJGlLDj31t/OPGoQ==,iv:R2niYaov0Q72PIfBarOZRb8EFFAqHkpXcgZY+YT3oYs=,tag:y7NEn7ODdJ9jXgeTm5q1GQ==,type:comment] +#ENC[AES256_GCM,data:wHNRsZHbwWXH2bFgeBSnz7j+5cqdIjy+JR/FXLFd,iv:IdFgmrv5C4saE3uIWQqzS3nOHlU/rz5NJAWwdrBcpAM=,tag:vb/uXHUg0iolvWzec9bh7A==,type:comment] +#ENC[AES256_GCM,data:I6AtsPyfwjMKe2oHLBSjFXzOW9eaCsD0HHqE21U+Iw==,iv:XwOCbvxzli6V+NVUNJlVRx6lgyAK050EXHJbFmh5Hs0=,tag:/Fa57Q9kICPKz3o2EW0x9Q==,type:comment] +#ENC[AES256_GCM,data:bJET8M1PJeJ5noDZ4QGdIAMP+NjwcDsM+QW2U90ryg==,iv:Y12xY4pnafIofuv0/xZTwiLLeKcffTLmE1m0O6Z7QO8=,tag:++KlYFUVSh5um5Zktz6NBA==,type:comment] +#ENC[AES256_GCM,data:GotI12Fyq2ZV+dNJLRfVW2USMp/eGYal564WsSIpLA==,iv:doLwNeg5cQ/UHLJJnYp1MMzgCi4+oJ5R2GL3wC1DdJk=,tag:fECy8DwR4jHNOvCWVOG5qg==,type:comment] +#ENC[AES256_GCM,data:AcdTijLD7MN17bAOCDi6Al3Xw+H4n1BoVThygzRKvKWVKSnFKUD62xkQkZNUSfJFrQ/OTQI4,iv:UU3LxSwCRQejod3ztXm8UMDTraINMZLiqNM4lJrnBWc=,tag:txnZl3iV1A7GFe0OVHna8A==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +#ENC[AES256_GCM,data:8oIZSQElQrAhuQ==,iv:j4I6ZCQzTUa04nxkGYhBcLebqx9QXjehRyOh9tHKGFo=,tag:C/BtgnETp7v9jbt2jC+HtQ==,type:comment] +#ENC[AES256_GCM,data:hjcyMCansc4bGbqQxJM9z1kkKhnIOIOttlhXiHKEMYzVmNSs1vl+rMxsRzOTx08pyLf2,iv:6M/Itf6ZKjCZRsDDFLr64NaZBC0vXsKB7pA6YqXmVFI=,tag:5yHtB5E586XNtkhOe1sdpQ==,type:comment] +ide_vscode_extensions: + - ENC[AES256_GCM,data:Jj0hdSjasMDGu8Si7iXIvXYDG0DDIf1TnOYO7w==,iv:v/ArO+aENF0jAckVeiMwpA6lqTGlVG83PhFmADgAiWY=,tag:FUskdGeRfh1b1slRnJItvQ==,type:str] + - ENC[AES256_GCM,data:1stsb8X/wV1DkJIB1ik=,iv:npzfLxVHSYzatv2OPm0ndHwWH7jAgbAm9kywdXsqYV8=,tag:I+8lPgdE+DPIDV42Ptr9Iw==,type:str] + - ENC[AES256_GCM,data:JFSqDzl/yGWwOzTRsZpghT6wLA==,iv:yLF1y5dG8ibXweH6gcKnAWPTu5YTFkc3qmqW5WfjWJk=,tag:SgAzo+zTLSlFG3O/sZqVVg==,type:str] + - ENC[AES256_GCM,data:Y9dQfTZ3UAAtYZgbqNO/atN3XN3kNlLQ1RR8hQ==,iv:5c9adQro3KJ/cjOzhrxfSlTFk0MYHqK85tBHe1MDItE=,tag:fJTwWBnFxN3B7g9RbKHyyA==,type:str] + - ENC[AES256_GCM,data:kKU88he4pmAuycci6qZInw5Pm+R3f1IoqTOvcg2e1iGwP12EddGAbPM0/w==,iv:rBDLUtlYfvsyf4nmo+xwwxMYRF9x7NfYEjZ8Aj5DJ4E=,tag:XzR42GBhYoBiHX+nMwQfAw==,type:str] + - ENC[AES256_GCM,data:VBqoeN/FLC3KUjbaZbeXGEY=,iv:wQRutX6srS6otju1rYK5HIgpfNv1m2j7AqKoCq3v+Jg=,tag:yPwJegVJzQvlkhKE6cP6lA==,type:str] + - ENC[AES256_GCM,data:TbwKxe07x0Ha/WpjBiYKuw==,iv:1dcMVNMxciN+idM/pYoROJAf/bdRxq3PxjTm2cNJQ80=,tag:MBj8r6Z9YB37ZG/+GDnYRw==,type:str] + - ENC[AES256_GCM,data:b/sSnEHnWsrwK5TSj8XGCVaq,iv:pn5i99AHQMeUF4g4guI+0n37Jv6V07xJ8yuEEPekXoY=,tag:8oCVUQfwEmYU95j9YK0gtg==,type:str] + - ENC[AES256_GCM,data:XhpjblfMjV36Wjs1JEUQAfzBNriCtA==,iv:DwAq8daqDwvEGh8UkpX8QqKU35sfey8KuZBaaM/OeKA=,tag:h41U7ejs4LMfaAeXgBh6GA==,type:str] + - ENC[AES256_GCM,data:qQ9L3wjJ4yHXHdqe26ED1pkBEeb8rW5F+jUjO5WF,iv:Amj6o3jO6jUM7oZ6oMrypd1CvZJAoWsTSEfrSGMYqUY=,tag:Hiitv1de2KCzPB2/D0ofAQ==,type:str] +sops: + age: + - recipient: age1n2g0g2z9jdgnqx826e8d0d78y8z0lc7ngdadm3jw9gzpxj2nf5rs0hm6p6 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1bEhPeHhMUUNOcHdlZGlB + RFdiT0RyUGs0dGVVczZpU0NoRWszSG1kUkdJCmRZNWdPN0VPWDFJUXNMdktwWkJj + VkVxWisvcGN5emxGWFpCK1VkbXppZzgKLS0tIEtkZHpoV294Wm94ODJFdzJjRGZY + ckZ0ZFprZnhRMmJ2TXNCOVJRam1xNVUK+YjMpjIPt0FJXurXmfREgeF9N187wRJt + lHCEd6yyW8Lhbo+lbhybgvmJpy4zz16X2TfLAr9FGtPzJy66vnDv1A== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-01-26T19:30:13Z" + mac: ENC[AES256_GCM,data:yETMY2opUxfvx2y+F0NIQls8yJNE96B2Kk/itZGnWfEp3FSciuJ4j8jA/NRbY4KiCAB4HRDgNYrvKIbFLA0CaKuTT3tE4PQDd6izdI0uHKYA+KWjTvzw0jxMg/lE/tfYBrJF1mfAWgLoA/yJSJa5dh3GKRm+PfmM8lh1FCgjalI=,iv:HqlExk2mcdFix8uPnfp9qpz8RDVWTEbEfU7qHiDzWsA=,tag:rNHFkfy35TbOjqvmzOA6KQ==,type:str] + unencrypted_suffix: _unencrypted + version: 3.11.0 diff --git a/config.yml b/config.yml deleted file mode 100644 index f56213e..0000000 --- a/config.yml +++ /dev/null @@ -1,280 +0,0 @@ ---- -# ================================================== -# Role: dotfiles -# ================================================== -dotfiles_repo: git@github.com:afonsoc12/dotfiles.git -dotfiles_secrets_src: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 64636565636636346635326564383961303734613933653937643338306132333865343863396433 - 6266333533313464653730663030653763666261336532640a303837323266353564393033333834 - 61613038626236396363343061363730383833663361323964613130383861343938333831643737 - 3034656537333861610a323934616261383362383065633561336466333030623930366133336562 - 33623064633138626431383431306332643532343533313165633235323639386631 -dotfiles_repo_dest: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 66623836336230393438376164316537663531666135343563613566303535313139613034653032 - 3861306234393739373035623264303638316263346236370a646133316563333138373065633335 - 34616366316231626664656239613237353237636565653733656136326266306339373466323431 - 6131396136393731660a303539666538376134386136396335306366383538353635646237323165 - 31623166376165623938346136383965633262643637363565316466623832653265323737363137 - 3261333866363761376632666532303434633036386332336463 - -# ================================================== -# Role: geerlingguy.mac.homebrew -# - docs: https://github.com/geerlingguy/ansible-collection-mac/blob/master/roles/homebrew/README.md -# ================================================== -homebrew_upgrade_all_packages: true -homebrew_taps: - - derailed/k9s - - teamookla/speedtest -homebrew_installed_packages: - - act - - argocd - - bat - - cloudflared - - cmctl - - dockutil - - etcd - - exiftool - - eza - - ffmpeg - - fluxcd/tap/flux - - fzf - - gh - - ghorg - - git - - gnupg - - pinentry-mac - - helm - - htop - - influxdb-cli - - iperf3 - - jq - - k9s - - kopia - - kubectx - - kubeseal - - make - - nmap - - rclone - - restic - - rsync - - sops - - speedtest - - stern - - telnet - - hashicorp/tap/terraform - - tree - - velero - - wakeonlan - - watch - - yq -homebrew_cask_apps: - - arduino - - balenaetcher - - bruno - - cyberduck - - discord - - docker - - drawio - - google-chrome - - iterm2 - - keepassxc - - kopiaui - - logi-options-plus - - megasync - - nextcloud - - obsidian - - openboardview - - pycharm-ce - - raspberry-pi-imager - - rectangle - - sigil - - spotify - - tailscale - - tor-browser - - transmission - - visual-studio-code - - vlc - - whatsapp - - yubico-yubikey-manager - - zerotier-one - - zoom - -# ================================================== -# Role: mas -# ================================================== -mas_upgrade_all_apps: true -mas_installed_apps: - - {name: AmorphousDiskMark, id: 1168254295} - - {name: Disk Speed Test, id: 425264550} - - {name: GarageBand, id: 682658836} - - {name: iMovie, id: 408981434} - - {name: Keynote, id: 409203825} - - {name: Microsoft Excel, id: 462058435} - - {name: Microsoft PowerPoint, id: 462062816} - - {name: Microsoft Word, id: 462054704} - - {name: MQTT Explorer, id: 1455214828} - - {name: Numbers, id: 409203825} - - {name: org.snafu.GeoTag, id: 1465180184} - - {name: Pages, id: 409201541} - - {name: Panorama Stitcher Mini, id: 1062350226} - - {name: Spherical Viewer, id: 1489700765} - - {name: Surfshark, id: 1437809329} - - {name: Trello, id: 1278508951} - - {name: WireGuard, id: 1451685025} - -# Uninstall does not work: https://github.com/mas-cli/mas/issues/313 -mas_uninstalled_apps: [] - -# ================================================== -# Role: python -# ================================================== -python_pyenv_versions: - - 3.9.16 - - 3.10.13 - - 3.11.2 -python_pyenv_global: - - 3.11.2 -python_pip_packages: - - ansible - - black - - firefly-cli - - isort - - oci-cli - - pipenv - - pytest - - requests - - versioneer - -# ================================================== -# Role: java -# ================================================== -java_versions: [] -java_jenv_global: [] - -# ================================================== -# Role: dock -# ================================================== -dock_persistent_apps: - - {name: iTerm, path: /Applications/iTerm.app} - - {name: Activity Monitor, path: /System/Applications/Utilities/Activity Monitor.app} - # - {type: spacer} - - {name: Google Chrome, path: /Applications/Google Chrome.app} - - {name: KeePassXC, path: /Applications/KeePassXC.app} - - {name: Messages, path: /System/Applications/Messages.app} - - {name: FaceTime, path: /System/Applications/FaceTime.app} - - {name: WhatsApp, path: /Applications/WhatsApp.app} - - {name: Calendar, path: /System/Applications/Calendar.app} - - {name: Reminders, path: /System/Applications/Reminders.app} - - {name: Stickies, path: /System/Applications/Stickies.app} - - {name: Obsidian, path: /Applications/Obsidian.app} - - {name: Spotify, path: /Applications/Spotify.app} - - {name: Books, path: /System/Applications/Books.app} - - {name: Photos, path: /System/Applications/Photos.app} - - {name: VSCode, path: /Applications/Visual Studio Code.app} - - {name: PyCharm CE, path: /Applications/PyCharm CE.app} - - {name: Docker, path: /Applications/Docker.app} - - {name: Bruno, path: /Applications/Bruno.app} - - {name: Adobe Lightroom Classic, path: /Applications/Adobe Lightroom Classic/Adobe Lightroom Classic.app} - - {name: Adobe Bridge 2023, path: /Applications/Adobe Bridge 2023/Adobe Bridge 2023.app} - - {name: System Settings, path: /System/Applications/System Settings.app} - -dock_persistent_others: - - {name: Applications, path: /Applications} - - {name: Downloads, path: "/Users/{{ ansible_env.USER }}/Downloads"} - -# ================================================== -# Role: macos -# ================================================== -macos_config_files: - - {src: files/smb/nsmb.conf, dest: /etc, become: true} - - {src: files/rectangle/com.knollsoft.Rectangle.plist, dest: $HOME/Library/Preferences} - -macos_ini_properties: - # KeePassXC - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoReloadOnChange, value: "false"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoSaveAfterEveryChange, value: "false"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoSaveNonDataChanges, value: "false"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoSaveOnExit, value: "false"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoTypeDelay, value: 50} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoTypeStartDelay, value: 300} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: BackupBeforeSave, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: ConfigVersion, value: 2} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: GlobalAutoTypeKey, value: 80} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: GlobalAutoTypeModifiers, value: 201326592} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: UpdateCheckMessageShown, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: GUI, option: TrayIconAppearance, value: monochrome} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: AdvancedMode, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: ExcludeAlike, value: "false"} - # yamllint disable rule:line-length - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: ExcludedChars, value: !vault "$ANSIBLE_VAULT;1.1;AES256\r\n346439373132326533303166313535613439393736646538363764623033616138373032373563356261653136363131663439663062636233363731613534320a303366336236663031313437613438626165623033623630313561356331643934626230613331613436306533346434346365656239613931656330303232620a6563323632613837643734376631383263666163333032336532343333353439"} # noqa: yaml[line-length] - # yamllint enable rule:line-length - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: Length, value: 20} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: Logograms, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: LowerCase, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: Math, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: Type, value: 0} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: PasswordGenerator, option: WordCount, value: 2} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: Security, option: ClearClipboardTimeout, value: 60} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: Security, option: EnableCopyOnDoubleClick, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: Security, option: HidePasswordPreviewPanel, value: "false"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: Security, option: IconDownloadFallback, value: "true"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: Security, option: PasswordsHidden, value: "false"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: Security, option: PasswordsRepeatVisible, value: "false"} - -# macos_hosts: -# - {ip: 127.0.0.1, hosts: tst} -# - {ip: 127.0.0.1, hosts: tst2} -# - {ip: 127.0.0.1, hosts: tst3} -# - {ip: 127.0.0.1, hosts: tst4} -macos_add_adobe_hosts: true -# macos_ssh_config: # Moved to vars/ssh_config.enc.yml - -# ================================================== -# Role: git -# ================================================== -git_global_name: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 37656631346636643032613363343064386331633935623836656138336132353763373938333862 - 3966633733643066346461646162333462613235316135300a346437376433333932393361613138 - 63646436306132356433663065326535396538666430333938386436353231626233363135643730 - 3961653434366461340a356532623636303231653737373432376238626164343364383364666439 - 3933 -git_global_email: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 36326534646534633339343639653136323036633932323339376230623363376133663065396263 - 6532333835663865393065396362386531653931653433300a623934393562626564626364363231 - 35663435363732393930643866613534643835613735383263323431643761653664356161363764 - 3365343430333732360a373530303765333666376639613536633165626239323961626335333238 - 38623930626231393662626463643363303638613034323130326261353466316334 -git_global_signing_key: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 34376264346636336637303239636363333538363532653465326461653966663165303731663737 - 3761346332356138353232633232623034323061373138370a613163383063623139313832333963 - 32313430623332376630613136663133333535653966333132343461313932343662393564643065 - 3738306663386432350a323839353064343462336466313661363633326463343738316631333962 - 66633262646636336662646131336538366465313434353766386538303030363130 -git_global_present_configs: - - {name: user.name, value: "{{ git_global_name }}"} - - {name: user.email, value: "{{ git_global_email }}"} - - {name: user.signingkey, value: "{{ git_global_signing_key }}"} - - {name: pull.rebase, value: "true"} - - {name: commit.gpgsign, value: "true"} - - {name: tag.gpgsign, value: "true"} - - {name: init.defaultBranch, value: master} - - {name: push.autoSetupRemote, value: "true"} - -git_global_absent_configs: - - gpg.format - -# ================================================== -# Role: ide -# ================================================== -ide_vscode_extensions: - - github.vscode-github-actions - - ms-python.python - - ms-python.vscode-pylance - - redhat.ansible - - redhat.vscode-yaml - - vscode-icons-team.vscode-icons diff --git a/dotfiles/gh/config.yml b/dotfiles/gh/config.yml new file mode 100644 index 0000000..1c3e3de --- /dev/null +++ b/dotfiles/gh/config.yml @@ -0,0 +1,11 @@ +--- +version: "1" +git_protocol: ssh +editor: nano +prompt: enabled +pager: cat +aliases: + prc: pr create -f + prcd: pr create -f --draft + prdy: pr ready + v: pr view --web diff --git a/dotfiles/git/config.j2 b/dotfiles/git/config.j2 new file mode 100644 index 0000000..5a6f06a --- /dev/null +++ b/dotfiles/git/config.j2 @@ -0,0 +1,36 @@ +[user] + name = Afonso Costa + email = {{ dotfiles_secrets.git.email }} + signingkey = {{ dotfiles_secrets.git.signing_key }} +[core] + editor = nano +[pull] + rebase = true +[commit] + gpgsign = true +[tag] + gpgsign = true +[init] + defaultBranch = master +[push] + autoSetupRemote = true +[alias] + rebase-dance = "!f() { \ + upstream=$(git remote show origin | awk '/HEAD branch/ {print $NF}'); \ + echo \"📡 Upstream main branch: $upstream\"; \ + if [ -n \"$(git status --porcelain --untracked-files=no)\" ]; then \ + echo '💾 Stashing tracked changes…'; \ + git stash && stashed=1; \ + else \ + stashed=0; \ + fi; \ + echo '⬇️ Fetching origin…'; \ + git fetch origin; \ + echo '🔄 Rebase in progress…'; \ + git rebase origin/$upstream; \ + if [ $stashed -eq 1 ]; then \ + echo '📥 Popping stash…'; \ + git stash pop; \ + fi; \ + echo '✅ Rebase dance complete!'; \ + }; f" diff --git a/dotfiles/gnupg/gpg-agent.conf b/dotfiles/gnupg/gpg-agent.conf new file mode 100644 index 0000000..beab335 --- /dev/null +++ b/dotfiles/gnupg/gpg-agent.conf @@ -0,0 +1,3 @@ +pinentry-program /opt/homebrew/bin/pinentry-mac +default-cache-ttl 2592000 # 1 month +max-cache-ttl 2592000 # 1 month diff --git a/dotfiles/gnupg/gpg.conf b/dotfiles/gnupg/gpg.conf new file mode 100644 index 0000000..d53cb13 --- /dev/null +++ b/dotfiles/gnupg/gpg.conf @@ -0,0 +1 @@ +use-agent diff --git a/dotfiles/k9s/aliases.yaml b/dotfiles/k9s/aliases.yaml new file mode 100644 index 0000000..c417df1 --- /dev/null +++ b/dotfiles/k9s/aliases.yaml @@ -0,0 +1,10 @@ +--- +aliases: + dp: deployments + sec: v1/secrets + jo: jobs + cr: clusterroles + crb: clusterrolebindings + ro: roles + rb: rolebindings + np: networkpolicies diff --git a/dotfiles/k9s/config.yaml.j2 b/dotfiles/k9s/config.yaml.j2 new file mode 100644 index 0000000..d031e27 --- /dev/null +++ b/dotfiles/k9s/config.yaml.j2 @@ -0,0 +1,42 @@ +--- +k9s: + liveViewAutoRefresh: false + screenDumpDir: {{ XDG_BASE_DIRS.XDG_STATE_HOME }}/k9s/screen-dumps + refreshRate: 2 + maxConnRetry: 5 + readOnly: false + noExitOnCtrlC: false + ui: + enableMouse: false + headless: false + logoless: false + crumbsless: false + reactive: false + noIcons: false + defaultsToFullScreen: false + skipLatestRevCheck: false + disablePodCounting: false + shellPod: + image: busybox:1.35.0 + namespace: default + limits: + cpu: 100m + memory: 100Mi + imageScans: + enable: false + exclusions: + namespaces: [] + labels: {} + logger: + tail: 100 + buffer: 5000 + sinceSeconds: -1 + textWrap: false + showTime: false + thresholds: + cpu: + critical: 90 + warn: 70 + memory: + critical: 90 + warn: 70 diff --git a/dotfiles/rclone/exclude b/dotfiles/rclone/exclude new file mode 100644 index 0000000..cddd26a --- /dev/null +++ b/dotfiles/rclone/exclude @@ -0,0 +1,130 @@ +# Flake 8 +.flake8 + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# # PyBuilder +# target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env*/ +.venv/ +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# === MacOS gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon\r + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk diff --git a/dotfiles/rsync/exclude b/dotfiles/rsync/exclude new file mode 100644 index 0000000..cddd26a --- /dev/null +++ b/dotfiles/rsync/exclude @@ -0,0 +1,130 @@ +# Flake 8 +.flake8 + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# # PyBuilder +# target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env*/ +.venv/ +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# === MacOS gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon\r + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk diff --git a/dotfiles/vscode/settings.json b/dotfiles/vscode/settings.json new file mode 100644 index 0000000..0de05de --- /dev/null +++ b/dotfiles/vscode/settings.json @@ -0,0 +1,36 @@ +{ + "explorer.confirmDragAndDrop": false, + "files.autoSave": "onFocusChange", + "files.exclude": { + "**/.git": false + }, + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "git.autofetch": true, + "git.confirmSync": false, + "git.enableCommitSigning": true, + "security.workspace.trust.untrustedFiles": "open", + "terminal.integrated.cursorBlinking": true, + "terminal.integrated.cursorStyle": "line", + "terminal.integrated.cursorWidth": 2, + "window.confirmBeforeClose": "keyboardOnly", + "window.nativeTabs": true, + "window.newWindowProfile": "Default", + "window.openFilesInNewWindow": "on", + "window.title": "${activeRepositoryName}", + "window.zoomLevel": 1, + "window.zoomPerWindow": false, + "workbench.colorCustomizations": { + "editorCursor.foreground": "#ff0000", + "editorMultiCursor.primary.foreground": "#ff0000", + "editorMultiCursor.secondary.foreground": "#ff8000", + "editor.findMatchHighlightBackground": "#dba80daa", + "editor.findMatchHighlightForeground": "#000000", + "editor.findMatchBackground": "#0ddb10aa", + "editor.findMatchForeground": "#000000", + "terminalCursor.foreground": "#ff0000" + }, + "workbench.colorTheme": "JetBrains Darcula Theme", + "workbench.iconTheme": "vscode-icons", + "workbench.tree.indent": 16 +} diff --git a/dotfiles/zsh/.zprofile b/dotfiles/zsh/.zprofile new file mode 100644 index 0000000..8cf7042 --- /dev/null +++ b/dotfiles/zsh/.zprofile @@ -0,0 +1,23 @@ +# ~/.zprofile +# Sourced only by login shells (before .zshrc). +# Use for PATH setup, environment prep, and login-time tool initialization. + +# ─────────── PATH ─────────── +export PATH="$XDG_BIN_HOME:$PATH" + +# ─────────── Homebrew ─────────── +if [ -x /opt/homebrew/bin/brew ]; then + eval "$(/opt/homebrew/bin/brew shellenv)" +fi + +# ─────────── Pyenv ─────────── +if command -v pyenv >/dev/null 2>&1; then + eval "$(pyenv init --path)" # login shell PATH prep + [[ -o interactive ]] && eval "$(pyenv init -)" # interactive features +fi + +# ─────────── jEnv ─────────── +if command -v jenv >/dev/null 2>&1; then + export PATH="$HOME/.jenv/bin:$PATH" + [[ -o interactive ]] && eval "$(jenv init -)" +fi diff --git a/dotfiles/zsh/.zshenv.j2 b/dotfiles/zsh/.zshenv.j2 new file mode 100644 index 0000000..8c944b2 --- /dev/null +++ b/dotfiles/zsh/.zshenv.j2 @@ -0,0 +1,49 @@ +# ~/.zshenv +# Essential environment variables for Zsh and tools. +# Sourced by all shells (login/non-login, interactive/non-interactive). +# Do NOT put aliases, prompts, or commands that produce output here. +# +# The following lines need to be placed in /etc/zshenv +# export ZDOTDIR=$HOME/.config/zsh +# echo ". $ZDOTDIR/.zshenv" + +# ─────────── XDG Base Directory Specification ─────────── +export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.local/cache}" +export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" +export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-$HOME/.local/run}" +export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" +export XDG_BIN_HOME="${XDG_BIN_HOME:-$HOME/.local/bin}" + +# ─────────── Zsh ─────────── +export ZDOTDIR="$XDG_CONFIG_HOME/zsh" +export ZSH="$XDG_DATA_HOME/oh-my-zsh" +export HISTFILE="$XDG_STATE_HOME/zsh/history" + +# ─────────── General ─────────── +export EDITOR="nano" +export LESSHISTFILE="$XDG_STATE_HOME/less/history" + +# ─────────── uv ─────────── +export UV_NATIVE_TLS=true +export UV_VENV_SEED=true + +# ─────────── Pyenv ─────────── +export PYENV_ROOT="$XDG_DATA_HOME/pyenv" + +# ─────────── GPG ─────────── +export GPG_TTY=$(tty) +export GNUPGHOME="{{ dotfiles_auth_home }}/gnupg" + +# ─────────── Docker ─────────── +export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker" + +# ─────────── Kubernetes ─────────── +export KUBECONFIG="{{ dotfiles_auth_home }}/kube/config" +export KUBE_EDITOR="nano" + +# ─────────── Ansible ─────────── +export ANSIBLE_HOME="$XDG_DATA_HOME/ansible" + +# ─────────── OCI CLI ─────────── +export OCI_CLI_CONFIG_FILE="{{ dotfiles_auth_home }}/oci/config" diff --git a/dotfiles/zsh/.zshrc b/dotfiles/zsh/.zshrc new file mode 100644 index 0000000..5bc2d75 --- /dev/null +++ b/dotfiles/zsh/.zshrc @@ -0,0 +1,38 @@ +# ~/.zshrc +# Sourced by interactive shells only. +# Set up aliases, functions, key bindings, prompt, and interactive tool features. + +# ─────────── Oh My Zsh ─────────── +export ZSH="$XDG_DATA_HOME/oh-my-zsh" +COMPLETION_WAITING_DOTS="true" +zstyle ':omz:update' frequency 15 +plugins=(aliases alias-finder) +[ -f "$ZSH/oh-my-zsh.sh" ] && source "$ZSH/oh-my-zsh.sh" + +# ─────────── plugins:alias-finder ─────────── +zstyle ':omz:plugins:alias-finder' autoload yes + +# ─────────── Pure Prompt ─────────── +autoload -U promptinit; promptinit +prompt pure + +zstyle :prompt:pure:git:stash show yes +zstyle :prompt:pure:execution_time color yellow +zstyle :prompt:pure:path color yellow +zstyle :prompt:pure:git:arrow color cyan +zstyle :prompt:pure:git:stash color cyan +zstyle :prompt:pure:git:branch color 242 +zstyle :prompt:pure:git:branch:cached color red +zstyle :prompt:pure:git:action color 242 +zstyle :prompt:pure:git:dirty color 218 +zstyle :prompt:pure:host color 242 +zstyle :prompt:pure:prompt:error color red +zstyle :prompt:pure:prompt:success color green +zstyle :prompt:pure:prompt:continuation color cyan +zstyle :prompt:pure:suspended_jobs color red +zstyle :prompt:pure:user color 242 +zstyle :prompt:pure:user:root color default +zstyle :prompt:pure:virtualenv show yes + +# ─────────── Aliases ─────────── +source $ZDOTDIR/aliases.zsh diff --git a/dotfiles/zsh/aliases.zsh b/dotfiles/zsh/aliases.zsh new file mode 100644 index 0000000..5e9c6bb --- /dev/null +++ b/dotfiles/zsh/aliases.zsh @@ -0,0 +1,48 @@ +# ~/.config/zsh/aliases.zsh +# This file defines shell aliases and environment variables for interactive Zsh shells. +# Grouped by category for clarity. + +# ─────────── General ─────────── +alias cdd="cd ~/Desktop" +alias cdh="cd ~" +command -v eza >/dev/null && alias v="eza -lah" || alias v="ls -lah" + +# ─────────── Tools ─────────── +alias wget=wget --hsts-file="$XDG_DATA_HOME/wget-hsts" + +# ─────────── Kubernetes ─────────── +alias k="kubectl" +export do="--dry-run=client -oyaml" +export now="--grace-period=0 --force" +alias kn="kubectl config set-context --current --namespace" +alias ka="kubectl apply -f" +alias kc="kubectl create" +alias kr="kubectl run" +alias kg="kubectl get" +alias kd="kubectl describe" +alias kdel="kubectl delete" +alias kdebug="kubectl run --rm -i --restart=Never" +alias hi="helm install --update" +alias hdel="helm install --update" + +# ─────────── Docker ─────────── +alias d="docker" +alias dc="docker compose" +alias dcu="docker compose up" +alias dcud="docker compose up -d" +alias dcd="docker compose down" + +# ─────────── Git ───────────" +alias g="git" +alias gs="git status" +alias ga="git add" +alias gp="git push" +alias gl="git log --oneline --graph --decorate" +alias gls="gl --show-signature" +alias gco="git checkout" +alias gcb="git checkout -b" +alias gpl="git pull" +alias gst="git stash" +alias gsta="git stash apply" +gcm() { git commit -m "$*"; } +gcmp() { gcm "$@" && git push ; } diff --git a/extra_tasks/.gitkeep b/extra_tasks/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/main.yml b/main.yml index 797a9ba..9dd02a6 100644 --- a/main.yml +++ b/main.yml @@ -1,7 +1,6 @@ --- - name: Configure local host hosts: localhost - vars: ansible_python_interpreter: /usr/bin/python3 @@ -10,40 +9,27 @@ pre_tasks: - name: Python interpreter - debug: - var: ansible_python_interpreter + debug: { var: ansible_python_interpreter } tags: [always] - name: Ensure python3 - assert: - that: ansible_python_version > "2" - tags: [always] - - name: Include playbook configuration. - include_vars: "{{ item }}" - with_fileglob: - - "{{ playbook_dir }}/config.yml" + assert: { that: ansible_facts.python_version > "2" } tags: [always] - - name: Include secret playbook configuration. # noqa ignore-errors - include_vars: "ssh_config.enc.yml" - ignore_errors: true + - name: Provision SOPS and variables + include_role: + name: sops + apply: { tags: [always] } + when: sops_file is defined tags: [always] roles: - - {role: elliotweiser.osx-command-line-tools, tags: [install]} - - {role: dotfiles, tags: [dotfiles]} - - {role: geerlingguy.mac.homebrew, tags: [homebrew]} - - {role: mas, tags: [mas]} - - {role: python, tags: [python]} - - {role: java, tags: [java]} - - {role: macos, tags: [macos]} - - {role: ide, tags: [ide]} - - {role: git, tags: [git]} - - {role: dock, tags: [dock]} + - { role: elliotweiser.osx-command-line-tools, tags: [install] } + - { role: dotfiles, tags: [dotfiles] } + - { role: geerlingguy.mac.homebrew, tags: [brew] } + - { role: geerlingguy.mac.mas, tags: [mas] } + + - { role: python, tags: [python] } + - { role: java, tags: [java] } + # - {role: macos, tags: [macos]} + - { role: ide, tags: [ide] } - tasks: - # Import custom tasks - - tags: [extras] - block: # noqa name[missing] - - name: Import custom tasks - include_tasks: "{{ item }}" - with_fileglob: - - "extra_tasks/**.y*ml" + # - {role: geerlingguy.mac.dock, tags: [dock]} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ba24e12 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "ready-set-develop" +version = "0.1.0" +description = "Ready, Set, Develop™ is a collection of automation scripts to streamline setting up new machines (almost) from scratch or to synchronising configs across computers." +readme = "README.md" +requires-python = ">=3.14" +dependencies = [ + "ansible>=13.2,<14", +] + +[dependency-groups] +dev = [ + "ansible-lint>=26.1,<27", + "yamllint>=1.38,<2", +] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d4eb0a7..0000000 --- a/requirements.txt +++ /dev/null @@ -1,45 +0,0 @@ -ansible==8.5.0 -ansible-compat==4.1.10 -ansible-core==2.15.5 -ansible-lint==6.21.1 -attrs==23.1.0 -black==23.10.0 -bracex==2.4 -certifi==2023.7.22 -cffi==1.16.0 -charset-normalizer==3.3.0 -click==8.1.7 -click-help-colors==0.9.2 -cryptography==41.0.4 -docker==6.1.3 -enrich==1.2.7 -filelock==3.12.4 -idna==3.4 -Jinja2==3.1.2 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -markdown-it-py==3.0.0 -MarkupSafe==2.1.3 -mdurl==0.1.2 -molecule==6.0.2 -molecule-plugins==23.5.0 -mypy-extensions==1.0.0 -packaging==23.2 -pathspec==0.11.2 -platformdirs==3.11.0 -pluggy==1.3.0 -pycparser==2.21 -Pygments==2.16.1 -PyYAML==6.0.1 -referencing==0.30.2 -requests==2.31.0 -resolvelib==1.0.1 -rich==13.6.0 -rpds-py==0.10.6 -ruamel.yaml==0.17.40 -ruamel.yaml.clib==0.2.8 -subprocess-tee==0.4.1 -urllib3==2.0.7 -wcmatch==8.5 -websocket-client==1.6.4 -yamllint==1.32.0 diff --git a/requirements.yml b/requirements.yml index fad092e..d221607 100644 --- a/requirements.yml +++ b/requirements.yml @@ -1,6 +1,8 @@ --- roles: - name: elliotweiser.osx-command-line-tools + version: 2.3.0 collections: - name: geerlingguy.mac + version: 5.0.0 diff --git a/roles/dock/defaults/main.yml b/roles/dock/defaults/main.yml deleted file mode 100644 index f79999a..0000000 --- a/roles/dock/defaults/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dock_persistent_apps: [] -dock_persistent_others: [] diff --git a/roles/dock/tasks/dock-add.yml b/roles/dock/tasks/dock-add.yml deleted file mode 100644 index d41bdcf..0000000 --- a/roles/dock/tasks/dock-add.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- - -- name: "Add to dock: {{ item.name }}" - shell: | - {% if 'type' in item %} - dockutil --add '' --type '{{ item.type }}' --section apps --after '{{ dock_persistent_apps[index - 1].name }}' - {% else %} - dockutil --find '{{ item.name }}' || dockutil --add '{{ item.path }}' --label '{{ item.name }}' - {% endif %} - register: dockutil_add - changed_when: "'was found in' not in dockutil_add.stdout" - -- name: Pause for 5 seconds if added # noqa no-handler - pause: - seconds: 5 - when: dockutil_add.changed -... diff --git a/roles/dock/tasks/dock-move.yml b/roles/dock/tasks/dock-move.yml deleted file mode 100644 index 028a5d9..0000000 --- a/roles/dock/tasks/dock-move.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -- name: "Move dock order: {{ item.name }}" - shell: | - set -o pipefail - {% if item.type | default("") != "" %} - # Skip spacer - echo "Item is spacer. Skipping..." - exit 0; - {% else %} - slot_info=$(dockutil --find '{{ item.name }}') - if [ $? -eq 0 ]; then - slot_value=$(echo "$slot_info" | grep -o -E 'slot [0-9]+' | awk '{print $2}') - if [ "$slot_value" != "{{ index + 1 }}" ]; then - echo "Will move to slot {{ index + 1 }}, currently at $slot_value" - dockutil --move '{{ item.name }}' --position {{ index + 1 }} - else - echo "Slot value is already $slot_value, no action required." - fi - else - echo "Item not found, no action required." - exit 1; - fi - {% endif %} - register: dockutil_move - changed_when: dockutil_move.rc == 0 and dockutil_move.stdout_lines[0].startswith("Will move to slot") - -- name: Pause for 5 seconds if moved # noqa no-handler - pause: - seconds: 5 - when: dockutil_move.changed -... diff --git a/roles/dock/tasks/main.yml b/roles/dock/tasks/main.yml deleted file mode 100644 index c78d3b0..0000000 --- a/roles/dock/tasks/main.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -- name: Setup dock - when: "dock_persistent_apps + dock_persistent_others" - block: - - name: List dock items and extract first column - shell: set -o pipefail && dockutil --list | awk -F'\t' '{print $1}' - register: dockutil_items - changed_when: false - - - name: Set fact with current dock items - set_fact: - dockutil_items: "{{ dockutil_items.stdout | split('\n') | select('!=', '')}}" - - - name: Remove all spacers - command: dockutil --remove spacer-tiles - changed_when: false - - - name: Remove items from dock if not to be persisted - command: dockutil --remove '{{ item }}' - with_items: "{{ dockutil_items }}" - when: "item not in (dock_persistent_apps + dock_persistent_others) | map(attribute='name', default='')" - register: dockutil_remove - failed_when: false - changed_when: dockutil_remove.rc == 0 and dockutil_remove.stdout == "" - - - name: Add all to dock - include_tasks: dock-add.yml - loop: "{{ dock_persistent_apps + dock_persistent_others }}" - loop_control: - index_var: index - - - name: Move persistent-apps - include_tasks: dock-move.yml - loop: "{{ dock_persistent_apps }}" - loop_control: - index_var: index - pause: 1 - - - name: Move persistent-others - include_tasks: dock-move.yml - loop: "{{ dock_persistent_others }}" - loop_control: - index_var: index -... diff --git a/roles/dotfiles/defaults/main.yml b/roles/dotfiles/defaults/main.yml index 5af9dc9..eefdcbf 100644 --- a/roles/dotfiles/defaults/main.yml +++ b/roles/dotfiles/defaults/main.yml @@ -1,9 +1,17 @@ --- -dotfiles_repo: https://github.com/afonsoc12/dotfiles -# Git commit, branch or tag to checkout -dotfiles_version: HEAD -dotfiles_repo_dest: "{{ lookup('env', 'HOME') }}/.config/dotfiles" -dotfiles_extra_zshrc: null -dotfiles_secrets_src: # /Volumes/myvolume/.mysecrets +dotfiles_dir: "{{ playbook_dir }}/dotfiles" +# dotfiles_secrets_src: dotfiles_secrets_dest: "{{ ansible_env.HOME }}" dotfiles_use_links: true + +dotfiles_links_vscode_settings_dir: "{{ lookup('env', 'HOME') }}/Library/Application Support/Code/User" +dotfiles_auth_home: "{{ lookup('env', 'HOME') }}/.secrets" + +# XDG Base Directory Specification (https://specifications.freedesktop.org/basedir/latest/) +XDG_BASE_DIRS: # noqa var-naming[pattern] + XDG_CONFIG_HOME: "{{ lookup('env', 'XDG_CONFIG_HOME') | default(ansible_facts['env']['HOME'] + '/.config', true) }}" # noqa var-naming[pattern] + XDG_CACHE_HOME: "{{ lookup('env', 'XDG_CACHE_HOME') | default(ansible_facts['env']['HOME'] + '/.local/cache', true) }}" + XDG_DATA_HOME: "{{ lookup('env', 'XDG_DATA_HOME') | default(ansible_facts['env']['HOME'] + '/.local/share', true) }}" + XDG_STATE_HOME: "{{ lookup('env', 'XDG_STATE_HOME') | default(ansible_facts['env']['HOME'] + '/.local/state', true) }}" + XDG_RUNTIME_DIR: "{{ lookup('env', 'XDG_RUNTIME_DIR') | default(ansible_facts['env']['HOME'] + '/.local/run', true) }}" + XDG_BIN_HOME: "{{ lookup('env', 'XDG_BIN_HOME') | default(ansible_facts['env']['HOME'] + '/.local/bin', true) }}" diff --git a/roles/dotfiles/tasks/install.yml b/roles/dotfiles/tasks/install.yml new file mode 100644 index 0000000..8bfa26c --- /dev/null +++ b/roles/dotfiles/tasks/install.yml @@ -0,0 +1,88 @@ +--- +- name: Ensure XDG base dirs exist + file: + path: "{{ item.value }}" + state: directory + mode: "0755" + loop: "{{ XDG_BASE_DIRS | dict2items }}" + +- name: Find all dotfiles + find: + paths: "{{ dotfiles_dir }}" + file_type: file + hidden: true + recurse: true + register: dotfiles_found + changed_when: false + +- name: Find template files (.j2) + set_fact: + dotfiles_templates: "{{ dotfiles_found.files | selectattr('path', 'search', '\\.j2$') | list }}" + +- name: Find non-template files + set_fact: + dotfiles_files: "{{ dotfiles_found.files | rejectattr('path', 'search', '\\.j2$') | list }}" + +- name: Create parent directories for dotfiles in XDG_CONFIG_HOME + file: + path: "{{ XDG_BASE_DIRS.XDG_CONFIG_HOME }}/{{ item.path | dirname | regex_replace('^' + dotfiles_dir + '/', '') }}" + state: directory + mode: "0700" + loop: "{{ dotfiles_found.files }}" + loop_control: { label: "{{ item.path | dirname }}" } + +- name: Link dotfiles files + when: dotfiles_use_links | default(true) + file: + src: "{{ item.path }}" + dest: >- + {{ + XDG_BASE_DIRS.XDG_CONFIG_HOME ~ '/' ~ + (item.path | dirname | regex_replace('^' + dotfiles_dir + '/','')) ~ '/' ~ + (item.path | basename) + }} + state: link + force: true + mode: "0644" + loop: "{{ dotfiles_files }}" + loop_control: { label: "{{ item.path }}" } + +- name: Copy dotfiles files (if not using links) + when: dotfiles_use_links is defined and not dotfiles_use_links + copy: + src: "{{ item.path }}" + dest: >- + {{ + XDG_BASE_DIRS.XDG_CONFIG_HOME ~ '/' ~ + (item.path | dirname | regex_replace('^' + dotfiles_dir + '/','')) ~ '/' ~ + (item.path | basename) + }} + mode: "0644" + loop: "{{ dotfiles_files }}" + loop_control: { label: "{{ item.path }}" } + +- name: Copy dotfiles templates + template: + src: "{{ item.path }}" + dest: >- + {{ + XDG_BASE_DIRS.XDG_CONFIG_HOME ~ '/' ~ + (item.path | dirname | regex_replace('^' + dotfiles_dir + '/','')) ~ '/' ~ + (item.path | basename | regex_replace('\.j2$', '')) + }} + mode: "0644" + loop: "{{ dotfiles_templates }}" + loop_control: { label: "{{ item.path }}" } + +- name: Create /etc/zshenv entrypoint + become: true + copy: + dest: /etc/zshenv + content: | + export ZDOTDIR="$HOME/.config/zsh" + if [ -f "$ZDOTDIR/.zshenv" ]; then + . "$ZDOTDIR/.zshenv" + else + echo "ERROR: $ZDOTDIR/.zshenv not found! This file is managed by afonsoc12/dotfiles." >&2 + fi + mode: "0444" diff --git a/roles/dotfiles/tasks/links.yml b/roles/dotfiles/tasks/links.yml new file mode 100644 index 0000000..5905c88 --- /dev/null +++ b/roles/dotfiles/tasks/links.yml @@ -0,0 +1,60 @@ +--- +- name: Ensure VS Code User settings directory exists + file: + path: "{{ dotfiles_links_vscode_settings_dir }}" + state: directory + mode: "0755" + +- name: Build list of VS Code files for symlinking + set_fact: + dotfiles_vscode_files: >- + {{ (dotfiles_vscode_files | default([])) + + [ + { + 'src': XDG_BASE_DIRS.XDG_CONFIG_HOME ~ '/' ~ (item.path | regex_replace('^' + dotfiles_dir + '/', '')), + 'dest': dotfiles_links_vscode_settings_dir ~ '/' ~ (item.path | basename), + 'basename': item.path | basename + } + ] + }} + loop: "{{ dotfiles_found.files | selectattr('path', 'search', '(^|/)vscode(/|$)') | list }}" + loop_control: + label: "{{ item.path }}" + +- name: Symlink VS Code config files + file: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + state: link + force: true + loop: "{{ dotfiles_vscode_files }}" + loop_control: + label: "{{ item.basename }}" + +- name: Find GNUPG config files + set_fact: + dotfiles_gnupg_files: >- + {{ (dotfiles_gnupg_files | default([])) + + [{ + 'src': XDG_BASE_DIRS.XDG_CONFIG_HOME ~ '/' ~ (item.path | regex_replace('^' + dotfiles_dir + '/', '')), + 'dest': dotfiles_auth_home ~ '/' ~ (item.path | regex_replace('^' + dotfiles_dir + '/', '')), + 'basename': item.path | basename + }]}} + loop: >- + {{ + dotfiles_found.files + | selectattr('path', 'search', '(^|/)gnupg(/|$)') + | list + }} + loop_control: + label: "{{ item.path }}" + +- name: Symlink GNUPG config files + file: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + state: link + force: true + loop: "{{ dotfiles_gnupg_files }}" + loop_control: + label: "{{ item.basename }}" diff --git a/roles/dotfiles/tasks/main.yml b/roles/dotfiles/tasks/main.yml index c109886..c777e70 100644 --- a/roles/dotfiles/tasks/main.yml +++ b/roles/dotfiles/tasks/main.yml @@ -1,58 +1,44 @@ --- -- name: Ensure dotfiles parent dir exists - file: - path: "{{ dotfiles_repo_dest | string | dirname }}" - state: directory - mode: "0755" +- name: Install dotfiles + include_tasks: install.yml -- name: Clone dotfiles repo - git: - repo: "{{ dotfiles_repo }}" - dest: "{{ dotfiles_repo_dest }}" - version: "{{ dotfiles_version }}" - environment: - GIT_TERMINAL_PROMPT: "0" # reports "terminal prompts disabled" on missing password +- name: Link dotfiles that cannot be used from XDG_CONFIG_HOME + include_tasks: links.yml -- name: Run installation tasks (tasks/*.yml) - include_tasks: "{{ task }}" - loop: "{{ query('fileglob', dotfiles_repo_dest | string | expandvars ~ '/tasks/*.yml') | sort }}" - loop_control: - loop_var: task +# - name: Append extra block to .zshrc +# blockinfile: +# path: "{{ ansible_env.ZDOTDIR | default(zshenv.ZDOTDIR) | expandvars }}/.zshrc" +# block: "{{ dotfiles_extra_zshrc }}" +# when: dotfiles_extra_zshrc -- name: Append extra block to .zshrc - blockinfile: - path: "{{ ansible_env.ZDOTDIR | default(zshenv.ZDOTDIR) | expandvars }}/.zshrc" - block: "{{ dotfiles_extra_zshrc }}" - when: dotfiles_extra_zshrc +# - name: Check volume with secrets is mounted +# stat: +# path: "{{ dotfiles_secrets_src }}" +# register: secrets_volume +# when: dotfiles_secrets_src is defined -- name: Check volume with secrets is mounted - stat: - path: "{{ dotfiles_secrets_src }}" - register: secrets_volume - when: dotfiles_secrets_src +# - name: Copy secrets from volume and set permissions +# when: +# - secrets_volume.stat is defined +# - secrets_volume.stat.exists +# block: +# - name: Copy secrets +# copy: +# src: "{{ dotfiles_secrets_src }}" +# dest: "{{ dotfiles_secrets_dest }}" +# directory_mode: "0700" +# mode: "0400" -- name: Copy secrets from volume and set permissions - when: - - secrets_volume.stat is defined - - secrets_volume.stat.exists - block: - - name: Copy secrets - copy: - src: "{{ dotfiles_secrets_src }}" - dest: "{{ dotfiles_secrets_dest }}" - directory_mode: "0700" - mode: "0400" +# - name: Check gnupg folder is present +# stat: +# path: "{{ dotfiles_secrets_dest }}/{{ dotfiles_secrets_src | string | basename }}/gnupg" +# register: gnupg_present - - name: Check gnupg folder is present - stat: - path: "{{ dotfiles_secrets_dest }}/{{ dotfiles_secrets_src | string | basename }}/gnupg" - register: gnupg_present - - - name: Set gnupg permissions - copy: - src: "{{ dotfiles_secrets_src }}/gnupg" - dest: "{{ dotfiles_secrets_dest }}/{{ dotfiles_secrets_src | string | basename }}" - directory_mode: "0700" - mode: "0600" - when: - - gnupg_present.stat.exists +# - name: Set gnupg permissions +# copy: +# src: "{{ dotfiles_secrets_src }}/gnupg" +# dest: "{{ dotfiles_secrets_dest }}/{{ dotfiles_secrets_src | string | basename }}" +# directory_mode: "0700" +# mode: "0600" +# when: +# - gnupg_present.stat.exists diff --git a/roles/git/defaults/main.yml b/roles/git/defaults/main.yml deleted file mode 100644 index 16f4299..0000000 --- a/roles/git/defaults/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -git_global_present_configs: [] -git_global_absent_configs: [] -git_clone_repos: [] diff --git a/roles/git/tasks/main.yml b/roles/git/tasks/main.yml deleted file mode 100644 index e29ae67..0000000 --- a/roles/git/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -- name: Create git directory - file: - path: "{{ ansible_env.XDG_CONFIG_HOME | default(zshenv.XDG_CONFIG_HOME) | expandvars }}/git" - state: directory - mode: "0700" - -- name: Create git global config file if not exists - file: - path: "{{ ansible_env.XDG_CONFIG_HOME | default(zshenv.XDG_CONFIG_HOME) | expandvars }}/git/config" - state: touch - modification_time: preserve - access_time: preserve - mode: "0600" - -- name: Unset global configs - git_config: - scope: global - name: "{{ item }}" - state: absent - with_items: "{{ git_global_absent_configs }}" - when: git_global_absent_configs - -- name: Set global configs - git_config: - scope: global - name: "{{ item.name }}" - value: "{{ item.value }}" - when: git_global_present_configs - loop: "{{ git_global_present_configs }}" - -- name: Clone repositories to location if not exist - git: # noqa latest[git] - repo: "{{ item.repo }}" - dest: "{{ item.dest }}" - update: false - with_items: "{{ git_clone_repos }}" - when: git_clone_repos diff --git a/roles/ide/defaults/main.yml b/roles/ide/defaults/main.yml index 577af8c..8a23f1a 100644 --- a/roles/ide/defaults/main.yml +++ b/roles/ide/defaults/main.yml @@ -2,12 +2,14 @@ # ================================================== # Task: iterm # ================================================== -ide_zsh_path: "{{ ansible_env.ZSH | default(zshenv.ZSH) | expandvars }}" +ide_zsh_path: >- + {{ + lookup('env', 'ZSH') + | default(lookup('env', 'XDG_DATA_HOME') ~ '/oh-my-zsh', true) + | default(lookup('env', 'HOME') ~ '/.local/share/oh-my-zsh', true) + }} # ================================================== # Task: vscode # ================================================== -ide_vscode_app_dir: "{{ homebrew_cask_appdir | default('/Applications') }}/Visual\ Studio\ Code.app1" -ide_vscode_code_bin: "{{ ide_vscode_app_dir }}/Contents/Resources/app/bin/code" -ide_vscode_code_dest_dir: /usr/local/bin ide_vscode_extensions: [] diff --git a/roles/ide/tasks/main.yml b/roles/ide/tasks/main.yml index 2eb6733..584789a 100644 --- a/roles/ide/tasks/main.yml +++ b/roles/ide/tasks/main.yml @@ -1,6 +1,6 @@ --- - name: Configure terminal (iTerm) - import_tasks: iterm.yml + import_tasks: terminal.yml - name: Configure VSCode import_tasks: vscode.yml diff --git a/roles/ide/tasks/iterm.yml b/roles/ide/tasks/terminal.yml similarity index 58% rename from roles/ide/tasks/iterm.yml rename to roles/ide/tasks/terminal.yml index ac15311..15c2b1e 100644 --- a/roles/ide/tasks/iterm.yml +++ b/roles/ide/tasks/terminal.yml @@ -1,29 +1,34 @@ --- +- name: Install iTerm (homebrew) + homebrew_cask: + name: iterm2 + state: present + - name: Check if oh-my-zsh is already installed stat: path: "{{ ide_zsh_path }}" - register: zsh_dir + register: ide_zsh_dir - name: Create temporary file ansible.builtin.tempfile: state: file suffix: oh-my-zsh-install.sh - register: tempfile - when: zsh_dir.stat.exists is false + register: ide_tempfile + when: ide_zsh_dir.stat.exists is false - name: Download oh-my-zsh installation script get_url: url: https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh - dest: "{{ tempfile.path }}" + dest: "{{ ide_tempfile.path }}" mode: "0755" - when: zsh_dir.stat.exists is false + when: ide_zsh_dir.stat.exists is false - name: Install oh-my-zsh - command: bash {{ tempfile.path }} --unattended --keep-zshrc + command: bash {{ ide_tempfile.path }} --unattended --keep-zshrc environment: ZSH: "{{ ide_zsh_path }}" changed_when: true - when: zsh_dir.stat.exists is false + when: ide_zsh_dir.stat.exists is false - name: Install pure theme homebrew: diff --git a/roles/ide/tasks/vscode.yml b/roles/ide/tasks/vscode.yml index cfcd25b..c9c09fd 100644 --- a/roles/ide/tasks/vscode.yml +++ b/roles/ide/tasks/vscode.yml @@ -1,25 +1,14 @@ --- -- name: Check VSCode is installed - stat: - path: "{{ ide_vscode_app_dir }}" - register: vscode_installed - -- name: Add code binary to {{ ide_vscode_code_dest_dir }} - become: true - file: - src: "{{ ide_vscode_code_bin }}" - dest: "{{ ide_vscode_code_dest_dir }}/code" - state: link - mode: "0755" - when: vscode_installed.stat.exists +- name: Install VSCode + homebrew_cask: + name: visual-studio-code + state: present - name: Install VSCode extensions command: "code --install-extension {{ item }}" with_items: "{{ ide_vscode_extensions }}" - register: code_install + register: ide_code_install changed_when: - - code_install.rc == 0 - - "'successfully installed' in code_install.stdout" - when: - - ide_vscode_extensions - - vscode_installed.stat.exists + - ide_code_install.rc == 0 + - "'successfully installed' in ide_code_install.stdout" + when: ide_vscode_extensions is truthy diff --git a/roles/java/defaults/main.yml b/roles/java/defaults/main.yml index 8401966..6dd4a69 100644 --- a/roles/java/defaults/main.yml +++ b/roles/java/defaults/main.yml @@ -1,4 +1,5 @@ --- +java_role_skip: true java_versions: [] java_jenv_global: [] java_jenv_plugins: diff --git a/roles/java/tasks/main.yml b/roles/java/tasks/main.yml index 585d551..f761885 100644 --- a/roles/java/tasks/main.yml +++ b/roles/java/tasks/main.yml @@ -1,32 +1,35 @@ --- -- name: Install jEnv - homebrew: - name: jenv - when: java_versions +- name: Install java + when: not (java_role_skip | default(false)) + block: + - name: Install jEnv + homebrew: + name: jenv + when: java_versions is truthy -- name: Set jEnv root fact - command: jenv root - changed_when: false - register: jenv_root - when: java_versions + - name: Set jEnv root fact + command: jenv root + changed_when: false + register: java_jenv_root + when: java_versions is truthy -- name: Install Temurin versions - loop: "{{ java_versions }}" - include_tasks: install_temurin.yml + - name: Install Temurin versions + loop: "{{ java_versions }}" + include_tasks: temurin.yml -- name: Set jEnv global {{ java_jenv_global | join(' ') }} - copy: - content: "{{ java_jenv_global | join('\n') }}" - dest: "{{ jenv_root.stdout }}/version" - mode: "0755" - when: java_jenv_global + - name: Set jEnv global {{ java_jenv_global | join(' ') }} + copy: + content: "{{ java_jenv_global | join('\n') }}" + dest: "{{ java_jenv_root.stdout }}/version" + mode: "0755" + when: java_jenv_global -- name: Add jEnv plugins - shell: - cmd: eval "$(jenv init -)" && jenv enable-plugin {{ item }} - executable: /bin/zsh - register: jenv_plugin - changed_when: "'plugin activated' in jenv_plugin.stdout" - failed_when: "jenv_plugin.rc != 0 or ('plugin activated' not in jenv_plugin.stdout and 'plugin already enabled' not in jenv_plugin.stdout)" - loop: "{{ java_jenv_plugins }}" - when: java_versions + - name: Add jEnv plugins + shell: + cmd: eval "$(jenv init -)" && jenv enable-plugin {{ item }} + executable: /bin/zsh + register: java_jenv_plugin + changed_when: "'plugin activated' in java_jenv_plugin.stdout" + failed_when: "java_jenv_plugin.rc != 0 or ('plugin activated' not in java_jenv_plugin.stdout and 'plugin already enabled' not in java_jenv_plugin.stdout)" + loop: "{{ java_java_jenv_plugins }}" + when: java_versions is truthy diff --git a/roles/java/tasks/install_temurin.yml b/roles/java/tasks/temurin.yml similarity index 58% rename from roles/java/tasks/install_temurin.yml rename to roles/java/tasks/temurin.yml index d021b66..bfdecf1 100644 --- a/roles/java/tasks/install_temurin.yml +++ b/roles/java/tasks/temurin.yml @@ -2,15 +2,9 @@ - name: "Install Temurin version {{ item }}" homebrew_cask: name: "temurin@{{ item }}" - register: brew_temurin - changed_when: brew_temurin.msg == '' - failed_when: >- - ('was successfully installed!' not in brew_temurin.msg - and 'is already installed' not in brew_temurin.msg - and '' not in brew_temurin.msg) - or 'No available formula' in brew_temurin.msg + state: present -- name: jEnv init # noqa: name[casing] +- name: jEnv init # noqa: name[casing] shell: eval "$(jenv init -)" changed_when: false @@ -24,13 +18,13 @@ or java_home.stdout_lines | length != 1 or ("-" ~ item ~ "." not in java_home.stdout and "/" ~ item ~ "." not in java_home.stdout) -- name: Add Java version {{ item }} to jEnv # noqa: name[template] +- name: Add Java version {{ item }} to jEnv # noqa: name[template] command: jenv add {{ java_home.stdout }} - register: jenv_add - changed_when: "'added' in jenv_add.stdout" - failed_when: "jenv_add.rc !=0 or 'is not a valid path to java installation' in jenv_add.stdout" + register: java_jenv_add + changed_when: "'added' in java_jenv_add.stdout" + failed_when: "java_jenv_add.rc !=0 or 'is not a valid path to java installation' in java_jenv_add.stdout" -- name: Add Java version {{ item }} (major version alias) to jEnv # noqa: name[template] +- name: Add Java version {{ item }} (major version alias) to jEnv # noqa: name[template] file: src: "/Library/Java/JavaVirtualMachines/temurin-{{ item }}.jdk/Contents/Home" dest: "~/.jenv/versions/{{ item }}" diff --git a/roles/mas/defaults/main.yml b/roles/mas/defaults/main.yml deleted file mode 100644 index 685d9ab..0000000 --- a/roles/mas/defaults/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -mas_uninstalled_apps: [] -mas_installed_apps: [] -mas_upgrade_all_apps: false diff --git a/roles/mas/tasks/main.yml b/roles/mas/tasks/main.yml deleted file mode 100644 index cbc5075..0000000 --- a/roles/mas/tasks/main.yml +++ /dev/null @@ -1,39 +0,0 @@ ---- -- name: Install mas (homebrew) - homebrew: - name: mas - state: present - -- name: List installed MAS apps. - command: mas list - register: mas_list - check_mode: false - changed_when: false - -- name: Display MAS installed apps. - debug: - var: mas_list.stdout_lines - verbosity: 1 - -# Uninstall does not work: https://github.com/mas-cli/mas/issues/313 -# - name: Ensure unwanted MAS apps are uninstalled. -# command: mas uninstall "{{ item.id | default(item) }}" -# register: mas_uninstall -# with_items: "{{ mas_uninstalled_apps }}" -# changed_when: -# - mas_uninstall.rc == 0 -# - "'==> Installed' in mas_uninstall.stdout_lines[-1]" - -- name: Ensure configured MAS apps are installed. - command: mas install "{{ item.id | default(item) }}" - register: mas_install - with_items: "{{ mas_installed_apps }}" - changed_when: - - mas_install.rc == 0 - - "'==> Installed' in mas_install.stdout" - -- name: Upgrade all apps - command: mas upgrade - register: mas_upgrade - changed_when: "'Warning: Nothing found to upgrade' not in mas_upgrade.stderr" - when: mas_upgrade_all_apps diff --git a/roles/python/defaults/main.yml b/roles/python/defaults/main.yml index 926c98a..100fef7 100644 --- a/roles/python/defaults/main.yml +++ b/roles/python/defaults/main.yml @@ -1,9 +1,11 @@ --- -python_pyenv_root: "{{ ansible_env.PYENV_ROOT | default(zshenv.PYENV_ROOT) | expandvars }}" +python_pyenv_root: "{{ (ansible_facts.env.XDG_DATA_HOME | default(ansible_facts.env.HOME ~ '/.local')) ~ '/pyenv' }}" python_pyenv_versions: [] -python_pyenv_global: [] +python_pyenv_global: python_pyenv_osx_packages: - openssl - readline - xz python_pip_packages: [] +python_uv_versions: [] +python_uv_tools: [] diff --git a/roles/python/tasks/install_pyenv.yml b/roles/python/tasks/install_pyenv.yml deleted file mode 100644 index 323e3ec..0000000 --- a/roles/python/tasks/install_pyenv.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -- name: Install pyenv (homebrew) - homebrew: - name: pyenv - state: present - -- name: Install pyenv-virtualenv plugin (homebrew) - homebrew: - name: pyenv-virtualenv - state: present diff --git a/roles/python/tasks/main.yml b/roles/python/tasks/main.yml index b2995fc..5f3544b 100644 --- a/roles/python/tasks/main.yml +++ b/roles/python/tasks/main.yml @@ -1,53 +1,6 @@ --- -- environment: # noqa name[missing] - PYENV_ROOT: "{{ python_pyenv_root }}" - block: - - name: Install - import_tasks: install_pyenv.yml - tags: [install] +- name: Setup pyenv + import_tasks: pyenv.yml - - name: Create folder for PYENV_ROOT - become: true - file: - path: "{{ python_pyenv_root }}" - state: directory - mode: "0777" - - - name: Install development packages necessary for building Python - homebrew: - name: "{{ python_pyenv_osx_packages }}" - state: present - - - name: Test pyenv command works - ansible.builtin.command: pyenv --version - register: result - changed_when: false - failed_when: result.rc != 0 or "pyenv" not in result.stdout - - - name: Install Python {{ python_pyenv_versions | join(' ') }} - ansible.builtin.command: pyenv install {{ item }} --skip-existing - register: result - with_items: "{{ python_pyenv_versions }}" - changed_when: - - result.rc == 0 - - result.stdout != '' - - - name: Set pyenv root fact - command: pyenv root - changed_when: false - register: pyenv_root - - - name: Set pyenv global {{ python_pyenv_global | join(' ') }} - copy: - content: "{{ python_pyenv_global | join('\n') }}" - dest: "{{ pyenv_root.stdout }}/version" - mode: "0755" - when: python_pyenv_global - - - name: Install global Pip packages - pip: - name: "{{ item.name | default(item) }}" - state: present - version: "{{ item.version | default(omit) }}" - executable: "{{ pyenv_root.stdout }}/shims/pip" - loop: "{{ python_pip_packages }}" +- name: Setup uv + import_tasks: uv.yml diff --git a/roles/python/tasks/pyenv.yml b/roles/python/tasks/pyenv.yml new file mode 100644 index 0000000..ea83c8d --- /dev/null +++ b/roles/python/tasks/pyenv.yml @@ -0,0 +1,62 @@ +--- +- environment: # noqa name[missing] + python_pyenv_root: "{{ python_pyenv_root }}" + block: + - name: Debug python_pyenv_root + debug: + var: python_pyenv_root + verbosity: 1 + + - name: Confirm python_pyenv_root + pause: + when: ansible_verbosity | int >= 1 + + - name: Install pyenv (homebrew) + homebrew: + name: pyenv + state: present + + - name: Create folder for python_pyenv_root + file: + path: "{{ python_pyenv_root }}" + state: directory + mode: "0755" + + - name: Install development packages necessary for building Python + homebrew: + name: "{{ python_pyenv_osx_packages }}" + state: present + + - name: Test pyenv command works + ansible.builtin.command: pyenv --version + register: python_pyenv_test + changed_when: false + failed_when: python_pyenv_test.rc != 0 or "pyenv" not in python_pyenv_test.stdout + + - name: Install Python versions {{ python_pyenv_versions | join(', ') }} + ansible.builtin.command: pyenv install {{ item }} --skip-existing + loop: "{{ python_pyenv_versions }}" + register: python_pyenv_install + changed_when: + - python_pyenv_install.rc == 0 + - python_pyenv_install.stdout != '' + + - name: Set pyenv root fact + command: pyenv root + changed_when: false + register: python_pyenv_root + + - name: Set pyenv global {{ python_pyenv_global }} + copy: + content: "{{ python_pyenv_global ~ '\n' }}" + dest: "{{ python_pyenv_root.stdout }}/version" + mode: "0755" + when: python_pyenv_global is truthy + + - name: Install global Pip packages + pip: + name: "{{ item.name | default(item) }}" + state: present + version: "{{ item.version | default(omit) }}" + executable: "{{ python_pyenv_root.stdout }}/shims/pip" + loop: "{{ python_pip_packages }}" diff --git a/roles/python/tasks/uv.yml b/roles/python/tasks/uv.yml new file mode 100644 index 0000000..d4419f9 --- /dev/null +++ b/roles/python/tasks/uv.yml @@ -0,0 +1,25 @@ +--- +- name: Install uv (homebrew) + homebrew: + name: uv + state: present + +- name: Test uv command works + ansible.builtin.command: uv --version + register: python_uv_test + changed_when: false + failed_when: python_uv_test.rc != 0 or "uv" not in python_uv_test.stdout + +- name: Install Python {{ python_uv_versions | join(' ') }} + ansible.builtin.command: uv python install {{ item }} + register: python_uv_install + with_items: "{{ python_uv_versions }}" + changed_when: + - python_uv_install.rc == 0 + - "'is already installed' not in python_uv_install.stderr" + +- name: Install uv tools + command: uv tool install {{ item }} + register: python_uv_tools_install + changed_when: "'Installed' in python_uv_tools_install.stderr" + loop: "{{ python_uv_tools }}" diff --git a/roles/sops/defaults/main.yml b/roles/sops/defaults/main.yml new file mode 100644 index 0000000..e7d2616 --- /dev/null +++ b/roles/sops/defaults/main.yml @@ -0,0 +1,6 @@ +--- +sops_file: +sops_version: "3.11.0" +sops_repo: "https://github.com/getsops/sops" +sops_tmp_dir: "/tmp/ansible_sops" +sops_binary: "sops" diff --git a/roles/sops/handlers/main.yml b/roles/sops/handlers/main.yml new file mode 100644 index 0000000..3836d1b --- /dev/null +++ b/roles/sops/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Remove sops binary + file: + path: "{{ sops_tmp_dir }}" + state: absent diff --git a/roles/sops/tasks/install_sops.yml b/roles/sops/tasks/install_sops.yml new file mode 100644 index 0000000..5d2f97b --- /dev/null +++ b/roles/sops/tasks/install_sops.yml @@ -0,0 +1,29 @@ +--- +- name: Ensure temp directory exists + file: + path: "{{ sops_tmp_dir }}" + state: directory + mode: "0755" + +- name: Construct download URL if SOPS not installed + set_fact: + sops_download_url: >- + {{ ( + (sops_repo | default('https://github.com/getsops/sops')) + ~ '/releases/download/v' ~ sops_version + ~ '/sops-v' ~ sops_version + ~ '.' ~ ('darwin' if ansible_facts['os_family'] == 'Darwin' else 'linux') + ~ '.' ~ ('amd64' if ansible_facts['architecture'] == 'x86_64' else ansible_facts['architecture']) + ) | trim }} + +- name: Download SOPS binary if not installed + get_url: + url: "{{ sops_download_url }}" + dest: "{{ sops_tmp_dir }}" + mode: "0755" + register: sops_download + +- name: Set sops_binary + set_fact: + sops_binary: "{{ sops_download.dest }}" + when: sops_download.status_code == 200 diff --git a/roles/sops/tasks/main.yml b/roles/sops/tasks/main.yml new file mode 100644 index 0000000..4a41bae --- /dev/null +++ b/roles/sops/tasks/main.yml @@ -0,0 +1,48 @@ +--- +- name: Check if SOPS is already installed + command: which sops + register: sops_check + changed_when: false + ignore_errors: true + +- name: Set fact for existing SOPS binary + set_fact: + sops_binary: "{{ sops_check.stdout }}" + when: sops_check.rc == 0 + +- name: Confirm sops install + pause: + prompt: "sops not found. Will be temporarily installed in {{ sops_tmp_dir }}. Press ENTER to continue" + when: sops_check.rc != 0 + +- name: Install sops in {{ sops_tmp_dir }} + import_tasks: install_sops.yml + when: sops_check.rc != 0 + notify: Remove sops binary + +- name: Test sops command works + command: "{{ sops_binary }} --version" + register: sops_test + changed_when: false + failed_when: sops_test.rc != 0 + +- name: Load sops file if defined + set_fact: + sops_decrypted: "{{ lookup('community.sops.sops', sops_file) | from_yaml | default({}) }}" + when: sops_file is truthy + +- name: Warn if SOPS file is empty + debug: + msg: "WARNING: {{ sops_file }} exists but contains no variables" + warn: true + when: + - sops_file is truthy + - sops_decrypted | length == 0 + +- name: Inject SOPS variables at top-level + set_fact: + "{{ item.key }}": "{{ item.value }}" + loop: "{{ sops_decrypted | dict2items }}" + loop_control: + label: "{{ item.key }}" + when: sops_decrypted is defined diff --git a/test/config.yml b/test/config.yml index 190f5a0..9efdab9 100644 --- a/test/config.yml +++ b/test/config.yml @@ -2,10 +2,6 @@ # ================================================== # Role: dotfiles # ================================================== -dotfiles_repo: https://github.com/afonsoc12/dotfiles -# dotfiles_version: HEAD -# dotfiles_repo_dest: "{{ lookup('env','HOME') }}/.config/dotfiles" -# dotfiles_extra_zshrc: # ================================================== # Role: geerlingguy.mac.homebrew @@ -27,7 +23,7 @@ homebrew_cask_apps: # Role: mas # ================================================== mas_upgrade_all_apps: true -mas_installed_apps: [] # mas-cli makes in GitHub Actions runner hang +mas_installed_apps: [] # mas-cli makes in GitHub Actions runner hang # - { id: 409201541, name: Pages } # - { id: 409203825, name: Numbers } # - { id: 409203825, name: Keynote } @@ -75,46 +71,28 @@ dock_persistent_apps: pos: 3 dock_persistent_others: - - {name: Applications, path: /Applications} - - {name: Downloads, path: "/Users/{{ ansible_env.USER }}/Downloads"} + - { name: Applications, path: /Applications } + - { name: Downloads, path: "/Users/{{ ansible_env.USER }}/Downloads" } # ================================================== # Role: macos # ================================================== macos_config_files: - - {src: files/smb/nsmb.conf, dest: /etc, become: true} - - {src: files/rectangle/com.knollsoft.Rectangle.plist, dest: $HOME/Library/Preferences} + - { src: files/smb/nsmb.conf, dest: /etc, become: true } + - { src: files/rectangle/com.knollsoft.Rectangle.plist, dest: $HOME/Library/Preferences } macos_ini_properties: # KeePassXC - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoReloadOnChange, value: "false"} - - {path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoSaveAfterEveryChange, value: "false"} + - { path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoReloadOnChange, value: "false" } + - { path: $HOME/Library/Application Support/KeePassXC/keepassxc.ini, section: General, option: AutoSaveAfterEveryChange, value: "false" } macos_hosts: - - {ip: 127.0.0.1, hosts: tst.com} - - {ip: 127.0.0.1, hosts: tst2.com} + - { ip: 127.0.0.1, hosts: tst.com } + - { ip: 127.0.0.1, hosts: tst2.com } macos_add_adobe_hosts: true macos_adobe_hosts_file: https://raw.githubusercontent.com/Ruddernation-Designs/Adobe-URL-Block-List/master/hosts macos_ssh_config: - - {host: "test1", user: test, hostname: "example.com", key_file: "~/.ssh/id_rsa"} - - {host: "test2", user: test2, hostname: "example2.com", port: 1234, strict_host_key_checking: false} - - {host: "test3", user: test2, hostname: "example2.com", proxy_command: ssh -W %h:%p jumphost} - -# ================================================== -# Role: git -# ================================================== -git_global_name: John Doe -git_global_email: johndoe@test.com -git_global_signing_key: ~/.ssh/my-ssh-key.pub -git_global_present_configs: - - {name: user.email, value: "{{ git_global_email }}"} - - {name: user.signingkey, value: "{{ git_global_signing_key }}"} - - {name: pull.rebase, value: "true"} - - {name: commit.gpgsign, value: "true"} - - {name: tag.gpgsign, value: "true"} - - {name: init.defaultBranch, value: master} -git_global_absent_configs: - - gpg.format -git_clone_repos: - - {repo: https://github.com/cowsay-org/cowsay.git, dest: $HOME/git/cowsay} + - { host: "test1", user: test, hostname: "example.com", key_file: "~/.ssh/id_rsa" } + - { host: "test2", user: test2, hostname: "example2.com", port: 1234, strict_host_key_checking: false } + - { host: "test3", user: test2, hostname: "example2.com", proxy_command: ssh -W %h:%p jumphost } # ================================================== # Role: ide diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..88d8b9a --- /dev/null +++ b/uv.lock @@ -0,0 +1,526 @@ +version = 1 +revision = 3 +requires-python = ">=3.14" + +[[package]] +name = "ansible" +version = "13.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ansible-core" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/18/f13c9a462ef20893d30bd11c4089edee02b5ef1d31e1c2634da592732279/ansible-13.2.0.tar.gz", hash = "sha256:fac46e202d1020027341659918b39e588dd7c43cef26537d7ca7fe51c324fe31", size = 52000144, upload-time = "2025-12-30T16:42:37.456Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/dc/1b0d0c7b83a75e574b3b56d179f887396d135aad5ab15cc45e121bc4d307/ansible-13.2.0-py3-none-any.whl", hash = "sha256:8a7f536542d4b18118200b8eaba40aa62ed990bd0e7b7622368b656b67db056f", size = 54530175, upload-time = "2025-12-30T16:42:32.195Z" }, +] + +[[package]] +name = "ansible-compat" +version = "25.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ansible-core" }, + { name = "jsonschema" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "subprocess-tee" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/62/fb3aee58827ba6eacee561183b02b4a49cf4819f405df2409e23bad69a00/ansible_compat-25.12.0.tar.gz", hash = "sha256:d38a149c5f95bb0d529c3b5e5fa3200b26f5e938ec7c31d8bb01d87c1f634410", size = 193698, upload-time = "2025-12-02T15:36:37.831Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/cb/be446a7db8b7ade13ebea507a7075a1eb8fd900c068c12ceee537a06ae9f/ansible_compat-25.12.0-py3-none-any.whl", hash = "sha256:322ccc7002030a91588d1fdba21e934703d64736f0e483dc6afe8ecd93a75614", size = 27731, upload-time = "2025-12-02T15:36:36.072Z" }, +] + +[[package]] +name = "ansible-core" +version = "2.20.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "resolvelib" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3e/47/3543ea4e7ad65859c0043e9a03e1da99c57c22dfb29027e9951dd58e7524/ansible_core-2.20.1.tar.gz", hash = "sha256:a891e5f90cd46626778f0f3d545ec1115840c9b50e8adf25944c5e1748452106", size = 3313203, upload-time = "2025-12-09T16:49:57.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/8c/b9ef852c9322bffd08ef72c8d6737922af810920e8ebd6ae5c9c5ac1f623/ansible_core-2.20.1-py3-none-any.whl", hash = "sha256:2a66825b4a53f130b62515e7e2a3d811d544b19b6e8a22d9ef88c55896384cb3", size = 2412350, upload-time = "2025-12-09T16:49:55.562Z" }, +] + +[[package]] +name = "ansible-lint" +version = "26.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ansible-compat" }, + { name = "ansible-core" }, + { name = "black" }, + { name = "cffi" }, + { name = "cryptography" }, + { name = "distro" }, + { name = "filelock" }, + { name = "jsonschema" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "ruamel-yaml" }, + { name = "subprocess-tee" }, + { name = "wcmatch" }, + { name = "yamllint" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/e6/40ae7444a618e6c47d4a9e59ab825bddb41802f980c9bf3f904b8dc1eea9/ansible_lint-26.1.1.tar.gz", hash = "sha256:7415b1b96ad7d7a453eb7e2afc74644e291dbcd8326f230f0216145fdee29a67", size = 728559, upload-time = "2026-01-16T03:45:31.051Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/df/e8c0d664d0e720af0229de98ea0931b91cdf309cca16bbd27f59547a7a19/ansible_lint-26.1.1-py3-none-any.whl", hash = "sha256:1ee6f472f1516fbbc86784f0046a9042cbcded87dba4e31e4611f6b62103f340", size = 324941, upload-time = "2026-01-16T03:45:29.039Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "black" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/13/88/560b11e521c522440af991d46848a2bde64b5f7202ec14e1f46f9509d328/black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58", size = 658785, upload-time = "2026-01-18T04:50:11.993Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/83/be35a175aacfce4b05584ac415fd317dd6c24e93a0af2dcedce0f686f5d8/black-26.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9dc8c71656a79ca49b8d3e2ce8103210c9481c57798b48deeb3a8bb02db5f115", size = 1871864, upload-time = "2026-01-18T04:59:47.586Z" }, + { url = "https://files.pythonhosted.org/packages/a5/f5/d33696c099450b1274d925a42b7a030cd3ea1f56d72e5ca8bbed5f52759c/black-26.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b22b3810451abe359a964cc88121d57f7bce482b53a066de0f1584988ca36e79", size = 1701009, upload-time = "2026-01-18T04:59:49.443Z" }, + { url = "https://files.pythonhosted.org/packages/1b/87/670dd888c537acb53a863bc15abbd85b22b429237d9de1b77c0ed6b79c42/black-26.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53c62883b3f999f14e5d30b5a79bd437236658ad45b2f853906c7cbe79de00af", size = 1767806, upload-time = "2026-01-18T04:59:50.769Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9c/cd3deb79bfec5bcf30f9d2100ffeec63eecce826eb63e3961708b9431ff1/black-26.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:f016baaadc423dc960cdddf9acae679e71ee02c4c341f78f3179d7e4819c095f", size = 1433217, upload-time = "2026-01-18T04:59:52.218Z" }, + { url = "https://files.pythonhosted.org/packages/4e/29/f3be41a1cf502a283506f40f5d27203249d181f7a1a2abce1c6ce188035a/black-26.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:66912475200b67ef5a0ab665011964bf924745103f51977a78b4fb92a9fc1bf0", size = 1245773, upload-time = "2026-01-18T04:59:54.457Z" }, + { url = "https://files.pythonhosted.org/packages/e4/3d/51bdb3ecbfadfaf825ec0c75e1de6077422b4afa2091c6c9ba34fbfc0c2d/black-26.1.0-py3-none-any.whl", hash = "sha256:1054e8e47ebd686e078c0bb0eaf31e6ce69c966058d122f2c0c950311f9f3ede", size = 204010, upload-time = "2026-01-18T04:50:09.978Z" }, +] + +[[package]] +name = "bracex" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "cryptography" +version = "46.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" }, + { url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" }, + { url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" }, + { url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" }, + { url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" }, + { url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" }, + { url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" }, + { url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" }, + { url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" }, + { url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" }, + { url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" }, + { url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" }, + { url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" }, + { url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" }, + { url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" }, + { url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" }, + { url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" }, + { url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" }, + { url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" }, + { url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" }, + { url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" }, + { url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" }, + { url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" }, + { url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" }, + { url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" }, + { url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" }, + { url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" }, + { url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" }, + { url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" }, + { url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" }, +] + +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, +] + +[[package]] +name = "filelock" +version = "3.20.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "packaging" +version = "26.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, +] + +[[package]] +name = "pathspec" +version = "1.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/b2/bb8e495d5262bfec41ab5cb18f522f1012933347fb5d9e62452d446baca2/pathspec-1.0.3.tar.gz", hash = "sha256:bac5cf97ae2c2876e2d25ebb15078eb04d76e4b98921ee31c6f85ade8b59444d", size = 130841, upload-time = "2026-01-09T15:46:46.009Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/2b/121e912bd60eebd623f873fd090de0e84f322972ab25a7f9044c056804ed/pathspec-1.0.3-py3-none-any.whl", hash = "sha256:e80767021c1cc524aa3fb14bedda9c34406591343cc42797b386ce7b9354fb6c", size = 55021, upload-time = "2026-01-09T15:46:44.652Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pytokens" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e5/16/4b9cfd90d55e66ffdb277d7ebe3bc25250c2311336ec3fc73b2673c794d5/pytokens-0.4.0.tar.gz", hash = "sha256:6b0b03e6ea7c9f9d47c5c61164b69ad30f4f0d70a5d9fe7eac4d19f24f77af2d", size = 15039, upload-time = "2026-01-19T07:59:50.623Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/f1/d07e6209f18ef378fc2ae9dee8d1dfe91fd2447c2e2dbfa32867b6dd30cf/pytokens-0.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0d7374c917197106d3c4761374718bc55ea2e9ac0fb94171588ef5840ee1f016", size = 159968, upload-time = "2026-01-19T07:59:23.07Z" }, + { url = "https://files.pythonhosted.org/packages/0a/73/0eb111400abd382a04f253b269819db9fcc748aa40748441cebdcb6d068f/pytokens-0.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cd3fa1caf9e47a72ee134a29ca6b5bea84712724bba165d6628baa190c6ea5b", size = 253373, upload-time = "2026-01-19T07:59:24.381Z" }, + { url = "https://files.pythonhosted.org/packages/bd/8d/9e4e2fdb5bcaba679e54afcc304e9f13f488eb4d626e6b613f9553e03dbd/pytokens-0.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c6986576b7b07fe9791854caa5347923005a80b079d45b63b0be70d50cce5f1", size = 267024, upload-time = "2026-01-19T07:59:25.74Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b7/e0a370321af2deb772cff14ff337e1140d1eac2c29a8876bfee995f486f0/pytokens-0.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9940f7c2e2f54fb1cb5fe17d0803c54da7a2bf62222704eb4217433664a186a7", size = 270912, upload-time = "2026-01-19T07:59:27.072Z" }, + { url = "https://files.pythonhosted.org/packages/7c/54/4348f916c440d4c3e68b53b4ed0e66b292d119e799fa07afa159566dcc86/pytokens-0.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:54691cf8f299e7efabcc25adb4ce715d3cef1491e1c930eaf555182f898ef66a", size = 103836, upload-time = "2026-01-19T07:59:28.112Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f8/a693c0cfa9c783a2a8c4500b7b2a8bab420f8ca4f2d496153226bf1c12e3/pytokens-0.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:94ff5db97a0d3cd7248a5b07ba2167bd3edc1db92f76c6db00137bbaf068ddf8", size = 167643, upload-time = "2026-01-19T07:59:29.292Z" }, + { url = "https://files.pythonhosted.org/packages/c0/dd/a64eb1e9f3ec277b69b33ef1b40ffbcc8f0a3bafcde120997efc7bdefebf/pytokens-0.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d0dd6261cd9cc95fae1227b1b6ebee023a5fd4a4b6330b071c73a516f5f59b63", size = 289553, upload-time = "2026-01-19T07:59:30.537Z" }, + { url = "https://files.pythonhosted.org/packages/df/22/06c1079d93dbc3bca5d013e1795f3d8b9ed6c87290acd6913c1c526a6bb2/pytokens-0.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cdca8159df407dbd669145af4171a0d967006e0be25f3b520896bc7068f02c4", size = 302490, upload-time = "2026-01-19T07:59:32.352Z" }, + { url = "https://files.pythonhosted.org/packages/8d/de/a6f5e43115b4fbf4b93aa87d6c83c79932cdb084f9711daae04549e1e4ad/pytokens-0.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4b5770abeb2a24347380a1164a558f0ebe06e98aedbd54c45f7929527a5fb26e", size = 305652, upload-time = "2026-01-19T07:59:33.685Z" }, + { url = "https://files.pythonhosted.org/packages/ab/3d/c136e057cb622e36e0c3ff7a8aaa19ff9720050c4078235691da885fe6ee/pytokens-0.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:74500d72c561dad14c037a9e86a657afd63e277dd5a3bb7570932ab7a3b12551", size = 115472, upload-time = "2026-01-19T07:59:34.734Z" }, + { url = "https://files.pythonhosted.org/packages/7c/3c/6941a82f4f130af6e1c68c076b6789069ef10c04559bd4733650f902fd3b/pytokens-0.4.0-py3-none-any.whl", hash = "sha256:0508d11b4de157ee12063901603be87fb0253e8f4cb9305eb168b1202ab92068", size = 13224, upload-time = "2026-01-19T07:59:49.822Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "ready-set-develop" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "ansible" }, +] + +[package.dev-dependencies] +dev = [ + { name = "ansible-lint" }, + { name = "yamllint" }, +] + +[package.metadata] +requires-dist = [{ name = "ansible", specifier = ">=13.2,<14" }] + +[package.metadata.requires-dev] +dev = [ + { name = "ansible-lint", specifier = ">=26.1,<27" }, + { name = "yamllint", specifier = ">=1.38,<2" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "resolvelib" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/14/4669927e06631070edb968c78fdb6ce8992e27c9ab2cde4b3993e22ac7af/resolvelib-1.2.1.tar.gz", hash = "sha256:7d08a2022f6e16ce405d60b68c390f054efcfd0477d4b9bd019cc941c28fad1c", size = 24575, upload-time = "2025-10-11T01:07:44.582Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/23/c941a0d0353681ca138489983c4309e0f5095dfd902e1357004f2357ddf2/resolvelib-1.2.1-py3-none-any.whl", hash = "sha256:fb06b66c8da04172d9e72a21d7d06186d8919e32ae5ab5cdf5b9d920be805ac2", size = 18737, upload-time = "2025-10-11T01:07:43.081Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, +] + +[[package]] +name = "ruamel-yaml" +version = "0.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/3b/ebda527b56beb90cb7652cb1c7e4f91f48649fbcd8d2eb2fb6e77cd3329b/ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993", size = 142709, upload-time = "2026-01-02T16:50:31.84Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/0c/51f6841f1d84f404f92463fc2b1ba0da357ca1e3db6b7fbda26956c3b82a/ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93", size = 118102, upload-time = "2026-01-02T16:50:29.201Z" }, +] + +[[package]] +name = "subprocess-tee" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/22/991efbf35bc811dfe7edcd749253f0931d2d4838cf55176132633e1c82a7/subprocess_tee-0.4.2.tar.gz", hash = "sha256:91b2b4da3aae9a7088d84acaf2ea0abee3f4fd9c0d2eae69a9b9122a71476590", size = 14951, upload-time = "2024-06-17T19:51:51.249Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/ab/e3a3be062cd544b2803760ff707dee38f0b1cb5685b2446de0ec19be28d9/subprocess_tee-0.4.2-py3-none-any.whl", hash = "sha256:21942e976715af4a19a526918adb03a8a27a8edab959f2d075b777e3d78f532d", size = 5249, upload-time = "2024-06-17T19:51:15.949Z" }, +] + +[[package]] +name = "wcmatch" +version = "10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bracex" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/3e/c0bdc27cf06f4e47680bd5803a07cb3dfd17de84cde92dd217dcb9e05253/wcmatch-10.1.tar.gz", hash = "sha256:f11f94208c8c8484a16f4f48638a85d771d9513f4ab3f37595978801cb9465af", size = 117421, upload-time = "2025-06-22T19:14:02.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl", hash = "sha256:5848ace7dbb0476e5e55ab63c6bbd529745089343427caa5537f230cc01beb8a", size = 39854, upload-time = "2025-06-22T19:14:00.978Z" }, +] + +[[package]] +name = "yamllint" +version = "1.38.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pathspec" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/a0/8fc2d68e132cf918f18273fdc8a1b8432b60d75ac12fdae4b0ef5c9d2e8d/yamllint-1.38.0.tar.gz", hash = "sha256:09e5f29531daab93366bb061e76019d5e91691ef0a40328f04c927387d1d364d", size = 142446, upload-time = "2026-01-13T07:47:53.276Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/92/aed08e68de6e6a3d7c2328ce7388072cd6affc26e2917197430b646aed02/yamllint-1.38.0-py3-none-any.whl", hash = "sha256:fc394a5b3be980a4062607b8fdddc0843f4fa394152b6da21722f5d59013c220", size = 68940, upload-time = "2026-01-13T07:47:51.343Z" }, +]