@dotdotdash/afterhours 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +189 -0
- package/dist/chunk-UC2WX3XO.js +56 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2920 -0
- package/dist/report-2P72ZPRH.js +10 -0
- package/package.json +62 -0
- package/templates/config.yml +90 -0
- package/templates/docker-cron/Dockerfile +23 -0
- package/templates/docker-cron/README.md +31 -0
- package/templates/docker-cron/crontab +3 -0
- package/templates/github-actions.yml +50 -0
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dotdotdash/afterhours",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Autonomous schedulable system that maintains web codebases",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"maintenance",
|
|
8
|
+
"automation",
|
|
9
|
+
"dependency-audit",
|
|
10
|
+
"llm",
|
|
11
|
+
"devops"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"bin": {
|
|
15
|
+
"afterhours": "dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"exports": {
|
|
18
|
+
".": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsx src/index.ts",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"lint": "eslint src",
|
|
31
|
+
"format": "prettier --write .",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest",
|
|
34
|
+
"prepublishOnly": "npm run typecheck && npm run lint && npm test && npm run build"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"templates",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"commander": "^12.1.0",
|
|
43
|
+
"dotenv": "^16.4.1",
|
|
44
|
+
"nodemailer": "^9.0.1",
|
|
45
|
+
"simple-git": "^3.1.0",
|
|
46
|
+
"yaml": "^2.6.0",
|
|
47
|
+
"zod": "^3.24.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^22.10.0",
|
|
51
|
+
"@types/nodemailer": "^8.0.1",
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
53
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
54
|
+
"eslint": "^9.0.0",
|
|
55
|
+
"eslint-config-prettier": "^10.0.0",
|
|
56
|
+
"prettier": "^3.0.0",
|
|
57
|
+
"tsup": "^8.1.0",
|
|
58
|
+
"tsx": "^4.19.0",
|
|
59
|
+
"typescript": "^5.7.0",
|
|
60
|
+
"vitest": "^2.1.0"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
|
|
3
|
+
project:
|
|
4
|
+
type: auto # auto | website | server | library
|
|
5
|
+
packageManager: auto # auto | npm | pnpm | yarn | bun
|
|
6
|
+
build: auto # auto-detected, or an explicit command like "npm run build"
|
|
7
|
+
test: auto # auto | none | explicit command
|
|
8
|
+
run: auto # smoke-run command; ignored for library
|
|
9
|
+
# runHealthcheck:
|
|
10
|
+
# type: http # http | log | exit
|
|
11
|
+
# url: http://localhost:3000/health
|
|
12
|
+
# timeoutSec: 30
|
|
13
|
+
|
|
14
|
+
sandbox:
|
|
15
|
+
mode: host # docker | host (prefer docker in CI, host for local)
|
|
16
|
+
image: node:20-bookworm # used when mode=docker
|
|
17
|
+
network: bridge # bridge | none
|
|
18
|
+
|
|
19
|
+
schedule:
|
|
20
|
+
cron: "0 3 * * 1" # every Monday at 3 AM (informational; consumed by adapters)
|
|
21
|
+
|
|
22
|
+
platform:
|
|
23
|
+
provider: github # github | gitlab | azure | codecommit | gcsr | generic
|
|
24
|
+
remote: origin
|
|
25
|
+
baseBranch: main
|
|
26
|
+
branchPrefix: afterhours/
|
|
27
|
+
autoMerge: false # if true, squash-merges when all tasks succeed
|
|
28
|
+
mergeStrategy: squash # squash | merge | rebase
|
|
29
|
+
|
|
30
|
+
llm:
|
|
31
|
+
provider: anthropic # anthropic | openai | ollama | github-models | gemini | copilot
|
|
32
|
+
model: claude-sonnet-4-5
|
|
33
|
+
apiKeyEnv: ANTHROPIC_API_KEY # name of env var holding the API key
|
|
34
|
+
# baseUrlEnv: # optional override (for Ollama, proxies, etc.)
|
|
35
|
+
maxTokens: 8000
|
|
36
|
+
# To use a GitHub Copilot seat for agentic work instead of a direct LLM API key:
|
|
37
|
+
# provider: copilot
|
|
38
|
+
# model: gpt-4o # any Copilot-supported chat model
|
|
39
|
+
# apiKeyEnv: COPILOT_TOKEN # a GitHub token for a Copilot-licensed account (can be a
|
|
40
|
+
# # different account than platform.provider's repo-access token,
|
|
41
|
+
# # e.g. an org member's Copilot seat working on a client-owned repo)
|
|
42
|
+
|
|
43
|
+
agent:
|
|
44
|
+
mode: builtin # builtin | external
|
|
45
|
+
# external:
|
|
46
|
+
# cli: aider # aider | claude | codex
|
|
47
|
+
# extraArgs: []
|
|
48
|
+
|
|
49
|
+
tasks:
|
|
50
|
+
dependencyAudit:
|
|
51
|
+
enabled: true
|
|
52
|
+
securityOnly: false # true = only upgrade vulnerable/deprecated deps
|
|
53
|
+
allowMajor: false # allow major-version bumps
|
|
54
|
+
notifyOnFailure: true
|
|
55
|
+
codeOptimization:
|
|
56
|
+
enabled: true
|
|
57
|
+
priorityThreshold: high # low | medium | high | severe
|
|
58
|
+
notifyOnComplete: false
|
|
59
|
+
deployment:
|
|
60
|
+
enabled: false # enable only when ready to deploy
|
|
61
|
+
targets: []
|
|
62
|
+
# Example targets:
|
|
63
|
+
# - type: npm
|
|
64
|
+
# tokenEnv: NPM_TOKEN
|
|
65
|
+
# access: public
|
|
66
|
+
# - type: github-release
|
|
67
|
+
# tagFrom: package.json
|
|
68
|
+
# generateNotes: true
|
|
69
|
+
issueTriage:
|
|
70
|
+
enabled: false # requires a platform token with issue read/write access (e.g. GITHUB_TOKEN)
|
|
71
|
+
allowedAuthors: # usernames allowed to trigger automated issue resolution, or ["*"] for anyone
|
|
72
|
+
- "*"
|
|
73
|
+
notifyOnFailure: true
|
|
74
|
+
|
|
75
|
+
notifications:
|
|
76
|
+
- type: github # comments on the PR; opens an issue on failure
|
|
77
|
+
# - type: email
|
|
78
|
+
# toEnv: NOTIFY_EMAIL_TO
|
|
79
|
+
# fromEnv: NOTIFY_EMAIL_FROM
|
|
80
|
+
# smtp:
|
|
81
|
+
# hostEnv: SMTP_HOST
|
|
82
|
+
# portEnv: SMTP_PORT
|
|
83
|
+
# userEnv: SMTP_USER
|
|
84
|
+
# passEnv: SMTP_PASS
|
|
85
|
+
# - type: webhook
|
|
86
|
+
# urlEnv: AFTERHOURS_WEBHOOK_URL
|
|
87
|
+
|
|
88
|
+
contacts:
|
|
89
|
+
- name: Maintainer
|
|
90
|
+
emailEnv: MAINTAINER_EMAIL
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
FROM node:20-bookworm-slim
|
|
2
|
+
|
|
3
|
+
# Install Docker CLI so afterhours can use the Docker sandbox
|
|
4
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
5
|
+
docker.io \
|
|
6
|
+
git \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
# Install afterhours globally
|
|
10
|
+
RUN npm install -g afterhours
|
|
11
|
+
|
|
12
|
+
# Mount repo at /workspace
|
|
13
|
+
WORKDIR /workspace
|
|
14
|
+
|
|
15
|
+
# The crontab schedules "afterhours run" — copy it in and install
|
|
16
|
+
COPY crontab /etc/cron.d/afterhours
|
|
17
|
+
RUN chmod 0644 /etc/cron.d/afterhours && crontab /etc/cron.d/afterhours
|
|
18
|
+
|
|
19
|
+
# Secrets are passed via --env-file when running the container:
|
|
20
|
+
# docker run --env-file .env -v /your/repo:/workspace afterhours-cron
|
|
21
|
+
# Never bake secrets into the image.
|
|
22
|
+
|
|
23
|
+
CMD ["cron", "-f"]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# afterhours Docker + cron adapter
|
|
2
|
+
|
|
3
|
+
This adapter runs `afterhours run` inside a Docker container on a cron schedule.
|
|
4
|
+
It is suitable for any host that can run Docker (VPS, EC2, bare metal, Raspberry Pi, etc.).
|
|
5
|
+
|
|
6
|
+
## Quick start
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# 1. Build the image
|
|
10
|
+
docker build -t afterhours-cron .
|
|
11
|
+
|
|
12
|
+
# 2. Create a .env file with your secrets (see .env.example at the repo root)
|
|
13
|
+
cp /path/to/afterhours/.env.example .env
|
|
14
|
+
# Edit .env with real values
|
|
15
|
+
|
|
16
|
+
# 3. Run the container, mounting your target repo
|
|
17
|
+
docker run -d \
|
|
18
|
+
--name afterhours-cron \
|
|
19
|
+
--env-file .env \
|
|
20
|
+
-v /path/to/your/repo:/workspace \
|
|
21
|
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
22
|
+
afterhours-cron
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Notes
|
|
26
|
+
|
|
27
|
+
- Secrets are passed via `--env-file`, never baked into the image.
|
|
28
|
+
- The Docker socket mount (`/var/run/docker.sock`) is only needed if you use `sandbox.mode: docker`.
|
|
29
|
+
For `sandbox.mode: host`, omit it.
|
|
30
|
+
- Adjust the cron schedule in `crontab` to match `.afterhours/config.yml`.
|
|
31
|
+
- View logs: `docker logs afterhours-cron`
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: afterhours
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 3 * * 1" # every Monday at 3 AM UTC; adjust to match .afterhours/config.yml
|
|
6
|
+
workflow_dispatch: # allow manual trigger from GitHub Actions UI
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
run:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
with:
|
|
14
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
15
|
+
fetch-depth: 0
|
|
16
|
+
|
|
17
|
+
- uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: 20
|
|
20
|
+
|
|
21
|
+
- name: Install afterhours
|
|
22
|
+
run: npm install -g afterhours || npx afterhours --version
|
|
23
|
+
|
|
24
|
+
- name: Run afterhours
|
|
25
|
+
run: npx afterhours run
|
|
26
|
+
env:
|
|
27
|
+
# Platform token — map your repo secret to the env var afterhours expects
|
|
28
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
29
|
+
|
|
30
|
+
# LLM provider — choose one and map the right secret
|
|
31
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
32
|
+
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
33
|
+
|
|
34
|
+
# Notifications (optional)
|
|
35
|
+
NOTIFY_EMAIL_TO: ${{ secrets.NOTIFY_EMAIL_TO }}
|
|
36
|
+
NOTIFY_EMAIL_FROM: ${{ secrets.NOTIFY_EMAIL_FROM }}
|
|
37
|
+
SMTP_HOST: ${{ secrets.SMTP_HOST }}
|
|
38
|
+
SMTP_PORT: ${{ secrets.SMTP_PORT }}
|
|
39
|
+
SMTP_USER: ${{ secrets.SMTP_USER }}
|
|
40
|
+
SMTP_PASS: ${{ secrets.SMTP_PASS }}
|
|
41
|
+
AFTERHOURS_WEBHOOK_URL: ${{ secrets.AFTERHOURS_WEBHOOK_URL }}
|
|
42
|
+
|
|
43
|
+
# Deployment (optional)
|
|
44
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
45
|
+
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
|
46
|
+
REGISTRY_PASS: ${{ secrets.REGISTRY_PASS }}
|
|
47
|
+
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
48
|
+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
49
|
+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
|
50
|
+
GIT_SHA: ${{ github.sha }}
|