An open API service indexing awesome lists of open source software.

https://github.com/omercnet/doh1


https://github.com/omercnet/doh1

Last synced: 5 months ago
JSON representation

Awesome Lists containing this project

README

          

# 🪖 דו"ח 1 - IDF Daily Attendance Automation

Automated daily attendance form submission for IDF reservists using Playwright.

> **📋 This is a template repo!** Click [**Use this template**](https://github.com/omercnet/doh1/generate) to create your own.

```
┌─────────────────────────────────────────────────────────────┐
│ 🇮🇱 🇮🇱 │
│ ╔═══╗ ╔═══╗ ╔═╗ ╔═╗ ╔═══╗ │
│ ║ ║ ║ ║ ║ ║ ║ ║ ║ │
│ ║ ║ ║ ║ ║ ╚═╝ ║ ║ │
│ ║ ║ ║ ║ ║ ╔═╗ ║ ║ │
│ ╚═══╝ ╚═══╝ ╚═╝ ╚═╝ ║ │
│ │
│ ⭐ Automate your מעקב נוכחות יומי ⭐ │
│ │
└─────────────────────────────────────────────────────────────┘
```

## What it does

- 🔐 Logs into miluim.idf.il with Azure AD authentication
- 📞 Handles MFA via phone call (you approve, it continues)
- 📝 Submits daily attendance form (דו"ח 1)
- ✅ Detects if already submitted today and skips gracefully
- 💾 Caches auth session to skip MFA on subsequent runs
- ⏰ Runs on schedule via GitHub Actions
- 📢 Notifies via Slack on success/failure

## 🛠️ Local Development

### Prerequisites

- [mise](https://mise.jdx.dev/) - Runtime version manager
- [fnox](https://github.com/jdx/fnox) - Secret management

### Setup

1. **Install dependencies:**

```bash
mise install
pnpm install
npx playwright install chromium
```

2. **Configure secrets:**

```bash
# Generate an age key if you don't have one
age-keygen -o ~/.config/fnox/age.txt

# Copy the PUBLIC key (starts with age1...) for fnox.toml
cat ~/.config/fnox/age.txt | grep "public key"

# Create your fnox.toml
cp fnox.toml.example fnox.toml
# Edit fnox.toml - replace YOUR_AGE_PUBLIC_KEY with your public key

# Add your secrets
fnox set IDF_ID
fnox set IDF_PASSWORD
```

3. **Run locally (headed):**

```bash
fnox run -- pnpm test:headed
```

When MFA triggers, approve the phone call.

4. **Run headless:**
```bash
fnox run -- pnpm test
```

## 🚀 GitHub Actions Setup

### Required Secrets

| Secret | Description |
| -------------------- | ------------------------------------------------ |
| `IDF_ID` | Your ID number (ת.ז.) |
| `IDF_PASSWORD` | Your Azure AD password |
| `TS_OAUTH_CLIENT_ID` | Tailscale OAuth client ID |
| `TS_OAUTH_SECRET` | Tailscale OAuth client secret |
| `TS_EXIT_NODE` | Tailscale exit node hostname (your home machine) |

### Optional Secrets

| Secret | Description |
| ------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `AGE_RECIPIENT` | Age public key (starts with `age1...`) for encrypting failed test artifacts. Get it from `~/.config/fnox/age.txt` |
| `SLACK_WEBHOOK_URL` | Slack webhook for notifications |

### Tailscale Setup

The IDF portal blocks access from cloud IPs (Azure AD Conditional Access). CI routes traffic through your home network via Tailscale.

1. **Enable exit node on your home machine:**

```bash
sudo tailscale up --advertise-exit-node
```

Then approve it in the [Tailscale admin console](https://login.tailscale.com/admin/machines).

2. **Add ACL tag for CI nodes:**
Add to your [Tailscale ACL policy](https://login.tailscale.com/admin/acls):

```json
"tagOwners": {
"tag:ci": ["autogroup:admin"]
}
```

3. **Create OAuth client:**
- Go to [Tailscale Settings → OAuth clients](https://login.tailscale.com/admin/settings/oauth)
- Click "Generate OAuth client"
- Add `tag:ci` tag
- Scopes: `auth_keys` (writable)
- Copy the **Client ID** and **Client Secret**

4. **Add GitHub repository secrets:**
- Go to repo Settings → Secrets and variables → Actions → Secrets
- Add `TS_OAUTH_CLIENT_ID` with the client ID (without `api.tailscale.com/` prefix)
- Add `TS_OAUTH_SECRET` with the client secret
- Add `TS_EXIT_NODE` with your home machine's Tailscale hostname

> **Note:** The age private key stays local in `~/.config/fnox/age.txt`. Only the public key goes to GitHub for encrypting artifacts you can decrypt locally.

### Schedule

Runs automatically Sunday-Thursday at 9:00 AM Israel time.

To run manually: Actions → Daily Attendance Form → Run workflow

### First Run

The first CI run (or after session expires) will require MFA:

1. Trigger the workflow
2. Wait for the phone call
3. Approve MFA
4. Session gets cached for future runs

## 🔧 Troubleshooting

### Decrypting Failed Test Artifacts

If a run fails, traces are encrypted and uploaded as artifacts.

```bash
# Download the artifact, then:
age -d -i ~/.config/fnox/age.txt test-results.tar.gz.age > test-results.tar.gz
tar -xzf test-results.tar.gz
npx playwright show-trace test-results/*/trace.zip
```

### Force Re-authentication

If the cached session is stale:

1. Go to Actions → Daily Attendance Form
2. Run workflow with "Force new login" checked

### Common Issues

| Issue | Solution |
| --------------------- | ---------------------------------------------------------- |
| MFA timeout | Be ready to approve the call within 3 minutes |
| Session expired | Force re-login via workflow dispatch |
| Already submitted | This is fine! Test passes with "Already submitted today ✓" |
| Selectors changed | Update selectors in `src/form/fill-attendance.ts` |
| "Cannot access" error | Azure AD blocking cloud IPs - check Tailscale exit node |
| Tailscale timeout | Ensure home machine is online and exit node is approved |

## 📁 Project Structure

```
src/
├── config.ts # Environment config
├── auth/
│ └── login.ts # Azure AD + MFA login flow
├── form/
│ └── fill-attendance.ts # Form submission logic
└── utils/
└── notify.ts # Slack/email notifications

tests/
└── test-1.spec.ts # Main test orchestrator

.github/workflows/
└── playwright.yml # CI workflow
```

## 📜 License

ISC

---

🎖️ _Made for מילואימניקים by מילואימניקים_ 🎖️