Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/review-submission.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Review Subdomain Submission

on:
pull_request_target:
types:
[
opened,
synchronize,
reopened,
edited,
ready_for_review,
converted_to_draft,
]
branches: [main]
workflow_dispatch:
inputs:
pr_number:
description: PR number to check and send an email for
required: true
type: string

permissions: {}

concurrency:
group: submission-review-${{ github.event.pull_request.number || inputs.pr_number }}
cancel-in-progress: false

jobs:
review:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
pull-requests: write
statuses: write
steps:
# SECURITY: run trusted base code only. Never check out or execute PR code here.
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
ref: ${{ github.event.pull_request.base.sha || github.sha }}
persist-credentials: false
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
with:
node-version: "22"
- name: Validate, comment, and notify
run: node scripts/review-pr.js
env:
GITHUB_TOKEN: ${{ github.token }}
REVIEWER_LOGIN: maoawa
INPUT_PR_NUMBER: ${{ inputs.pr_number }}
REVIEW_SERVICE_URL: ${{ vars.REVIEW_SERVICE_URL }}
REVIEW_WEBHOOK_SECRET: ${{ secrets.REVIEW_WEBHOOK_SECRET }}
25 changes: 25 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Test Review Automation
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
with:
persist-credentials: false
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
with:
node-version: "22"
- run: npm test
- run: npm ci
working-directory: review-service
- run: npm test
working-directory: review-service
- run: npm run check
working-directory: review-service
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/node_modules

package-lock.json
package-lock.json
# Local service state and credentials
**/node_modules/
**/.wrangler/
**/.dev.vars*
**/.env*
!**/.dev.vars.example
!review-service/package-lock.json
48 changes: 48 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Submission rules / 提交规范

For a normal subdomain request, submit a PR to `main` with a short description of your website. The automated reviewer comments on every submission and reports the `submission-format` status. Passing format checks does not approve the website's content.

普通域名申请请向 `main` 提交 PR,并简要说明网站用途。机器人会检查格式并留言;检查通过不代表内容审核通过。

## Quick start

Copy the README's JSON template, replace the username/domain/DNS target, save it as `records/<domain>.json`, and open a PR describing your website in one sentence. The contact email is optional. Keep `proxied` as `false` if you are unsure. The bot will explain any problem and you can edit the same PR to fix it.

复制 README 模板,填写用户名、域名和 DNS 目标,保存为 `records/<域名>.json`,再提交 PR 并用一句话介绍网站即可。邮箱可不填;不确定代理设置时保留 `false`。机器人会提示问题,修改同一个 PR 即可。

## Detailed checks (reference)

- Change 1–10 files, only directly under `records/`, named `<domain>.json`. Automated approval accepts additions and modifications; deletions, renames, and maintenance changes require manual review.
- Each file must be a regular, non-executable UTF-8 JSON object, at most 32 KiB.
- Required fields: `owner`, `domain`, `records`, `proxied`. Optional field: `ttl`. Other fields are rejected to catch typos.
- `owner` contains a valid `username` and optionally `email`. The username must match the PR author, case-insensitively. Email may be omitted or empty; supplied addresses are public.
- `domain` must equal the filename without `.json`. Use lowercase DNS labels separated by dots, each no longer than 63 characters. A leading underscore supports verification labels. No wildcards, slashes, URLs, or trailing dot.
- `records` supports `A`, `AAAA`, `CNAME`, and `TXT`. Each value is a string or an array of 1–20 unique, non-empty strings. A/AAAA must be valid IP addresses. TXT values are at most 2,048 UTF-8 bytes each.
- `CNAME` takes exactly one hostname, without a URL, IP address, or self-reference. It cannot coexist with any other record type.
- `proxied` must be `true` or `false`. Set it to `false` for TXT-only configurations.
- Optional `ttl`: `1` (automatic) or an integer from `60` to `86400` seconds.
- Existing files, parent namespaces, and child namespaces remain reserved for their recorded owners. Delegated requests and ownership transfers need manual review.
- The current deployment script does not remove old record types or non-CNAME values. Such changes must be handled manually, including the DNS cleanup.

