Reuse TOKEN_FOR_GITEA for the wiki when no wiki secret exists #49
@@ -27,5 +27,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITEA_API_URL: ${{ gitea.api_url }}
|
GITEA_API_URL: ${{ gitea.api_url }}
|
||||||
SOURCE_REPOSITORY: ${{ gitea.repository }}
|
SOURCE_REPOSITORY: ${{ gitea.repository }}
|
||||||
WIKI_CREDENTIALS: ${{ secrets.TOKEN_FOR_GITEA_WIKI }}
|
# TOKEN_FOR_GITEA_WIKI wins when it exists; otherwise TOKEN_FOR_GITEA is reused.
|
||||||
|
WIKI_CREDENTIALS: ${{ secrets.TOKEN_FOR_GITEA_WIKI || secrets.TOKEN_FOR_GITEA }}
|
||||||
run: python3 tools/publish_wiki.py
|
run: python3 tools/publish_wiki.py
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ It currently contains the Gitea workflow [`sync-github-metadata.yml`](.gitea/sco
|
|||||||
- Repository secrets:
|
- Repository secrets:
|
||||||
- `TOKEN_FOR_GITEA`: Gitea API token (plain string, or JSON with `GITEA_TOKEN`)
|
- `TOKEN_FOR_GITEA`: Gitea API token (plain string, or JSON with `GITEA_TOKEN`)
|
||||||
- `CREDENTIALS_FOR_GITHUB`: JSON object containing `GITHUB_PAT`, a GitHub personal access token allowed to edit the mirror repository
|
- `CREDENTIALS_FOR_GITHUB`: JSON object containing `GITHUB_PAT`, a GitHub personal access token allowed to edit the mirror repository
|
||||||
- `TOKEN_FOR_GITEA_WIKI` (only in this repository, for the **Publish wiki** workflow): Gitea token that can write the repository wiki
|
- `TOKEN_FOR_GITEA_WIKI` (optional, only in this repository, for the **Publish wiki** workflow): Gitea token that can write the repository wiki; when it is absent, `TOKEN_FOR_GITEA` is used and needs write access
|
||||||
|
|
||||||
## 🛠️ Setup
|
## 🛠️ Setup
|
||||||
|
|
||||||
|
|||||||
@@ -59,17 +59,19 @@ is ever printed.
|
|||||||
## Wiki publishing secret
|
## Wiki publishing secret
|
||||||
|
|
||||||
The workflow **Publish wiki** (this repository only) copies `wiki/` to the Gitea
|
The workflow **Publish wiki** (this repository only) copies `wiki/` to the Gitea
|
||||||
wiki when a change to `wiki/` is merged to `main`. It uses its own secret so
|
wiki when a change to `wiki/` is merged to `main`. It uses `TOKEN_FOR_GITEA_WIKI`
|
||||||
that the metadata sync tokens never get write access.
|
when that secret exists and otherwise reuses `TOKEN_FOR_GITEA`.
|
||||||
|
|
||||||
| Secret | Content | Used for |
|
| Secret | Content | Used for |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `TOKEN_FOR_GITEA_WIKI` | A bare token, a JSON string, or JSON with `GITEA_TOKEN` | Writing the wiki pages of this repository |
|
| `TOKEN_FOR_GITEA_WIKI` (optional) | A bare token, a JSON string, or JSON with `GITEA_TOKEN` | Writing the wiki pages of this repository |
|
||||||
|
|
||||||
- A Gitea personal access token with scope `write:repository`. Gitea has no
|
- The token that is used needs scope `write:repository`, and its user needs
|
||||||
wiki-only scope, so create the token for a dedicated user that has write
|
write access to this repository. Gitea has no wiki-only scope.
|
||||||
access to this repository only. S05 approves the scope and S03 stores the
|
- `TOKEN_FOR_GITEA` is documented above with `read:repository` only. Reusing it
|
||||||
secret.
|
for the wiki means raising its scope, which also gives the metadata sync
|
||||||
|
write access. A separate `TOKEN_FOR_GITEA_WIKI` for a dedicated user keeps
|
||||||
|
the sync token read-only. S05 decides which, and S03 stores the secret.
|
||||||
- Calls made: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`,
|
- Calls made: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`,
|
||||||
`GET`, `POST` and `PATCH /repos/{owner}/{repo}/wiki/...` and, for a page that
|
`GET`, `POST` and `PATCH /repos/{owner}/{repo}/wiki/...` and, for a page that
|
||||||
no longer exists in `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
no longer exists in `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ never starts, or stops before the step) is a **runner** problem.
|
|||||||
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | The JSON form needs a `GITEA_TOKEN` key |
|
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | The JSON form needs a `GITEA_TOKEN` key |
|
||||||
| `Could not determine the Gitea source repository.` | configuration | The run has no repository name; report as a defect |
|
| `Could not determine the Gitea source repository.` | configuration | The run has no repository name; report as a defect |
|
||||||
| `Expected at most one GitHub push mirror ... found N` | configuration | Keep one GitHub push mirror |
|
| `Expected at most one GitHub push mirror ... found N` | configuration | Keep one GitHub push mirror |
|
||||||
| `TOKEN_FOR_GITEA_WIKI is missing or empty.` | configuration | Wiki publishing only: add the secret (see [credentials.md](credentials.md)) |
|
| `No token for the wiki: set TOKEN_FOR_GITEA_WIKI, or TOKEN_FOR_GITEA.` | configuration | Wiki publishing only: add one of the secrets (see [credentials.md](credentials.md)) |
|
||||||
|
| `... HTTP 403 ...` while publishing the wiki | permissions | Wiki publishing only: the token needs `write:repository` and write access to this repository |
|
||||||
| `The wiki is not enabled on <repo>` | configuration | Wiki publishing only: enable the wiki in the repository settings |
|
| `The wiki is not enabled on <repo>` | configuration | Wiki publishing only: enable the wiki in the repository settings |
|
||||||
| `The wiki source directory ... has no Markdown pages` | configuration | Wiki publishing only: `wiki/` is empty or missing; nothing was changed |
|
| `The wiki source directory ... has no Markdown pages` | configuration | Wiki publishing only: `wiki/` is empty or missing; nothing was changed |
|
||||||
| `Could not determine the GitHub owner and repository ...` | configuration | The mirror address must look like `https://github.com/<owner>/<repo>.git` |
|
| `Could not determine the GitHub owner and repository ...` | configuration | The mirror address must look like `https://github.com/<owner>/<repo>.git` |
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class TestParseGiteaToken:
|
|||||||
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||||
publish_wiki.parse_gitea_token(raw)
|
publish_wiki.parse_gitea_token(raw)
|
||||||
assert caught.value.category == "configuration"
|
assert caught.value.category == "configuration"
|
||||||
assert "TOKEN_FOR_GITEA_WIKI" in str(caught.value)
|
assert "TOKEN_FOR_GITEA" in str(caught.value) or "wiki token" in str(caught.value)
|
||||||
|
|
||||||
|
|
||||||
class TestReadPages:
|
class TestReadPages:
|
||||||
@@ -172,7 +172,7 @@ class TestMain:
|
|||||||
monkeypatch.setenv("WIKI_CREDENTIALS", "")
|
monkeypatch.setenv("WIKI_CREDENTIALS", "")
|
||||||
gitea = FakeGitea()
|
gitea = FakeGitea()
|
||||||
|
|
||||||
with pytest.raises(publish_wiki.WorkflowError, match="TOKEN_FOR_GITEA_WIKI"):
|
with pytest.raises(publish_wiki.WorkflowError, match="No token for the wiki"):
|
||||||
run_main(monkeypatch, gitea)
|
run_main(monkeypatch, gitea)
|
||||||
|
|
||||||
assert gitea.calls == []
|
assert gitea.calls == []
|
||||||
@@ -191,6 +191,57 @@ class TestMain:
|
|||||||
assert gitea.wiki == {"Home": b64("keep me")}
|
assert gitea.wiki == {"Home": b64("keep me")}
|
||||||
|
|
||||||
|
|
||||||
|
class TestDescribeToken:
|
||||||
|
def test_recognises_a_gitea_token_shape(self):
|
||||||
|
description = publish_wiki.describe_token("a1b2c3d4e5" * 4)
|
||||||
|
assert "40 characters" in description
|
||||||
|
assert "looks like a Gitea token" in description
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("token", "expected"),
|
||||||
|
[
|
||||||
|
("*******", "only mask characters"),
|
||||||
|
("TOKEN_FOR_GITEA_WIKI=" + "a" * 40, "contains '='"),
|
||||||
|
('"' + "a" * 40 + '"', "quote character"),
|
||||||
|
("abc def", "whitespace"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_names_the_likely_mistake_without_echoing_the_token(self, token, expected):
|
||||||
|
description = publish_wiki.describe_token(token)
|
||||||
|
assert expected in description
|
||||||
|
assert token not in description
|
||||||
|
|
||||||
|
|
||||||
|
class TestRejectedToken:
|
||||||
|
def test_rejection_adds_the_token_shape_but_not_the_token(self, monkeypatch, environment):
|
||||||
|
monkeypatch.setenv("WIKI_CREDENTIALS", "*******")
|
||||||
|
|
||||||
|
def reject(url, method="GET", headers=None, body=None):
|
||||||
|
raise publish_wiki.WorkflowError("credentials", "Gitea rejected the token.")
|
||||||
|
|
||||||
|
monkeypatch.setattr(publish_wiki, "request_json", reject)
|
||||||
|
|
||||||
|
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||||
|
publish_wiki.main()
|
||||||
|
|
||||||
|
message = str(caught.value)
|
||||||
|
assert caught.value.category == "credentials"
|
||||||
|
assert "Token shape: 7 characters" in message
|
||||||
|
assert "only mask characters" in message
|
||||||
|
assert "*******" not in message.split("Token shape:")[0]
|
||||||
|
|
||||||
|
def test_other_categories_are_not_changed(self, monkeypatch, environment):
|
||||||
|
def forbid(url, method="GET", headers=None, body=None):
|
||||||
|
raise publish_wiki.WorkflowError("permissions", "Forbidden.")
|
||||||
|
|
||||||
|
monkeypatch.setattr(publish_wiki, "request_json", forbid)
|
||||||
|
|
||||||
|
with pytest.raises(publish_wiki.WorkflowError) as caught:
|
||||||
|
publish_wiki.main()
|
||||||
|
|
||||||
|
assert str(caught.value) == "[permissions] Forbidden."
|
||||||
|
|
||||||
|
|
||||||
class TestRequestJson:
|
class TestRequestJson:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def raise_http_error(monkeypatch, code, reason):
|
def raise_http_error(monkeypatch, code, reason):
|
||||||
@@ -258,5 +309,7 @@ class TestWorkflow:
|
|||||||
assert text.count("secrets.TOKEN_FOR_GITEA_WIKI") == 1
|
assert text.count("secrets.TOKEN_FOR_GITEA_WIKI") == 1
|
||||||
steps = document["jobs"]["publish-wiki"]["steps"]
|
steps = document["jobs"]["publish-wiki"]["steps"]
|
||||||
publish_step = steps[-1]
|
publish_step = steps[-1]
|
||||||
assert publish_step["env"]["WIKI_CREDENTIALS"] == "${{ secrets.TOKEN_FOR_GITEA_WIKI }}"
|
assert publish_step["env"]["WIKI_CREDENTIALS"] == (
|
||||||
|
"${{ secrets.TOKEN_FOR_GITEA_WIKI || secrets.TOKEN_FOR_GITEA }}"
|
||||||
|
)
|
||||||
assert "secrets" not in publish_step["run"]
|
assert "secrets" not in publish_step["run"]
|
||||||
|
|||||||
+36
-2
@@ -16,6 +16,7 @@ Exit codes: 0 published or nothing to do, 1 failed (message names a category).
|
|||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
@@ -43,6 +44,7 @@ class WorkflowError(RuntimeError):
|
|||||||
def __init__(self, category: str, message: str) -> None:
|
def __init__(self, category: str, message: str) -> None:
|
||||||
super().__init__(f"[{category}] {message}")
|
super().__init__(f"[{category}] {message}")
|
||||||
self.category = category
|
self.category = category
|
||||||
|
self.detail = message
|
||||||
|
|
||||||
|
|
||||||
def request_json(
|
def request_json(
|
||||||
@@ -85,7 +87,10 @@ def parse_gitea_token(raw_credentials: str | None) -> str:
|
|||||||
"""Return the token from a bare value, a JSON string or JSON with GITEA_TOKEN."""
|
"""Return the token from a bare value, a JSON string or JSON with GITEA_TOKEN."""
|
||||||
raw_credentials = (raw_credentials or "").strip()
|
raw_credentials = (raw_credentials or "").strip()
|
||||||
if not raw_credentials:
|
if not raw_credentials:
|
||||||
raise WorkflowError("configuration", "TOKEN_FOR_GITEA_WIKI is missing or empty.")
|
raise WorkflowError(
|
||||||
|
"configuration",
|
||||||
|
"No token for the wiki: set TOKEN_FOR_GITEA_WIKI, or TOKEN_FOR_GITEA.",
|
||||||
|
)
|
||||||
|
|
||||||
token: Any
|
token: Any
|
||||||
try:
|
try:
|
||||||
@@ -102,11 +107,33 @@ def parse_gitea_token(raw_credentials: str | None) -> str:
|
|||||||
|
|
||||||
if not isinstance(token, str) or not token.strip():
|
if not isinstance(token, str) or not token.strip():
|
||||||
raise WorkflowError(
|
raise WorkflowError(
|
||||||
"configuration", "TOKEN_FOR_GITEA_WIKI must contain a non-empty GITEA_TOKEN."
|
"configuration", "The wiki token must contain a non-empty GITEA_TOKEN."
|
||||||
)
|
)
|
||||||
return token.strip()
|
return token.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def describe_token(token: str) -> str:
|
||||||
|
"""Describe the shape of a token without revealing any of its characters.
|
||||||
|
|
||||||
|
Used when Gitea rejects the token, so a wrongly stored secret (the masked
|
||||||
|
text, ``NAME=value``, quotes) can be recognised from the log.
|
||||||
|
"""
|
||||||
|
facts = [f"{len(token)} characters"]
|
||||||
|
if re.fullmatch(r"[0-9a-f]{40}", token):
|
||||||
|
facts.append("looks like a Gitea token (40 hexadecimal characters)")
|
||||||
|
return ", ".join(facts)
|
||||||
|
facts.append("a Gitea token has 40 hexadecimal characters")
|
||||||
|
if set(token) <= {"*", "x", "X", "•"}:
|
||||||
|
facts.append("only mask characters: the masked text was stored")
|
||||||
|
if "=" in token:
|
||||||
|
facts.append("contains '=': the secret name may be part of the value")
|
||||||
|
if re.search(r"[\"'`]", token):
|
||||||
|
facts.append("contains a quote character")
|
||||||
|
if re.search(r"\s", token):
|
||||||
|
facts.append("contains whitespace")
|
||||||
|
return ", ".join(facts)
|
||||||
|
|
||||||
|
|
||||||
def split_repository(full_name: str | None) -> tuple[str, str]:
|
def split_repository(full_name: str | None) -> tuple[str, str]:
|
||||||
"""Split ``owner/repo`` into its two parts."""
|
"""Split ``owner/repo`` into its two parts."""
|
||||||
owner, separator, repo = (full_name or "").partition("/")
|
owner, separator, repo = (full_name or "").partition("/")
|
||||||
@@ -215,6 +242,7 @@ def main() -> int:
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
repository = request_json(repository_url, headers=headers)
|
repository = request_json(repository_url, headers=headers)
|
||||||
if isinstance(repository, dict) and repository.get("has_wiki") is False:
|
if isinstance(repository, dict) and repository.get("has_wiki") is False:
|
||||||
raise WorkflowError(
|
raise WorkflowError(
|
||||||
@@ -224,6 +252,12 @@ def main() -> int:
|
|||||||
print("Preflight passed: Gitea accepted the token and the wiki is enabled.")
|
print("Preflight passed: Gitea accepted the token and the wiki is enabled.")
|
||||||
|
|
||||||
result = publish(pages, f"{repository_url}/wiki", headers, request_json)
|
result = publish(pages, f"{repository_url}/wiki", headers, request_json)
|
||||||
|
except WorkflowError as error:
|
||||||
|
if error.category == "credentials":
|
||||||
|
raise WorkflowError(
|
||||||
|
"credentials", f"{error.detail} Token shape: {describe_token(token)}."
|
||||||
|
) from None
|
||||||
|
raise
|
||||||
print(
|
print(
|
||||||
f"Published {len(pages)} page(s) to the wiki of {owner}/{repo}: "
|
f"Published {len(pages)} page(s) to the wiki of {owner}/{repo}: "
|
||||||
f"{len(result['created'])} created, {len(result['updated'])} updated, "
|
f"{len(result['created'])} created, {len(result['updated'])} updated, "
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- translation of Credentials.md, source sha256 59f87b6dca4b -->
|
<!-- translation of Credentials.md, source sha256 57f66acfdc0a -->
|
||||||
|
|
||||||
> Dette er en oversættelse af [`Credentials`](Credentials). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
|
> Dette er en oversættelse af [`Credentials`](Credentials). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
|
||||||
|
|
||||||
@@ -52,13 +52,14 @@ Ved succes står der i loggen `Preflight passed: Gitea and GitHub accepted the c
|
|||||||
|
|
||||||
## Secret til publicering af wiki
|
## Secret til publicering af wiki
|
||||||
|
|
||||||
Workflowet **Publish wiki** (kun dette repository) kopierer `wiki/` til Gitea-wikien, når en ændring af `wiki/` flettes til `main`. Det bruger sin egen secret, så synkroniseringstokens aldrig får skriveadgang.
|
Workflowet **Publish wiki** (kun dette repository) kopierer `wiki/` til Gitea-wikien, når en ændring af `wiki/` flettes til `main`. Det bruger `TOKEN_FOR_GITEA_WIKI`, hvis den secret findes, og genbruger ellers `TOKEN_FOR_GITEA`.
|
||||||
|
|
||||||
| Secret | Indhold | Bruges til |
|
| Secret | Indhold | Bruges til |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `TOKEN_FOR_GITEA_WIKI` | Et almindeligt token, en JSON-streng eller JSON med `GITEA_TOKEN` | At skrive wikisiderne for dette repository |
|
| `TOKEN_FOR_GITEA_WIKI` (valgfri) | Et almindeligt token, en JSON-streng eller JSON med `GITEA_TOKEN` | At skrive wikisiderne for dette repository |
|
||||||
|
|
||||||
- Et Gitea personal access token med scope `write:repository`. Gitea har intet scope kun til wikien, så opret tokenet til en dedikeret bruger, der kun har skriveadgang til dette repository. S05 godkender scopet, og S03 gemmer secreten.
|
- Det token, der bruges, skal have scope `write:repository`, og dets bruger skal have skriveadgang til dette repository. Gitea har intet scope kun til wikien.
|
||||||
|
- `TOKEN_FOR_GITEA` er beskrevet ovenfor med kun `read:repository`. Hvis det genbruges til wikien, skal dets scope hæves, hvilket også giver metadatasynkroniseringen skriveadgang. En separat `TOKEN_FOR_GITEA_WIKI` til en dedikeret bruger holder synkroniseringstokenet skrivebeskyttet. S05 beslutter hvilket, og S03 gemmer secreten.
|
||||||
- Kald, der foretages: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`, `GET`, `POST` og `PATCH /repos/{owner}/{repo}/wiki/...` og, for en side, der ikke længere findes i `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
- Kald, der foretages: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`, `GET`, `POST` og `PATCH /repos/{owner}/{repo}/wiki/...` og, for en side, der ikke længere findes i `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
||||||
- Wikien skal være aktiveret i repositoryets indstillinger. Workflowet nægter at køre, hvis den ikke er det.
|
- Wikien skal være aktiveret i repositoryets indstillinger. Workflowet nægter at køre, hvis den ikke er det.
|
||||||
- Wikien er altid lig med `wiki/`: sider, der er redigeret eller tilføjet i Gitea's weboverflade, overskrives eller fjernes ved næste publicering.
|
- Wikien er altid lig med `wiki/`: sider, der er redigeret eller tilføjet i Gitea's weboverflade, overskrives eller fjernes ved næste publicering.
|
||||||
|
|||||||
+9
-7
@@ -65,17 +65,19 @@ is ever printed.
|
|||||||
## Wiki publishing secret
|
## Wiki publishing secret
|
||||||
|
|
||||||
The workflow **Publish wiki** (this repository only) copies `wiki/` to the Gitea
|
The workflow **Publish wiki** (this repository only) copies `wiki/` to the Gitea
|
||||||
wiki when a change to `wiki/` is merged to `main`. It uses its own secret so
|
wiki when a change to `wiki/` is merged to `main`. It uses `TOKEN_FOR_GITEA_WIKI`
|
||||||
that the metadata sync tokens never get write access.
|
when that secret exists and otherwise reuses `TOKEN_FOR_GITEA`.
|
||||||
|
|
||||||
| Secret | Content | Used for |
|
| Secret | Content | Used for |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `TOKEN_FOR_GITEA_WIKI` | A bare token, a JSON string, or JSON with `GITEA_TOKEN` | Writing the wiki pages of this repository |
|
| `TOKEN_FOR_GITEA_WIKI` (optional) | A bare token, a JSON string, or JSON with `GITEA_TOKEN` | Writing the wiki pages of this repository |
|
||||||
|
|
||||||
- A Gitea personal access token with scope `write:repository`. Gitea has no
|
- The token that is used needs scope `write:repository`, and its user needs
|
||||||
wiki-only scope, so create the token for a dedicated user that has write
|
write access to this repository. Gitea has no wiki-only scope.
|
||||||
access to this repository only. S05 approves the scope and S03 stores the
|
- `TOKEN_FOR_GITEA` is documented above with `read:repository` only. Reusing it
|
||||||
secret.
|
for the wiki means raising its scope, which also gives the metadata sync
|
||||||
|
write access. A separate `TOKEN_FOR_GITEA_WIKI` for a dedicated user keeps
|
||||||
|
the sync token read-only. S05 decides which, and S03 stores the secret.
|
||||||
- Calls made: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`,
|
- Calls made: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`,
|
||||||
`GET`, `POST` and `PATCH /repos/{owner}/{repo}/wiki/...` and, for a page that
|
`GET`, `POST` and `PATCH /repos/{owner}/{repo}/wiki/...` and, for a page that
|
||||||
no longer exists in `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
no longer exists in `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- translation of Credentials.md, source sha256 59f87b6dca4b -->
|
<!-- translation of Credentials.md, source sha256 57f66acfdc0a -->
|
||||||
|
|
||||||
> Ini ialah terjemahan [`Credentials`](Credentials). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
|
> Ini ialah terjemahan [`Credentials`](Credentials). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
|
||||||
|
|
||||||
@@ -52,13 +52,14 @@ Apabila berjaya, log menyatakan `Preflight passed: Gitea and GitHub accepted the
|
|||||||
|
|
||||||
## Secret untuk menerbitkan wiki
|
## Secret untuk menerbitkan wiki
|
||||||
|
|
||||||
Aliran kerja **Publish wiki** (repositori ini sahaja) menyalin `wiki/` ke wiki Gitea apabila perubahan pada `wiki/` digabungkan ke `main`. Ia menggunakan secret sendiri supaya token penyegerakan metadata tidak pernah mendapat akses tulis.
|
Aliran kerja **Publish wiki** (repositori ini sahaja) menyalin `wiki/` ke wiki Gitea apabila perubahan pada `wiki/` digabungkan ke `main`. Ia menggunakan `TOKEN_FOR_GITEA_WIKI` jika secret itu wujud, dan jika tidak, menggunakan semula `TOKEN_FOR_GITEA`.
|
||||||
|
|
||||||
| Secret | Kandungan | Digunakan untuk |
|
| Secret | Kandungan | Digunakan untuk |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `TOKEN_FOR_GITEA_WIKI` | Token biasa, rentetan JSON, atau JSON dengan `GITEA_TOKEN` | Menulis halaman wiki repositori ini |
|
| `TOKEN_FOR_GITEA_WIKI` (pilihan) | Token biasa, rentetan JSON, atau JSON dengan `GITEA_TOKEN` | Menulis halaman wiki repositori ini |
|
||||||
|
|
||||||
- Personal access token Gitea dengan skop `write:repository`. Gitea tidak mempunyai skop untuk wiki sahaja, jadi cipta token untuk pengguna khusus yang hanya mempunyai akses tulis kepada repositori ini. S05 meluluskan skop dan S03 menyimpan secret.
|
- Token yang digunakan mesti mempunyai skop `write:repository`, dan penggunanya mesti mempunyai akses tulis kepada repositori ini. Gitea tidak mempunyai skop untuk wiki sahaja.
|
||||||
|
- `TOKEN_FOR_GITEA` didokumenkan di atas dengan `read:repository` sahaja. Menggunakannya semula untuk wiki bermakna meningkatkan skopnya, yang juga memberi akses tulis kepada penyegerakan metadata. `TOKEN_FOR_GITEA_WIKI` yang berasingan untuk pengguna khusus mengekalkan token penyegerakan sebagai baca sahaja. S05 memutuskan yang mana, dan S03 menyimpan secret.
|
||||||
- Panggilan yang dibuat: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`, `GET`, `POST` dan `PATCH /repos/{owner}/{repo}/wiki/...` dan, bagi halaman yang tidak lagi wujud dalam `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
- Panggilan yang dibuat: `GET /repos/{owner}/{repo}`, `GET /repos/{owner}/{repo}/wiki/pages`, `GET`, `POST` dan `PATCH /repos/{owner}/{repo}/wiki/...` dan, bagi halaman yang tidak lagi wujud dalam `wiki/`, `DELETE /repos/{owner}/{repo}/wiki/page/{name}`.
|
||||||
- Wiki mesti diaktifkan dalam tetapan repositori. Aliran kerja enggan berjalan jika ia tidak diaktifkan.
|
- Wiki mesti diaktifkan dalam tetapan repositori. Aliran kerja enggan berjalan jika ia tidak diaktifkan.
|
||||||
- Wiki sentiasa sama dengan `wiki/`: halaman yang diedit atau ditambah dalam antara muka web Gitea ditimpa atau dibuang pada penerbitan seterusnya.
|
- Wiki sentiasa sama dengan `wiki/`: halaman yang diedit atau ditambah dalam antara muka web Gitea ditimpa atau dibuang pada penerbitan seterusnya.
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
<!-- translation of Home.md, source sha256 362c897f1425 -->
|
<!-- translation of Home.md, source sha256 75c6a7722bf7 -->
|
||||||
|
|
||||||
> Dette er en oversættelse af [`Home`](Home). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
|
> Dette er en oversættelse af [`Home`](Home). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ Det indeholder i øjeblikket Gitea-workflowet [`sync-github-metadata.yml`](https
|
|||||||
- Repository-secrets:
|
- Repository-secrets:
|
||||||
- `TOKEN_FOR_GITEA`: Gitea API-token (almindelig tekststreng eller JSON med `GITEA_TOKEN`)
|
- `TOKEN_FOR_GITEA`: Gitea API-token (almindelig tekststreng eller JSON med `GITEA_TOKEN`)
|
||||||
- `CREDENTIALS_FOR_GITHUB`: JSON-objekt med `GITHUB_PAT`, et GitHub personal access token, der må redigere spejl-repositoryet
|
- `CREDENTIALS_FOR_GITHUB`: JSON-objekt med `GITHUB_PAT`, et GitHub personal access token, der må redigere spejl-repositoryet
|
||||||
- `TOKEN_FOR_GITEA_WIKI` (kun i dette repository, til workflowet **Publish wiki**): Gitea-token, der kan skrive til repositoryets wiki
|
- `TOKEN_FOR_GITEA_WIKI` (valgfri, kun i dette repository, til workflowet **Publish wiki**): Gitea-token, der kan skrive til repositoryets wiki; hvis den mangler, bruges `TOKEN_FOR_GITEA`, som så skal have skriveadgang
|
||||||
|
|
||||||
|
|
||||||
## Opsætning
|
## Opsætning
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ It currently contains the Gitea workflow [`sync-github-metadata.yml`](https://gi
|
|||||||
- Repository secrets:
|
- Repository secrets:
|
||||||
- `TOKEN_FOR_GITEA`: Gitea API token (plain string, or JSON with `GITEA_TOKEN`)
|
- `TOKEN_FOR_GITEA`: Gitea API token (plain string, or JSON with `GITEA_TOKEN`)
|
||||||
- `CREDENTIALS_FOR_GITHUB`: JSON object containing `GITHUB_PAT`, a GitHub personal access token allowed to edit the mirror repository
|
- `CREDENTIALS_FOR_GITHUB`: JSON object containing `GITHUB_PAT`, a GitHub personal access token allowed to edit the mirror repository
|
||||||
- `TOKEN_FOR_GITEA_WIKI` (only in this repository, for the **Publish wiki** workflow): Gitea token that can write the repository wiki
|
- `TOKEN_FOR_GITEA_WIKI` (optional, only in this repository, for the **Publish wiki** workflow): Gitea token that can write the repository wiki; when it is absent, `TOKEN_FOR_GITEA` is used and needs write access
|
||||||
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
<!-- translation of Home.md, source sha256 362c897f1425 -->
|
<!-- translation of Home.md, source sha256 75c6a7722bf7 -->
|
||||||
|
|
||||||
> Ini ialah terjemahan [`Home`](Home). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
|
> Ini ialah terjemahan [`Home`](Home). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ Buat masa ini ia mengandungi aliran kerja Gitea [`sync-github-metadata.yml`](htt
|
|||||||
- Rahsia (secret) repositori:
|
- Rahsia (secret) repositori:
|
||||||
- `TOKEN_FOR_GITEA`: token API Gitea (rentetan biasa, atau JSON dengan `GITEA_TOKEN`)
|
- `TOKEN_FOR_GITEA`: token API Gitea (rentetan biasa, atau JSON dengan `GITEA_TOKEN`)
|
||||||
- `CREDENTIALS_FOR_GITHUB`: objek JSON yang mengandungi `GITHUB_PAT`, iaitu personal access token GitHub yang dibenarkan mengubah suai repositori cermin
|
- `CREDENTIALS_FOR_GITHUB`: objek JSON yang mengandungi `GITHUB_PAT`, iaitu personal access token GitHub yang dibenarkan mengubah suai repositori cermin
|
||||||
- `TOKEN_FOR_GITEA_WIKI` (hanya dalam repositori ini, untuk aliran kerja **Publish wiki**): token Gitea yang boleh menulis ke wiki repositori
|
- `TOKEN_FOR_GITEA_WIKI` (pilihan, hanya dalam repositori ini, untuk aliran kerja **Publish wiki**): token Gitea yang boleh menulis ke wiki repositori; jika tiada, `TOKEN_FOR_GITEA` digunakan dan mesti mempunyai akses tulis
|
||||||
|
|
||||||
|
|
||||||
## Persediaan
|
## Persediaan
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- translation of Troubleshooting.md, source sha256 060a822225e1 -->
|
<!-- translation of Troubleshooting.md, source sha256 d34495c26923 -->
|
||||||
|
|
||||||
> Dette er en oversættelse af [`Troubleshooting`](Troubleshooting). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
|
> Dette er en oversættelse af [`Troubleshooting`](Troubleshooting). Den engelske side er autoritativ, og ændringer her bliver overskrevet, næste gang wikien publiceres.
|
||||||
|
|
||||||
@@ -34,7 +34,8 @@ Kategorien fortæller, hvor du skal kigge. En fejl uden for scriptet (jobbet sta
|
|||||||
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | JSON-formen kræver nøglen `GITEA_TOKEN` |
|
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | JSON-formen kræver nøglen `GITEA_TOKEN` |
|
||||||
| `Could not determine the Gitea source repository.` | configuration | Kørslen har intet repositorynavn; meld det som en defekt |
|
| `Could not determine the Gitea source repository.` | configuration | Kørslen har intet repositorynavn; meld det som en defekt |
|
||||||
| `Expected at most one GitHub push mirror ... found N` | configuration | Behold ét GitHub push-spejl |
|
| `Expected at most one GitHub push mirror ... found N` | configuration | Behold ét GitHub push-spejl |
|
||||||
| `TOKEN_FOR_GITEA_WIKI is missing or empty.` | configuration | Kun wiki-publicering: tilføj secreten (se [credentials.md](Credentials.da)) |
|
| `No token for the wiki: set TOKEN_FOR_GITEA_WIKI, or TOKEN_FOR_GITEA.` | configuration | Kun wiki-publicering: tilføj en af secrets (se [credentials.md](Credentials.da)) |
|
||||||
|
| `... HTTP 403 ...` ved publicering af wikien | permissions | Kun wiki-publicering: tokenet skal have `write:repository` og skriveadgang til dette repository |
|
||||||
| `The wiki is not enabled on <repo>` | configuration | Kun wiki-publicering: aktivér wikien i repositoryets indstillinger |
|
| `The wiki is not enabled on <repo>` | configuration | Kun wiki-publicering: aktivér wikien i repositoryets indstillinger |
|
||||||
| `The wiki source directory ... has no Markdown pages` | configuration | Kun wiki-publicering: `wiki/` er tom eller mangler; intet blev ændret |
|
| `The wiki source directory ... has no Markdown pages` | configuration | Kun wiki-publicering: `wiki/` er tom eller mangler; intet blev ændret |
|
||||||
| `Could not determine the GitHub owner and repository ...` | configuration | Spejlets adresse skal se ud som `https://github.com/<owner>/<repo>.git` |
|
| `Could not determine the GitHub owner and repository ...` | configuration | Spejlets adresse skal se ud som `https://github.com/<owner>/<repo>.git` |
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ never starts, or stops before the step) is a **runner** problem.
|
|||||||
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | The JSON form needs a `GITEA_TOKEN` key |
|
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | The JSON form needs a `GITEA_TOKEN` key |
|
||||||
| `Could not determine the Gitea source repository.` | configuration | The run has no repository name; report as a defect |
|
| `Could not determine the Gitea source repository.` | configuration | The run has no repository name; report as a defect |
|
||||||
| `Expected at most one GitHub push mirror ... found N` | configuration | Keep one GitHub push mirror |
|
| `Expected at most one GitHub push mirror ... found N` | configuration | Keep one GitHub push mirror |
|
||||||
| `TOKEN_FOR_GITEA_WIKI is missing or empty.` | configuration | Wiki publishing only: add the secret (see [credentials.md](Credentials)) |
|
| `No token for the wiki: set TOKEN_FOR_GITEA_WIKI, or TOKEN_FOR_GITEA.` | configuration | Wiki publishing only: add one of the secrets (see [credentials.md](Credentials)) |
|
||||||
|
| `... HTTP 403 ...` while publishing the wiki | permissions | Wiki publishing only: the token needs `write:repository` and write access to this repository |
|
||||||
| `The wiki is not enabled on <repo>` | configuration | Wiki publishing only: enable the wiki in the repository settings |
|
| `The wiki is not enabled on <repo>` | configuration | Wiki publishing only: enable the wiki in the repository settings |
|
||||||
| `The wiki source directory ... has no Markdown pages` | configuration | Wiki publishing only: `wiki/` is empty or missing; nothing was changed |
|
| `The wiki source directory ... has no Markdown pages` | configuration | Wiki publishing only: `wiki/` is empty or missing; nothing was changed |
|
||||||
| `Could not determine the GitHub owner and repository ...` | configuration | The mirror address must look like `https://github.com/<owner>/<repo>.git` |
|
| `Could not determine the GitHub owner and repository ...` | configuration | The mirror address must look like `https://github.com/<owner>/<repo>.git` |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- translation of Troubleshooting.md, source sha256 060a822225e1 -->
|
<!-- translation of Troubleshooting.md, source sha256 d34495c26923 -->
|
||||||
|
|
||||||
> Ini ialah terjemahan [`Troubleshooting`](Troubleshooting). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
|
> Ini ialah terjemahan [`Troubleshooting`](Troubleshooting). Halaman bahasa Inggeris ialah teks yang sah, dan perubahan di sini akan ditimpa pada penerbitan wiki yang seterusnya.
|
||||||
|
|
||||||
@@ -34,7 +34,8 @@ Kategori menunjukkan di mana perlu dilihat. Kegagalan di luar skrip (kerja tidak
|
|||||||
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | Bentuk JSON memerlukan kunci `GITEA_TOKEN` |
|
| `TOKEN_FOR_GITEA must contain a non-empty GITEA_TOKEN.` | configuration | Bentuk JSON memerlukan kunci `GITEA_TOKEN` |
|
||||||
| `Could not determine the Gitea source repository.` | configuration | Larian tiada nama repositori; laporkan sebagai kecacatan |
|
| `Could not determine the Gitea source repository.` | configuration | Larian tiada nama repositori; laporkan sebagai kecacatan |
|
||||||
| `Expected at most one GitHub push mirror ... found N` | configuration | Kekalkan satu push mirror GitHub |
|
| `Expected at most one GitHub push mirror ... found N` | configuration | Kekalkan satu push mirror GitHub |
|
||||||
| `TOKEN_FOR_GITEA_WIKI is missing or empty.` | configuration | Penerbitan wiki sahaja: tambah secret (lihat [credentials.md](Credentials.ms)) |
|
| `No token for the wiki: set TOKEN_FOR_GITEA_WIKI, or TOKEN_FOR_GITEA.` | configuration | Penerbitan wiki sahaja: tambah salah satu secret (lihat [credentials.md](Credentials.ms)) |
|
||||||
|
| `... HTTP 403 ...` semasa menerbitkan wiki | permissions | Penerbitan wiki sahaja: token memerlukan `write:repository` dan akses tulis kepada repositori ini |
|
||||||
| `The wiki is not enabled on <repo>` | configuration | Penerbitan wiki sahaja: aktifkan wiki dalam tetapan repositori |
|
| `The wiki is not enabled on <repo>` | configuration | Penerbitan wiki sahaja: aktifkan wiki dalam tetapan repositori |
|
||||||
| `The wiki source directory ... has no Markdown pages` | configuration | Penerbitan wiki sahaja: `wiki/` kosong atau tiada; tiada apa-apa diubah |
|
| `The wiki source directory ... has no Markdown pages` | configuration | Penerbitan wiki sahaja: `wiki/` kosong atau tiada; tiada apa-apa diubah |
|
||||||
| `Could not determine the GitHub owner and repository ...` | configuration | Alamat cermin mesti kelihatan seperti `https://github.com/<owner>/<repo>.git` |
|
| `Could not determine the GitHub owner and repository ...` | configuration | Alamat cermin mesti kelihatan seperti `https://github.com/<owner>/<repo>.git` |
|
||||||
|
|||||||
Reference in New Issue
Block a user