完整示例见 [中文说明](README.md) 或 [English README](README.en.md)。机器人只检查 PR 中变更的配置,不要求一次修复所有旧文件。

## Commit messages

Use a short, readable commit message. **GitHub's default message is fine; no special syntax is required.** For example:

```text
Create luna.json
Update luna.json
Add my personal blog
修正博客的 DNS 记录
```

The automated check only requires a non-empty first line of at most 200 characters, without control characters. Merge/sync commits are exempt. PRs with more than 100 commits need manual review.

**不需要学习特殊的提交格式,直接保留 GitHub 默认的提交说明即可。** 也可以用中文或其他语言简要说明变更。首行非空、不超过 200 字符,且不含控制字符即可。

## Review results

Fix the errors in the bot's comment and push again. Draft PRs are not emailed. A passing submission gets a maintainer review; it is never automatically merged just because the check passes.

For maintenance PRs, the format check deliberately fails with an explanation. A maintainer can review and merge them manually. **Do not make `submission-format` universally required** unless your branch rules provide a deliberate maintenance path.
78 changes: 78 additions & 0 deletions README.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# ฅ●ω●ฅ moe.page — Free, cute subdomains

[简体中文](README.md) | **English**

[![GitHub Actions Status](https://github.com/moepage/subdomain/actions/workflows/deploy.yml/badge.svg)](https://github.com/moepage/subdomain/actions)

> Get your own `.moe.page` subdomain with a pull request!

## ✨ What is this?

`moe.page` is a free, open, automated subdomain registration project. It gives your personal projects, blogs, homepages, and creative ideas a cute, memorable address.

## 🚀 How to apply

### Step 1: Fork this repository

Click **Fork** at the top right to copy this project to your GitHub account.

### Step 2: Add your domain file

1. Open the `records/` directory in your fork.
2. Select **Add file → Create new file**.
3. Name the file after the subdomain you want, with a `.json` extension. For `luna.moe.page`, use `luna.json`.

### Step 3: Fill in your configuration

Copy this template into the new file and replace the example values:

```json
{
"owner": {
"username": "your-github-username",
"email": "you@example.com"
},
"domain": "luna",
"records": {
"A": ["1.2.3.4"]
},
"proxied": false
}
```

- `owner`: Your GitHub username and optional contact email. Your username must match the PR author for automated review. Contact emails committed here are public; omit the field or leave it empty if you prefer.
- `domain`: Your requested subdomain. It must match the filename exactly, in lowercase.
- `records`: Your DNS records. `A` points to an IPv4 address, `AAAA` to an IPv6 address, `CNAME` to another hostname, and `TXT` contains text, often used for verification. Values may be a string or an array of strings. A CNAME must have exactly one target and cannot coexist with any other record type.
- `proxied`: Whether to enable the Cloudflare proxy (orange cloud). This must be a Boolean and applies only to A, AAAA, and CNAME records.
- `ttl` (optional): `1` for automatic TTL, or a number of seconds from `60` to `86400`. The deployment defaults to `120` and uses automatic TTL for proxied records.

Nested names such as `wiki.luna` and verification labels such as `_atproto.luna` are supported. Existing namespaces cannot be claimed by another owner through automated approval.

### Step 4: Submit a pull request

1. Keep GitHub’s default commit message (such as `Create luna.json`) or write a short description. No special commit format is required.
2. Return to your fork's homepage and select **Contribute → Open pull request**.
3. Target `main` and describe what your website does in the PR description.
4. The bot checks commit messages, JSON and DNS formats, and recorded ownership, then leaves or updates a comment explaining the result.
5. After the checks pass, a maintainer reviews the submission. When email review is configured, they receive the submission details and private links to approve and merge, or decline with a message.
6. Once merged, GitHub Actions deploys the DNS records. Check the deployment result; DNS changes can take time to become visible.

Automated checks validate format, not website safety. Maintenance changes, ownership transfers, record deletion, and changes requiring removal of old DNS values need manual review.

## 📜 Rules and limitations

1. Do not use these domains for illegal or inappropriate content, including phishing, spam, or adult content.
2. A CNAME cannot coexist with any other DNS record type.
3. We reserve the right to remove abused domains at any time.

## Maintainer setup

See [review automation setup](docs/review-automation.md) for the GitHub workflow, email delivery, and the small Cloudflare review service. The email links show details and require a deliberate button press before changing a PR.

## Acknowledgments

Thanks to [Cloudflare](https://www.cloudflare.com/) for its infrastructure and support.

---

Get started with your own `.moe.page` subdomain!
38 changes: 23 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# ฅ●ω●ฅ moe.page - 免费的萌系二级域名
# ฅ●ω●ฅ moe.page - 免费的萌系二级域名

[![GitHub Actions Status](https://github.com/zknmoe/moe.page-subdomains/actions/workflows/deploy.yml/badge.svg)](https://github.com/zknmoe/moe.page-subdomains/actions)
**简体中文** | [English](README.en.md)

[![GitHub Actions Status](https://github.com/moepage/subdomain/actions/workflows/deploy.yml/badge.svg)](https://github.com/moepage/subdomain/actions)

> 只需一个 Pull Request,即可拥有你的专属 `.moe.page` 域名!

Expand Down Expand Up @@ -32,39 +34,45 @@
},
"domain": "luna",
"records": {
"A": [
"1.2.3.4"
]
"A": ["1.2.3.4"]
},
"proxied": false
}
```

**字段说明:**
* `owner`: 你的个人信息。
* `domain`: 你想要的子域名(**必须**和文件名一致)。
* `records`: 你想设置的 DNS 记录。
* `A`: 指向一个 IPv4 地址。
* `CNAME`: 指向另一个域名。(**注意:CNAME 很霸道,如果用了它,就不能有其他任何记录!**)
* `TXT`: 可以是任何文本,常用于验证。
* `proxied`: 是否开启 Cloudflare 代理(橙色云朵),只对 A, AAAA, CNAME 记录有效。

- `owner`: 你的个人信息。
- `domain`: 你想要的子域名(**必须**和文件名一致)。
- `records`: 你想设置的 DNS 记录。
- `A`: 指向一个 IPv4 地址。
- `CNAME`: 指向另一个域名。(**注意:CNAME 很霸道,如果用了它,就不能有其他任何记录!**)
- `TXT`: 可以是任何文本,常用于验证。
- `proxied`: 是否开启 Cloudflare 代理(橙色云朵),只对 A, AAAA, CNAME 记录有效。

### 第四步:提交 Pull Request

1. 完成以上步骤后,回到你仓库的首页。
2. 你会看到一个提示,点击 `Contribute` -> `Open pull request`。
3. 简单描述一下你的网站是做什么的,然后提交 PR。
4. 等待机器人检查通过,以及管理员(就是我啦!)合并后,你的域名就生效啦!
4. 直接保留 GitHub 默认的提交说明(例如 `Create luna.json`),或简单描述变更即可,不需要特殊格式。详细检查规则见 [提交规范](CONTRIBUTING.md)。
5. 机器人会检查提交信息、JSON / DNS 格式与已有记录的归属,并在 PR 中更新检查结果。检查通过后,管理员可通过邮件中的私密审核页面查看详情、批准并合并,或填写原因拒绝。邮件功能需要先完成管理员配置。
6. 合并后,GitHub Actions 会部署 DNS 记录,请确认部署成功。

## 📜 规则与限制

1. 禁止用于任何非法、不当内容,包括但不限于钓鱼、垃圾邮件、成人内容等。
2. 请遵守 CNAME 的规则:如果你的记录里有 `CNAME`,就不能有其他任何类型的记录。
3. 我们保留随时删除被滥用的域名的权利。

## 管理员配置

请查看 [自动审核与邮件服务配置](docs/review-automation.md)。自动检查仅验证格式,不判断网站内容是否合规。涉及所有权转移、删除记录或清理旧 DNS 值的变更需要人工处理。`owner.email` 是可选字段,提交到公开仓库后所有人均可查看。

## 鸣谢

* 感谢 [Cloudflare](https://www.cloudflare.com/) 提供的强大支持。
- 感谢 [Cloudflare](https://www.cloudflare.com/) 提供的强大支持。

---
现在就开始吧!

现在就开始吧!
Loading
Loading