Compare commits

...

54 commits

Author SHA1 Message Date
David Rotermund
f7b3ac4930 Merge branch 'forgejo' into delete_with_subpath
Some checks failed
Integration tests for the release process / release-simulation (push) Has been cancelled
2025-06-10 10:40:42 +02:00
Renovate Bot
a1bec15043 Update module connectrpc.com/connect to v1.18.1 (forgejo) (#8128)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8128
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-09 19:02:41 +02:00
Renovate Bot
9a1c10f92e Update dependency markdownlint-cli to v0.45.0 (forgejo) (#8127)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-09 18:49:57 +02:00
Renovate Bot
1d3208898f Update dependency eslint-plugin-regexp to v2.9.0 (forgejo) (#8126)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-09 18:48:30 +02:00
Renovate Bot
8d80a9cc01 Update vitest monorepo to v3.2.3 (forgejo) (#8125)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-09 18:48:27 +02:00
networkException
881cdf88bb feat: enable mlkem768x25519-sha256 by default for builtin ssh (#8115)
This pull request enables the `mlkem768x25519-sha256` key exchange algorithm by default. Support for this has landed in go 1.24 and crypto/ssh 0.39.0 respectively.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8115
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: networkException <git@nwex.de>
Co-committed-by: networkException <git@nwex.de>
2025-06-09 14:34:15 +02:00
Renovate Bot
d3adaf7574 Lock file maintenance (forgejo) (#8118)
This PR contains the following updates:

| Update | Change |
|---|---|
| lockFileMaintenance | All locks refreshed |

🔧 This Pull Request updates lock files to use the latest dependency versions.

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM, only on Monday ( * 0-3 * * 1 ) (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4wIiwidXBkYXRlZEluVmVyIjoiNDAuNDAuMCIsInRhcmdldEJyYW5jaCI6ImZvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8118
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-09 11:41:12 +02:00
Renovate Bot
81c960f0c2 Update renovate to v40.48.4 (forgejo) (#8117)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-09 10:50:43 +02:00
Malte Jürgens
580efedad4 fix: remove download attribute from external assets (#8112)
Fixes #6983.

I suppose a change like this doesn't require any testing?

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8112
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Beowulf <beowulf@beocode.eu>
Co-authored-by: Malte Jürgens <maltejur@dismail.de>
Co-committed-by: Malte Jürgens <maltejur@dismail.de>
2025-06-09 10:48:35 +02:00
Julian Schlarb
e70f48bd44 fix: always render detailed team permissions table in sidebar (#8108)
Remove the generic write/admin description block for AccessMode 2/3 and unconditionally display the unit-level permissions table.

fixes #3517

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [X] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [X] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [X] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8108
Reviewed-by: Otto <otto@codeberg.org>
Co-authored-by: Julian Schlarb <julian.schlarb@denktmit.de>
Co-committed-by: Julian Schlarb <julian.schlarb@denktmit.de>
2025-06-09 10:37:31 +02:00
pat-s
bd6f3243ab feat: support artifact uploads for OCI container packages (#8070)
# Fix OCI artifact uploads with`oras`

## Problem

ORAS (OCI Registry As Storage) artifact uploads were failing with several HTTP-related errors when pushing to Forgejo's container registry. This prevented users from storing OCI artifacts like `artifacthub-repo.yaml` in commands like `oras push [...] artifacthub-repo.yaml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml`.

This has been discussed previously in https://github.com/go-gitea/gitea/issues/25846

## Root Causes and Fixes

### 1. Missing Content-Length for Empty Blobs

**Issue**: Empty blobs (size 0) were not getting the required `Content-Length: 0` header, causing ORAS to fail with "unknown response Content-Length".

**Fix**: Changed the condition in `setResponseHeaders` from `if h.ContentLength != 0` to `if h.ContentLength >= 0` to ensure the Content-Length header is always set for valid blob sizes.

```go
// Before
if h.ContentLength != 0 {
    resp.Header().Set("Content-Length", strconv.FormatInt(h.ContentLength, 10))
}

// After
if h.ContentLength >= 0 {
    resp.Header().Set("Content-Length", strconv.FormatInt(h.ContentLength, 10))
}
```

### 2. Content-Length Mismatch in JSON Error Responses

**Issue**: The `jsonResponse` function was calling `WriteHeader()` before writing JSON content, causing "wrote more than the declared Content-Length" errors when the HTTP stack calculated a different Content-Length than what was actually written.

**Fix**: Modified `jsonResponse` to buffer JSON content first, calculate the exact Content-Length, then write the complete response.

### 3. Incomplete HTTP Responses in Error Handling

**Issue**: The `apiError` function was only setting response headers without writing any response body, causing EOF errors when clients expected a complete HTTP response.

**Fix**: Updated `apiError` to write proper JSON error responses following the OCI Distribution Specification format with `code` and `message` fields.

### 4. Empty Config Blob Handling for OCI Artifacts

**Issue**: OCI artifacts often have empty config blobs (required by spec but contain no data). The JSON decoder was failing with EOF when trying to parse these empty configs.

**Fix**: Added EOF handling in `parseOCIImageConfig` to return a valid default metadata object for empty config blobs.

```go
if err := json.NewDecoder(r).Decode(&image); err != nil {
    // Handle empty config blobs (common in OCI artifacts)
    if err == io.EOF {
        return &Metadata{
            Type:     TypeOCI,
            Platform: DefaultPlatform,
        }, nil
    }
    return nil, err
}
```

## Testing

Verified that ORAS artifact uploads now work correctly:

```bash
oras push registry/owner/package:artifacthub.io \
  --config /dev/null:application/vnd.cncf.artifacthub.config.v1+yaml \
  artifacthub-repo.yaml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml
```

### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8070
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: pat-s <patrick.schratz@gmail.com>
Co-committed-by: pat-s <patrick.schratz@gmail.com>
2025-06-09 10:14:53 +02:00
John Moon
b2b039b6e7 fix: allow instance API URLs in release assets (#7644)
Currently, if you try to add an "external" link to a release in Forgejo,
the validation code checks for basic URL soundness and then specifically
checks that the URL is not an API URL.

In some cases, it may make sense to link to instance API URLs (like when
you want to create a release that links to several different repos'
packages). Relax this check so it only validates basic URL soundness.

Refs: https://codeberg.org/forgejo/forgejo/issues/7598

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

See: https://codeberg.org/forgejo/docs/pulls/1161

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7644): <!--number 7644 --><!--line 0 --><!--description YWxsb3cgaW5zdGFuY2UgQVBJIFVSTHMgaW4gcmVsZWFzZSBhc3NldHM=-->allow instance API URLs in release assets<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7644
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Malte Jürgens <maltejur@noreply.codeberg.org>
Co-authored-by: John Moon <john.moon@vts-i.com>
Co-committed-by: John Moon <john.moon@vts-i.com>
2025-06-09 10:01:59 +02:00
Julian Schlarb
a8e375eb28 fix: omit Content-Length on 307 redirects when serving direct manifest for containers (#8037)
Containers have been refactored to use the same serve method as other packages, ensuring consistent response handling.

fixes #7888

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8037): <!--number 8037 --><!--line 0 --><!--description b21pdCBDb250ZW50LUxlbmd0aCBvbiAzMDcgcmVkaXJlY3RzIHdoZW4gc2VydmluZyBkaXJlY3QgbWFuaWZlc3QgZm9yIGNvbnRhaW5lcnM=-->omit Content-Length on 307 redirects when serving direct manifest for containers<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8037
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Julian Schlarb <julian.schlarb@denktmit.de>
Co-committed-by: Julian Schlarb <julian.schlarb@denktmit.de>
2025-06-09 08:43:41 +02:00
Julian Schlarb
4b6ccbd631 feat: auto cleanup of offline runners (#7803)
Fixes #7646

Adds a cron job to cleanup action runners that have been offline or inactive for X amount of time.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7803
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Julian Schlarb <julian.schlarb@denktmit.de>
Co-committed-by: Julian Schlarb <julian.schlarb@denktmit.de>
2025-06-08 00:13:37 +02:00
Renovate Bot
4d44ae39e1 Update vitest monorepo to v3.2.2 (forgejo) (#8102)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 04:49:09 +02:00
Renovate Bot
db83b43d8d Update dependency happy-dom to v17.6.3 (forgejo) (#8098)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8098
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 04:45:10 +02:00
Renovate Bot
6d7f5fb41e Update x/tools to v0.34.0 (forgejo) (#8103)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 03:57:12 +02:00
Renovate Bot
dc2954f8fe Update dependency @vitest/eslint-plugin to v1.2.1 (forgejo) (#8100)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 03:53:05 +02:00
Renovate Bot
7428edacbe Update module github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker to v3.3.0 (forgejo) (#8101)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 03:53:04 +02:00
Renovate Bot
10da5e5609 Update linters (forgejo) (#8099)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 03:52:56 +02:00
Renovate Bot
f476ee2196 Update dependency @vitejs/plugin-vue to v5.2.4 (forgejo) (#8097)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 03:52:39 +02:00
Renovate Bot
1242786324 Update dependency @axe-core/playwright to v4.10.2 (forgejo) (#8096)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-07 03:51:41 +02:00
Otto
e0bfacac0b fix: show membership of limited orgs (#8094)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8094
Reviewed-by: Otto <otto@codeberg.org>
2025-06-07 01:26:56 +02:00
Gusted
b68f923592
fix: show membership of limited orgs
- Include organisations with visibility of limited if the visitor is signed in.
- Resolves forgejo/forgejo#8093
- Added unit test.
2025-06-06 19:33:26 +02:00
Shiny Nematoda
82e4ccc223 port(gitea): Retain issue/pull sort type (#8067)
port of [gitea#34559](https://github.com/go-gitea/gitea/pull/34559)

initial work attributed to [badhezi](https://github.com/badhezi)

Co-authored-by: badhezi <zlilaharon@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8067
Reviewed-by: Beowulf <beowulf@beocode.eu>
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
Co-committed-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
2025-06-06 15:30:52 +02:00
Renovate Bot
8f2c08b8dc Update module golang.org/x/crypto to v0.39.0 (forgejo) (#8091)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8091
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-06 15:19:05 +02:00
Renovate Bot
dcf1eef9e9 Update module github.com/sergi/go-diff to v1.4.0 (forgejo) (#8090)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8090
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-06 15:02:54 +02:00
Renovate Bot
249f1fc17e Update dependency go to v1.24.4 (forgejo) (#8086)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [go](https://go.dev/) ([source](https://github.com/golang/go)) | toolchain | patch | `1.24.3` -> `1.24.4` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4wIiwidXBkYXRlZEluVmVyIjoiNDAuNDAuMCIsInRhcmdldEJyYW5jaCI6ImZvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8086
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-06 11:10:27 +02:00
Lucas Schwiderski
313504739f chore: extract commit header template (#8061)
Part of #7155

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8061
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Reviewed-by: Beowulf <beowulf@beocode.eu>
Co-authored-by: Lucas Schwiderski <lucas@lschwiderski.de>
Co-committed-by: Lucas Schwiderski <lucas@lschwiderski.de>
2025-06-05 11:35:08 +02:00
Ian Spence
7df94ff7b2 feat: add admin user reset-mfa CLI command (#8047)
### Pull Request Description:

This Pull Request adds a new `admin user reset-mfa` option to the CLI which lets admins remove all two-factor authentication configurations for a user (both totp & passkey). Like with `reset-password` this lets admins help unblock users who might be locked out.

### Justification:

Although users are told to back up or store TOTP recovery keys in a safe place, this is hardly a fool-proof design (not the fault of Forgejo or Gitea), in addition, passkeys don't really provide any means of recovery should the key no longer be available. It's entirely possible to become totally locked out of your foregejo account because you cannot complete a two-factor challenge.

Providing a means to recover from this lockout scenario through the existing CLI tool parallels the scenario of forgetting a password.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/8047): <!--number 8047 --><!--line 0 --><!--description QWRkcyBgYWRtaW4gdXNlciByZXNldC1tZmFgIENMSSBvcHRpb24=-->Adds `admin user reset-mfa` CLI option<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8047
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Ian Spence <ian@ecnepsnai.com>
Co-committed-by: Ian Spence <ian@ecnepsnai.com>
2025-06-05 10:40:21 +02:00
Earl Warren
60adf59620 i18n: update of translations from Codeberg Translate (#7969)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7969
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2025-06-05 08:54:57 +02:00
Codeberg Translate
805e749a15
i18n: update of translations from Codeberg Translate
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: AzzyDev <azzydev@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: BlackSpirits <blackspirits@noreply.codeberg.org>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Dirk <dirk@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <git@alius.cz>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Juno Takano <jutty@noreply.codeberg.org>
Co-authored-by: Laurent FAVOLE <lfavole@noreply.codeberg.org>
Co-authored-by: Lzebulon <lzebulon@noreply.codeberg.org>
Co-authored-by: Outbreak2096 <outbreak2096@noreply.codeberg.org>
Co-authored-by: Shihfu Juan <xlion@xlion.tw>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Vyxie <kitakita@disroot.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: earl-warren <earl-warren@noreply.codeberg.org>
Co-authored-by: fnetX <otto@codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: kwoot <kwoot@noreply.codeberg.org>
Co-authored-by: milimarg <milimarg@noreply.codeberg.org>
Co-authored-by: nightfurysl2001 <nightfurysl2001@noreply.codeberg.org>
Co-authored-by: oscarotero <oscarotero@noreply.codeberg.org>
Co-authored-by: pomp <pomp@noreply.codeberg.org>
Co-authored-by: rdsq <rdsq@noreply.codeberg.org>
Co-authored-by: tacaly <frederick@tacaly.com>
Co-authored-by: volkan <volkan@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/da/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/fil/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/nl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/ru/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo-next/zh_Hant/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/cs/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/da/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/de/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/eo/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fi/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fil/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/fr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/gl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/it/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/jbo/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/ko/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/lv/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nds/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/nl/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_BR/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/pt_PT/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/tr/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/uk/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hans/
Translate-URL: https://translate.codeberg.org/projects/forgejo/forgejo/zh_Hant/
Translation: Forgejo/forgejo
Translation: Forgejo/forgejo-next
2025-06-05 06:25:50 +00:00
Renovate Bot
e4c43c0cec Update module github.com/blevesearch/bleve/v2 to v2.5.2 (forgejo) (#8064)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8064
Reviewed-by: Shiny Nematoda <snematoda@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-04 14:18:00 +02:00
Renovate Bot
a24ca6e4b4 Update dependency postcss to v8.5.4 (forgejo) (#8062)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [postcss](https://postcss.org/) ([source](https://github.com/postcss/postcss)) | dependencies | patch | [`8.5.2` -> `8.5.4`](https://renovatebot.com/diffs/npm/postcss/8.5.2/8.5.4) |

---

### Release Notes

<details>
<summary>postcss/postcss (postcss)</summary>

### [`v8.5.4`](https://github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#854)

[Compare Source](https://github.com/postcss/postcss/compare/8.5.3...8.5.4)

-   Fixed Parcel compatibility issue (by [@&#8203;git-sumitchaudhary](https://github.com/git-sumitchaudhary)).

### [`v8.5.3`](https://github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#853)

[Compare Source](https://github.com/postcss/postcss/compare/8.5.2...8.5.3)

-   Added more details to `Unknown word` error (by [@&#8203;hiepxanh](https://github.com/hiepxanh)).
-   Fixed types (by [@&#8203;romainmenke](https://github.com/romainmenke)).
-   Fixed docs (by [@&#8203;catnipan](https://github.com/catnipan)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4wIiwidXBkYXRlZEluVmVyIjoiNDAuNDAuMCIsInRhcmdldEJyYW5jaCI6ImZvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8062
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-04 10:02:52 +02:00
Renovate Bot
534020d0ad Update module go.uber.org/mock/mockgen to v0.5.2 (forgejo) (#8065)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [go.uber.org/mock/mockgen](https://github.com/uber/mock) | patch | `v0.5.1` -> `v0.5.2` |

---

### Release Notes

<details>
<summary>uber/mock (go.uber.org/mock/mockgen)</summary>

### [`v0.5.2`](https://github.com/uber-go/mock/releases/tag/v0.5.2)

[Compare Source](https://github.com/uber/mock/compare/v0.5.1...v0.5.2)

#### 0.5.2 (28 Apr 2025)

##### Fixed

-   [#&#8203;248][]: Fixed an issue with type aliases not being included in generated code correctly.

[#&#8203;248]: https://github.com/uber-go/mock/pull/248

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4wIiwidXBkYXRlZEluVmVyIjoiNDAuNDAuMCIsInRhcmdldEJyYW5jaCI6ImZvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8065
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-04 10:01:47 +02:00
Renovate Bot
39d3e874b0 Update dependency vue to v3.5.16 (forgejo) (#8063)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-04 08:40:18 +02:00
Danko Aleksejevs
905a5748a8 Add issue number to the search index, rank number and title matches higher (#7956) (#7968)
An attempt at solving #7956. This (and rebuilding the index) seems enough to ensure the issue *appears* among the results.

However, I couldn't figure out from [bleve docs](https://github.com/blevesearch/bleve/blob/master/docs/scoring.md) how to affect the scoring based on specific fields, or whether that is possible at all.

Disclaimer: I've never written Go before, sorry 😅 take it as a quick PoC more than anything.

### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7968): <!--number 7968 --><!--line 0 --><!--description QWRkIGlzc3VlIG51bWJlciB0byB0aGUgc2VhcmNoIGluZGV4LCByYW5rIG51bWJlciBhbmQgdGl0bGUgbWF0Y2hlcyBoaWdoZXIgKCM3OTU2KQ==-->Add issue number to the search index, rank number and title matches higher (#7956)<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7968
Reviewed-by: Shiny Nematoda <snematoda@noreply.codeberg.org>
Co-authored-by: Danko Aleksejevs <danko@very.lv>
Co-committed-by: Danko Aleksejevs <danko@very.lv>
2025-06-04 07:42:29 +02:00
Earl Warren
2529923dea fix: rename api.{List,}ActionRun to api.{List,}RepoActionRun (#8066)
This variable name conflict happened because both

https://codeberg.org/forgejo/forgejo/pulls/7699

and

https://codeberg.org/forgejo/forgejo/pulls/7508

introduced the same names in different places and were merged at the same time.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8066
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-06-04 07:09:06 +02:00
Renovate Bot
4dd0514022 Update linters (forgejo) (#8052)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-03 14:47:40 +02:00
christopher-besch
d17aa98262 Actions Failure, Succes, Recover Webhooks (#7508)
Implement Actions Success, Failure and Recover webhooks for Forgejo, Gitea, Gogs, Slack, Discord, DingTalk, Telegram, Microsoft Teams, Feishu / Lark Suite, Matrix, WeCom (Wechat Work), Packagist. Some of these webhooks have not been manually tested.

Implement settings for these new webhooks.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7508): <!--number 7508 --><!--line 0 --><!--description QWN0aW9ucyBGYWlsdXJlLCBTdWNjZXMsIFJlY292ZXIgV2ViaG9va3M=-->Actions Failure, Succes, Recover Webhooks<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7508
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: christopher-besch <mail@chris-besch.com>
Co-committed-by: christopher-besch <mail@chris-besch.com>
2025-06-03 14:29:19 +02:00
Renovate Bot
6ce9d764bc Update module code.forgejo.org/f3/gof3/v3 to v3.11.0 (forgejo) (#8056)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| code.forgejo.org/f3/gof3/v3 | require | minor | `v3.10.8` -> `v3.11.0` |

---

### Configuration

📅 **Schedule**: Branch creation - On day 1 of the month, every 3 months ( * * 1 */3 * ) (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4wIiwidXBkYXRlZEluVmVyIjoiNDAuNDAuMCIsInRhcmdldEJyYW5jaCI6ImZvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Co-authored-by: limiting-factor <limiting-factor@posteo.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8056
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-03 14:24:57 +02:00
Michael Kriese
549fcff997 chore: drop unused misspell (#8058)
Package not used

- closes #8053

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8058
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-committed-by: Michael Kriese <michael.kriese@visualon.de>
2025-06-03 12:03:00 +02:00
Renovate Bot
bc14ad7da2 Update dependency happy-dom to v17.6.1 (forgejo) (#8051)
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-03 10:53:43 +02:00
Earl Warren
48671975f1 fix: migrate repository.topics column for SQLite (#8019)
XORM is unable to migrate a column type for SQLite, it has to be done manually.

Refs: forgejo/forgejo#7920

Note: testing is done by setting the `run-end-to-end-tests` label.
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8019
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-06-03 10:20:05 +02:00
Michael Kriese
240d958c0f chore(renovate): disable indirect digest updates for stable (#8055)
We usually don't updates them anyways

---

Please admin merge to not waste ci time

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8055
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-committed-by: Michael Kriese <michael.kriese@visualon.de>
2025-06-03 10:17:48 +02:00
Michael Kriese
ea07f0c0f3 chore: drop unused @typescript-eslint/parser package (#8054)
Package isn't references, `typescript-eslint` still pulls it transitive which is the recommend way

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8054
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-committed-by: Michael Kriese <michael.kriese@visualon.de>
2025-06-03 10:12:12 +02:00
Earl Warren
e38e761d5b fix: CLI is forgejo not Forgejo (#8049)
> **Warning** note to self: update the docs CLI page right after it is merged.

Regression from https://codeberg.org/forgejo/forgejo/pulls/8035

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

Check the USAGE line:

From the forgejo branch:

```sh
$ make TAGS='sqlite sqlite_unlock_notify' forgejo
$ ./forgejo help | head
 ./forgejo help | head
NAME:
   Forgejo - Beyond coding. We forge.

USAGE:
   Forgejo [global options] [command [command options]]
```

From this pull request:

```sh
$ make TAGS='sqlite sqlite_unlock_notify' forgejo
$ ./forgejo help | head
NAME:
   forgejo - Beyond coding. We forge.

USAGE:
   forgejo [global options] [command [command options]]
```

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8049
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-06-03 09:25:58 +02:00
Patrick Schratz
ac1f1a9cfb fix: add missing bottom margin for verification-button in release view (#8044)
When a release contains a GPG verified button, the bottom margin is missing. The top one is already `tw-mt-4`.

Screenshot from https://codeberg.org/crowci/crow/releases/tag/v3.6.0

| Current | New  |
|---------|---------|
| ![image](/attachments/489beb0a-4fc0-4140-9a46-534ae43a28ea) | ![image](/attachments/8ed2456f-28e4-4d1d-99e5-c64c4af93d20) |

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8044
Reviewed-by: Beowulf <beowulf@beocode.eu>
Co-authored-by: Patrick Schratz <pat-s@noreply.codeberg.org>
Co-committed-by: Patrick Schratz <pat-s@noreply.codeberg.org>
2025-06-03 08:55:22 +02:00
Michael Kriese
dbbd0de860 chore(renovate): bump to v40.40.0 and disable v7 (#8050)
- bump renovate to v40.40.0
- remove v7 branch from renovate
- disable transitive updates on stable branches (security updates will /should still open automatically)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8050
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-committed-by: Michael Kriese <michael.kriese@visualon.de>
2025-06-03 08:52:21 +02:00
0ko
9ecef99ab9 feat: configurable default units for mirrors (#7902)
Partial implementation of b1f42a0cdd

Docs update: https://codeberg.org/forgejo/docs/pulls/1197

Closes #6561
* issue author only provided a reason for the option for mirrors, and there's no known reason for implementing the same option for templates yet, but this change will not make it harder to add that separately.

Pull requests and Actions do not make sense for mirrors to have them, at least by default. Pull requests because changes will get overridden by upstream, Actions get triggered and are failing, filling the actions table in the DB with unwanted content, and there's a security concern, too.

## Testing

* log in to https://v12.next.forgejo.org
* migrate repository
    * example lightweight repo: https://codeberg.org/forgejo-contrib/delightful-forgejo
    * tick "This repository will be a mirror"
* verify that the repo doesn't have these tabs: Pull requests, Actions

Testing note: there's `models/unit/unit_test.go`, but I don't completely get how it works and was not able to append it with the new setting while keeping it working.

Co-authored-by: Zettat123 <zettat123@gmail.com>
Idea-by: lng2020

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7902): <!--number 7902 --><!--line 0 --><!--description Y29uZmlndXJhYmxlIGRlZmF1bHQgdW5pdHMgZm9yIG1pcnJvcnM=-->configurable default units for mirrors<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7902
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-committed-by: 0ko <0ko@noreply.codeberg.org>
2025-06-03 08:12:29 +02:00
Maxim Cournoyer
374def9922 Add a GNU Guix manifest (#8038)
## Testing

See https://codeberg.org/forgejo/docs/pulls/1224

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8038
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Co-committed-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
2025-06-03 08:08:17 +02:00
Michael Jerger
3bb6ed8f19 refactor & enhance AP elements used (#7728)
This PR is part of https://codeberg.org/forgejo/forgejo/pulls/4767 filed by @algernon

To keep changes isolated this might be reviewed &  merge after https://codeberg.org/forgejo/forgejo/pulls/7714

Refactor existing code to have one AP struct per file.
Enhance AP structs needed by related PR

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.

### Release notes

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: zam <mirco.zachmann@meissa.de>
Co-authored-by: Mirco Zachmann <nostar@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7728
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Michael Jerger <michael.jerger@meissa-gmbh.de>
Co-committed-by: Michael Jerger <michael.jerger@meissa-gmbh.de>
2025-06-02 22:29:10 +02:00
Antonin Delpeuch
0ed7237b12 [gitea] Always use an empty line to separate the commit message and trailer (#8041)
This is a port of a gitea PR: https://github.com/go-gitea/gitea/pull/34512.

I have added some copy-editing commits on top for cleanliness.
I haven't tested the changes manually and only relied on the existing automated test.

## Checklist
### Tests

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Jim Lin <jim@andestech.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8041
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Antonin Delpeuch <antonin@delpeuch.eu>
Co-committed-by: Antonin Delpeuch <antonin@delpeuch.eu>
2025-06-02 22:10:59 +02:00
klausfyhn
fc35915a28 feat: make action runs available in api (#7699)
## Summary

Inspired by https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository and https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#get-a-workflow-run

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/7699): <!--number 7699 --><!--line 0 --><!--description bWFrZSBhY3Rpb24gcnVucyBhdmFpbGFibGUgaW4gYXBp-->make action runs available in api<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7699
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: klausfyhn <klausfyhn@gmail.com>
Co-committed-by: klausfyhn <klausfyhn@gmail.com>
2025-06-02 22:05:12 +02:00
185 changed files with 5797 additions and 2172 deletions

View file

@ -87,12 +87,24 @@ forgejo.org/modules/eventsource
Event.String
forgejo.org/modules/forgefed
NewForgeFollowFromAp
NewForgeFollow
ForgeFollow.MarshalJSON
ForgeFollow.UnmarshalJSON
ForgeFollow.Validate
NewForgeUndoLike
ForgeUndoLike.UnmarshalJSON
ForgeUndoLike.Validate
NewForgeUserActivityFromAp
NewForgeUserActivity
ForgeUserActivity.Validate
NewPersonIDFromModel
GetItemByType
JSONUnmarshalerFn
NotEmpty
NewForgeUserActivityNoteFromAp
newNote
ForgeUserActivityNote.Validate
ToRepository
OnRepository

View file

@ -28,7 +28,7 @@ jobs:
runs-on: docker
container:
image: data.forgejo.org/renovate/renovate:40.31.0
image: data.forgejo.org/renovate/renovate:40.48.4
steps:
- name: Load renovate repo cache

View file

@ -37,19 +37,18 @@ endif
XGO_VERSION := go-1.21.x
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.1 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.3.0 # renovate: datasource=go
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 # renovate: datasource=go
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0 # renovate: datasource=go
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.32.0 # renovate: datasource=go
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.1 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.34.0 # renovate: datasource=go
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.2 # renovate: datasource=go
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.18.1 # renovate: datasource=go
RENOVATE_NPM_PACKAGE ?= renovate@40.31.0 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
RENOVATE_NPM_PACKAGE ?= renovate@40.48.4 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
@ -924,7 +923,6 @@ deps-tools:
$(GO) install $(GOFUMPT_PACKAGE)
$(GO) install $(GOLANGCI_LINT_PACKAGE)
$(GO) install $(GXZ_PACKAGE)
$(GO) install $(MISSPELL_PACKAGE)
$(GO) install $(SWAGGER_PACKAGE)
$(GO) install $(XGO_PACKAGE)
$(GO) install $(GO_LICENSES_PACKAGE)

View file

@ -18,6 +18,7 @@ func subcmdUser() *cli.Command {
microcmdUserDelete(),
microcmdUserGenerateAccessToken(),
microcmdUserMustChangePassword(),
microcmdUserResetMFA(),
},
}
}

View file

@ -0,0 +1,73 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"fmt"
auth_model "forgejo.org/models/auth"
user_model "forgejo.org/models/user"
"github.com/urfave/cli/v3"
)
func microcmdUserResetMFA() *cli.Command {
return &cli.Command{
Name: "reset-mfa",
Usage: "Remove all two-factor authentication configurations for a user",
Action: runResetMFA,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "username",
Aliases: []string{"u"},
Value: "",
Usage: "The user to update",
},
},
}
}
func runResetMFA(ctx context.Context, c *cli.Command) error {
if err := argsSet(c, "username"); err != nil {
return err
}
ctx, cancel := installSignals(ctx)
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
user, err := user_model.GetUserByName(ctx, c.String("username"))
if err != nil {
return err
}
webAuthnList, err := auth_model.GetWebAuthnCredentialsByUID(ctx, user.ID)
if err != nil {
return err
}
for _, credential := range webAuthnList {
if _, err := auth_model.DeleteCredential(ctx, credential.ID, user.ID); err != nil {
return err
}
}
tfaModes, err := auth_model.GetTwoFactorByUID(ctx, user.ID)
if err == nil && tfaModes != nil {
if err := auth_model.DeleteTwoFactorByID(ctx, tfaModes.ID, user.ID); err != nil {
return err
}
} else {
if _, is := err.(auth_model.ErrTwoFactorNotEnrolled); !is {
return err
}
}
fmt.Printf("%s's two-factor authentication settings have been removed!\n", user.Name)
return nil
}

View file

@ -159,7 +159,7 @@ func NewMainApp(version, versionExtra string) *cli.Command {
func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmdWithConfigArgs []*cli.Command, globalFlagsArgs func() []cli.Flag) *cli.Command {
app := &cli.Command{}
app.Name = "Forgejo"
app.Name = "forgejo"
app.Usage = "Beyond coding. We forge."
app.Description = `By default, forgejo will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".`
app.Version = version + versionExtra

View file

@ -408,7 +408,7 @@ local addIssueLabelsOverrides(labels) =
regex: '',
type: 'query',
multi: true,
allValue: '.+'
allValue: '.+',
},
)
.addTemplate(
@ -423,7 +423,7 @@ local addIssueLabelsOverrides(labels) =
regex: '',
type: 'query',
multi: true,
allValue: '.+'
allValue: '.+',
},
)
.addTemplate(

View file

@ -183,7 +183,7 @@ RUN_USER = ; git
;;
;; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
;; for system SSH this setting has no effect
;SSH_SERVER_KEY_EXCHANGES = curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1
;SSH_SERVER_KEY_EXCHANGES = mlkem768x25519-sha256, curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1
;;
;; For the built-in SSH server, choose the MACs to support for SSH connections,
;; for system SSH this setting has no effect
@ -1025,6 +1025,10 @@ LEVEL = Info
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
;DEFAULT_FORK_REPO_UNITS = repo.code,repo.pulls
;;
;; Comma separated list of default mirror repo units.
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
;DEFAULT_MIRROR_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.wiki,repo.projects,repo.packages
;;
;; Prefix archive files by placing them in a directory named after the repository
;PREFIX_ARCHIVE_FILES = true
;;

26
go.mod
View file

@ -2,10 +2,10 @@ module forgejo.org
go 1.24
toolchain go1.24.3
toolchain go1.24.4
require (
code.forgejo.org/f3/gof3/v3 v3.10.8
code.forgejo.org/f3/gof3/v3 v3.11.0
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
code.forgejo.org/forgejo/go-rpmutils v1.0.0
code.forgejo.org/forgejo/levelqueue v1.0.0
@ -17,7 +17,7 @@ require (
code.gitea.io/actions-proto-go v0.4.0
code.gitea.io/sdk/gitea v0.21.0
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
connectrpc.com/connect v1.17.0
connectrpc.com/connect v1.18.1
github.com/42wim/httpsig v1.2.3
github.com/42wim/sshsig v0.0.0-20250502153856-5100632e8920
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
@ -26,7 +26,7 @@ require (
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
github.com/alecthomas/chroma/v2 v2.18.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.5.1
github.com/blevesearch/bleve/v2 v2.5.2
github.com/buildkite/terminal-to-html/v3 v3.16.8
github.com/caddyserver/certmagic v0.23.0
github.com/chi-middleware/proxy v1.1.1
@ -87,8 +87,8 @@ require (
github.com/prometheus/client_golang v1.21.1
github.com/redis/go-redis/v9 v9.8.0
github.com/robfig/cron/v3 v3.0.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
github.com/sergi/go-diff v1.4.0
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
github.com/stretchr/testify v1.10.0
github.com/syndtr/goleveldb v1.0.0
@ -101,13 +101,13 @@ require (
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
gitlab.com/gitlab-org/api/client-go v0.129.0
go.uber.org/mock v0.5.2
golang.org/x/crypto v0.38.0
golang.org/x/crypto v0.39.0
golang.org/x/image v0.27.0
golang.org/x/net v0.40.0
golang.org/x/net v0.41.0
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.14.0
golang.org/x/sync v0.15.0
golang.org/x/sys v0.33.0
golang.org/x/text v0.25.0
golang.org/x/text v0.26.0
google.golang.org/protobuf v1.36.4
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
@ -146,7 +146,7 @@ require (
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
github.com/blevesearch/zapx/v16 v16.2.3 // indirect
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect
@ -237,9 +237,9 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.uber.org/zap/exp v0.3.0 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.31.0 // indirect
golang.org/x/tools v0.34.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)

48
go.sum
View file

@ -1,7 +1,7 @@
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
code.forgejo.org/f3/gof3/v3 v3.10.8 h1:cL5XgOcKffqMdKDOqGCXfMc2OBX89xYvGSj2mz3E/VQ=
code.forgejo.org/f3/gof3/v3 v3.10.8/go.mod h1:ovgb7R8o7k6poQKQ+KWXHOD9uIoanB6tNSmA3kKOMCI=
code.forgejo.org/f3/gof3/v3 v3.11.0 h1:f/xToKwqTgxG6PYxvewywjDQyCcyHEEJ6sZqUitFsAE=
code.forgejo.org/f3/gof3/v3 v3.11.0/go.mod h1:4FaRUNSQGBiD1M0DuB0yNv+Z2wMtlOeckgygHSSq4KQ=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
code.forgejo.org/forgejo/act v1.26.0 h1:6mTmoaw7d/WpYiw/Pw6AaypxFdgJog5OFi/PMEgEbxs=
@ -32,8 +32,8 @@ code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA=
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
@ -87,8 +87,8 @@ github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCk
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blevesearch/bleve/v2 v2.5.1 h1:cc/O++W2Hcjp1SU5ETHeE+QYWv2oV88ldYEPowdmg8M=
github.com/blevesearch/bleve/v2 v2.5.1/go.mod h1:9g/wnbWKm9AgXrU8Ecqi+IDdqjUHWymwkQRDg+5tafU=
github.com/blevesearch/bleve/v2 v2.5.2 h1:Ab0r0MODV2C5A6BEL87GqLBySqp/s9xFgceCju6BQk8=
github.com/blevesearch/bleve/v2 v2.5.2/go.mod h1:5Dj6dUQxZM6aqYT3eutTD/GpWKGFSsV8f7LDidFbwXo=
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
github.com/blevesearch/geo v0.2.3 h1:K9/vbGI9ehlXdxjxDRJtoAMt7zGAsMIzc6n8zWcwnhg=
@ -121,8 +121,8 @@ github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
github.com/blevesearch/zapx/v16 v16.2.3 h1:7Y0r+a3diEvlazsncexq1qoFOcBd64xwMS7aDm4lo1s=
github.com/blevesearch/zapx/v16 v16.2.3/go.mod h1:wVJ+GtURAaRG9KQAMNYyklq0egV+XJlGcXNCE0OFjjA=
github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@ -499,11 +499,11 @@ github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
@ -591,8 +591,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
@ -603,8 +603,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -620,8 +620,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -633,8 +633,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -684,8 +684,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -695,8 +695,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

38
manifest.scm Normal file
View file

@ -0,0 +1,38 @@
;;; Copyright 2025 The Forgejo Authors. All rights reserved.
;;; SPDX-License-Identifier: MIT
;;;
;;; Commentary:
;;;
;;; This is a GNU Guix manifest that can be used to create a
;;; development environment to build and test Forgejo.
;;;
;;; The following is a usage example to create a containerized
;;; environment, with HOME shared for the Go cache and the network
;;; made available to fetch required Go and Node dependencies.
;;;
#|
guix shell -CNF --share=$HOME -m manifest.scm
export GOTOOLCHAIN=local # to use the Go binary from Guix
export CC=gcc CGO_ENABLED=1
export TAGS="timetzdata sqlite sqlite_unlock_notify"
make clean
make -j$(nproc)
make test -j$(nproc) # run unit tests
make test-sqlite -j$(nproc) # run integration tests
make watch # run an instance/rebuild on changes
|#
(specifications->manifest
(list "bash-minimal"
"coreutils"
"findutils"
"gcc-toolchain"
"git" ;libpcre support is required
"git-lfs"
"gnupg"
"go"
"grep"
"make"
"node"
"nss-certs"
"openssh"
"sed"))

View file

@ -54,6 +54,8 @@ type FindRunJobOptions struct {
CommitSHA string
Statuses []Status
UpdatedBefore timeutil.TimeStamp
Events []string // []webhook_module.HookEventType
RunNumber int64
}
func (opts FindRunJobOptions) ToConds() builder.Cond {
@ -76,5 +78,11 @@ func (opts FindRunJobOptions) ToConds() builder.Cond {
if opts.UpdatedBefore > 0 {
cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore})
}
if len(opts.Events) > 0 {
cond = cond.And(builder.In("event", opts.Events))
}
if opts.RunNumber > 0 {
cond = cond.And(builder.Eq{"`index`": opts.RunNumber})
}
return cond
}

View file

@ -16,6 +16,7 @@ import (
repo_model "forgejo.org/models/repo"
"forgejo.org/models/shared/types"
user_model "forgejo.org/models/user"
"forgejo.org/modules/log"
"forgejo.org/modules/optional"
"forgejo.org/modules/timeutil"
"forgejo.org/modules/translation"
@ -353,3 +354,53 @@ func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
}
return res.RowsAffected()
}
func DeleteOfflineRunners(ctx context.Context, olderThan timeutil.TimeStamp, globalOnly bool) error {
log.Info("Doing: DeleteOfflineRunners")
if olderThan.AsTime().After(timeutil.TimeStampNow().AddDuration(-RunnerOfflineTime).AsTime()) {
return fmt.Errorf("invalid `cron.cleanup_offline_runners.older_than`value: must be at least %q", RunnerOfflineTime)
}
cond := builder.Or(
// never online
builder.And(builder.Eq{"last_online": 0}, builder.Lt{"created": olderThan}),
// was online but offline
builder.And(builder.Gt{"last_online": 0}, builder.Lt{"last_online": olderThan}),
)
if globalOnly {
cond = builder.And(cond, builder.Eq{"owner_id": 0}, builder.Eq{"repo_id": 0})
}
if err := db.Iterate(
ctx,
cond,
func(ctx context.Context, r *ActionRunner) error {
if err := DeleteRunner(ctx, r); err != nil {
return fmt.Errorf("DeleteOfflineRunners: %w", err)
}
lastOnline := r.LastOnline.AsTime()
olderThanTime := olderThan.AsTime()
if !lastOnline.IsZero() && lastOnline.Before(olderThanTime) {
log.Info(
"Deleted runner [ID: %d, Name: %s], last online %s ago",
r.ID, r.Name, olderThanTime.Sub(lastOnline).String(),
)
} else {
log.Info(
"Deleted runner [ID: %d, Name: %s], unused since %s ago",
r.ID, r.Name, olderThanTime.Sub(r.Created.AsTime()).String(),
)
}
return nil
},
); err != nil {
return err
}
log.Info("Finished: DeleteOfflineRunners")
return nil
}

View file

@ -6,10 +6,12 @@ import (
"encoding/binary"
"fmt"
"testing"
"time"
auth_model "forgejo.org/models/auth"
"forgejo.org/models/db"
"forgejo.org/models/unittest"
"forgejo.org/modules/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -73,3 +75,68 @@ func TestDeleteRunner(t *testing.T) {
idAsBinary[6], idAsBinary[7])
assert.Equal(t, idAsHexadecimal, after.UUID[19:])
}
func TestDeleteOfflineRunnersRunnerGlobalOnly(t *testing.T) {
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
timeutil.MockSet(baseTime)
defer timeutil.MockUnset()
require.NoError(t, unittest.PrepareTestDatabase())
olderThan := timeutil.TimeStampNow().Add(-timeutil.Hour)
require.NoError(t, DeleteOfflineRunners(db.DefaultContext, olderThan, true))
// create at test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 12345678})
// last_online test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000001})
// created one month ago but a repo
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000002})
// last online one hour ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000003})
// last online 10 seconds ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000004})
// created 1 month ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000005})
// created 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000006})
// last online 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000007})
}
func TestDeleteOfflineRunnersAll(t *testing.T) {
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
timeutil.MockSet(baseTime)
defer timeutil.MockUnset()
require.NoError(t, unittest.PrepareTestDatabase())
olderThan := timeutil.TimeStampNow().Add(-timeutil.Hour)
require.NoError(t, DeleteOfflineRunners(db.DefaultContext, olderThan, false))
// create at test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 12345678})
// last_online test base time
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000001})
// created one month ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000002})
// last online one hour ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000003})
// last online 10 seconds ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000004})
// created 1 month ago
unittest.AssertNotExistsBean(t, &ActionRunner{ID: 10000005})
// created 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000006})
// last online 1 hour ago
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 10000007})
}
func TestDeleteOfflineRunnersErrorOnInvalidOlderThanValue(t *testing.T) {
baseTime := time.Date(2024, 5, 19, 7, 40, 32, 0, time.UTC)
timeutil.MockSet(baseTime)
defer timeutil.MockUnset()
require.Error(t, DeleteOfflineRunners(db.DefaultContext, timeutil.TimeStampNow(), false))
}

View file

@ -34,6 +34,15 @@ var statusNames = map[Status]string{
StatusBlocked: "blocked",
}
var nameToStatus = make(map[string]Status, len(statusNames))
func init() {
// Populate name to status lookup map
for status, name := range statusNames {
nameToStatus[name] = status
}
}
// String returns the string name of the Status
func (s Status) String() string {
return statusNames[s]
@ -102,3 +111,8 @@ func (s Status) AsResult() runnerv1.Result {
}
return runnerv1.Result_RESULT_UNSPECIFIED
}
func StatusFromString(name string) (Status, bool) {
status, exists := nameToStatus[name]
return status, exists
}

View file

@ -227,7 +227,7 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
// The ssh library can parse the key, so next we find out what key exactly we have.
switch pkeyType {
case ssh.KeyAlgoDSA:
case ssh.KeyAlgoDSA: //nolint:staticcheck
rawPub := struct {
Name string
P, Q, G, Y *big.Int

View file

@ -471,3 +471,64 @@
need_approval: 0
approved_by: 0
event_payload: '{"head_commit":{"id":"5f22f7d0d95d614d25a5b68592adb345a4b5c7fd"}}'
# GET action run(s) test
-
id: 892
title: "successful push run"
repo_id: 63
owner_id: 2
workflow_id: "success.yaml"
index: 1
trigger_user_id: 2
ref: "refs/heads/main"
commit_sha: "97f29ee599c373c729132a5c46a046978311e0ee"
event: "push"
is_fork_pull_request: 0
status: 1 # success
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
-
id: 893
title: "failed pull_request run"
repo_id: 63
owner_id: 2
workflow_id: "failed.yaml"
index: 2
trigger_user_id: 2
ref: "refs/heads/bugfix-1"
commit_sha: "35c5cddfc19397501ec8f4f7bb808a7c8f04445f"
event: "pull_request"
is_fork_pull_request: 0
status: 2 # failure
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
-
id: 894
title: "running workflow_dispatch run"
repo_id: 63
owner_id: 2
workflow_id: "running.yaml"
index: 3
trigger_user_id: 2
ref: "refs/heads/main"
commit_sha: "97f29ee599c373c729132a5c46a046978311e0ee"
event: "workflow_dispatch"
is_fork_pull_request: 0
status: 6 # running
started: 1683636528
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0

View file

@ -18,3 +18,122 @@
created: 1716104432
updated: 1716104432
deleted: ~
- id: 10000001
uuid: 10d3b248-6460-4bf5-b819-1f5b3109e10f
name: global-online
version: v6.3.1+7-gc4c0ca0
owner_id: 0
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: 7e9ed71f64e98ce1f70e94c63f3cb6c41a8cb0b90de3e1daf7ec5c35361d60ed44da67c5ac393b7aaf443dcfc766007dc828
token_salt: WUcgZWl7mW
last_online: 1716104422
last_active: 0
agent_labels: '["docker"]'
created: 1716104431
updated: 1716104422
deleted: ~
- id: 10000002
uuid: 1d188484-dd97-4a70-b707-5e87b578ab6b
name: repo-never-used
version: v6.3.1+7-gc4c0ca0
owner_id: 0
repo_id: 1
description: ""
base: 0
repo_range: ""
token_hash: 51e88c17ac8b54dd101dc2e4f530a71643c703adba7170f4b1a28f1cb483b4cfb107798c521e0532ef3c6480b64518a5c6a5
token_salt: 4rh8ncXYIO
last_online: 0
last_active: 0
agent_labels: '["docker"]'
created: 1713512432
updated: 1713512432
deleted: ~
- id: 10000003
uuid: 7a039c6b-b0b2-4cf5-a93d-715d617f99e2
name: global-offline
version: v6.3.1+7-gc4c0ca0
owner_id: 0
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: c76960c56bc6069f0d1648991ec626500abe8c15286f5c355d565c3b5ba945d7d6f1272a6c77849e592528179511b94f5d69
token_salt: TFMe2jhOkB
last_online: 1715499632
last_active: 0
agent_labels: '["docker"]'
created: 1715499632
updated: 1715499632
deleted: ~
- id: 10000004
uuid: 93ca7fdd-faca-4df6-a474-8345263ef10b
name: user-online
version: v6.3.1+7-gc4c0ca0
owner_id: 1
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: 6ddf7f0f2301d2b3f66418145dc497a6d09fa6586e659afcb5ae2a0c5b639561d795aff8062537db9df73b396842ea826134
token_salt: QcdGuReAp4
last_online: 1716104422
last_active: 0
agent_labels: '["docker"]'
created: 1716104431
updated: 1716104422
deleted: ~
- id: 10000005
uuid: a8534df6-c4be-40f4-9714-903b69d973d9
name: user-never-used
version: v6.3.1+7-gc4c0ca0
owner_id: 1
repo_id: 0
description: desc
base: 0
repo_range: ""
token_hash: 4441de7defcfc3d21baa608dec66a562cf23307abddaabdbb836907ac5f48c8780c354891916c525b79ec7af8e95be7a09b4
token_salt: ONNqIOnj3t
last_online: 0
last_active: 0
agent_labels: '["docker"]'
created: 1713512433
updated: 1713512433
deleted: ~
- id: 10000006
uuid: e1c5bb6c-de68-4335-8955-5192f76708ac
name: orga-fresh-created
version: v6.3.1+7-gc4c0ca0
owner_id: 35
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: a61f9ee48c6847d243ace0a8936efe80af9277c7bc46d6da6e03d1d406608b8023ee66600ad24f0effaa8e3338f92ac97ac9
token_salt: fZJKjrFGWA
last_online: 0
last_active: 0
agent_labels: '["docker"]'
created: 1716100832
updated: 1716100832
deleted: ~
- id: 10000007
uuid: ff755f06-948e-479b-8031-5b3e9f123e32
name: orga-offline
version: v6.3.1+7-gc4c0ca0
owner_id: 35
repo_id: 0
description: ""
base: 0
repo_range: ""
token_hash: 9372efb38f9b64efe65065380abe2f24ef34a59d9619f4cdc08f1151e9849f0b6e722aa10538e8730288de6e2f09acdac695
token_salt: TnU7iiIdCb
last_online: 1716100832
last_active: 0
agent_labels: '["docker"]'
created: 1736085520
updated: 1716100832
deleted: ~

View file

@ -795,3 +795,10 @@
type: 10
config: "{}"
created_unix: 946684810
-
id: 115
repo_id: 63
type: 10
config: "{}"
created_unix: 946684810

View file

@ -1889,3 +1889,35 @@
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
topics: '[]'
-
id: 63
owner_id: 2
owner_name: user2
lower_name: test_action_run_search
name: test_action_run_search
default_branch: main
num_watches: 0
num_stars: 0
num_forks: 0
num_issues: 0
num_closed_issues: 0
num_pulls: 0
num_closed_pulls: 0
num_milestones: 0
num_closed_milestones: 0
num_projects: 0
num_closed_projects: 0
is_private: true
is_empty: false
is_archived: false
is_mirror: false
status: 0
is_fork: false
fork_id: 0
is_template: false
template_id: 0
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
topics: '[]'

View file

@ -239,3 +239,15 @@
num_members: 2
includes_all_repositories: false
can_create_org_repo: false
-
id: 25
org_id: 17
lower_name: super-user
name: super-user
description: ""
authorize: 3
num_repos: 0
num_members: 0
includes_all_repositories: 0
can_create_org_repo: 0

View file

@ -329,3 +329,10 @@
team_id: 22
type: 3
access_mode: 1
-
id: 84
org_id: 17
team_id: 25
type: 3
access_mode: 3

View file

@ -70,7 +70,7 @@
num_followers: 2
num_following: 1
num_stars: 2
num_repos: 17
num_repos: 18
num_teams: 0
num_members: 0
visibility: 0
@ -642,7 +642,7 @@
num_following: 0
num_stars: 0
num_repos: 2
num_teams: 3
num_teams: 4
num_members: 4
visibility: 0
repo_admin_change_team_access: false

View file

@ -10,16 +10,45 @@ import (
func SetTopicsAsEmptySlice(x *xorm.Engine) error {
var err error
if x.Dialect().URI().DBType == schemas.POSTGRES {
switch x.Dialect().URI().DBType {
case schemas.MYSQL:
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL OR topics = 'null'")
case schemas.SQLITE:
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL OR topics = 'null'")
case schemas.POSTGRES:
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL OR topics::text = 'null'")
} else {
_, err = x.Exec("UPDATE `repository` SET topics = '[]' WHERE topics IS NULL")
}
if err != nil {
return err
}
if x.Dialect().URI().DBType == schemas.SQLITE {
sessMigration := x.NewSession()
defer sessMigration.Close()
if err := sessMigration.Begin(); err != nil {
return err
}
_, err = sessMigration.Exec("ALTER TABLE `repository` RENAME COLUMN `topics` TO `topics_backup`")
if err != nil {
return err
}
_, err = sessMigration.Exec("ALTER TABLE `repository` ADD COLUMN `topics` TEXT NOT NULL DEFAULT '[]'")
if err != nil {
return err
}
_, err = sessMigration.Exec("UPDATE `repository` SET `topics` = `topics_backup`")
if err != nil {
return err
}
_, err = sessMigration.Exec("ALTER TABLE `repository` DROP COLUMN `topics_backup`")
if err != nil {
return err
}
return sessMigration.Commit()
}
type Repository struct {
ID int64 `xorm:"pk autoincr"`
Topics []string `xorm:"TEXT JSON NOT NULL"`

View file

@ -0,0 +1,5 @@
-
id: 1000
uid: 4
org_id: 22
is_public: true

View file

@ -26,6 +26,7 @@ type SearchOrganizationsOptions struct {
type FindOrgOptions struct {
db.ListOptions
UserID int64
IncludeLimited bool
IncludePrivate bool
}
@ -43,7 +44,11 @@ func (opts FindOrgOptions) ToConds() builder.Cond {
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
}
if !opts.IncludePrivate {
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
if !opts.IncludeLimited {
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
} else {
cond = cond.And(builder.In("`user`.visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
}
}
return cond
}

View file

@ -27,6 +27,7 @@ func TestCountOrganizations(t *testing.T) {
}
func TestFindOrgs(t *testing.T) {
defer unittest.OverrideFixtures("models/organization/TestFindOrgs")()
require.NoError(t, unittest.PrepareTestDatabase())
orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
@ -34,8 +35,14 @@ func TestFindOrgs(t *testing.T) {
IncludePrivate: true,
})
require.NoError(t, err)
if assert.Len(t, orgs, 1) {
assert.EqualValues(t, 3, orgs[0].ID)
if assert.Len(t, orgs, 2) {
if orgs[0].ID == 22 {
assert.EqualValues(t, 22, orgs[0].ID)
assert.EqualValues(t, 3, orgs[1].ID)
} else {
assert.EqualValues(t, 3, orgs[0].ID)
assert.EqualValues(t, 22, orgs[1].ID)
}
}
orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
@ -50,6 +57,14 @@ func TestFindOrgs(t *testing.T) {
IncludePrivate: true,
})
require.NoError(t, err)
assert.EqualValues(t, 2, total)
total, err = db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
UserID: 4,
IncludePrivate: false,
IncludeLimited: true,
})
require.NoError(t, err)
assert.EqualValues(t, 1, total)
}

View file

@ -235,7 +235,7 @@ func UpdateAttachmentByUUID(ctx context.Context, attach *Attachment, cols ...str
if attach.UUID == "" {
return errors.New("attachment uuid should be not blank")
}
if attach.ExternalURL != "" && !validation.IsValidExternalURL(attach.ExternalURL) {
if attach.ExternalURL != "" && !validation.IsValidReleaseAssetURL(attach.ExternalURL) {
return ErrInvalidExternalURL{ExternalURL: attach.ExternalURL}
}
_, err := db.GetEngine(ctx).Where("uuid=?", attach.UUID).Cols(cols...).Update(attach)
@ -244,7 +244,7 @@ func UpdateAttachmentByUUID(ctx context.Context, attach *Attachment, cols ...str
// UpdateAttachment updates the given attachment in database
func UpdateAttachment(ctx context.Context, atta *Attachment) error {
if atta.ExternalURL != "" && !validation.IsValidExternalURL(atta.ExternalURL) {
if atta.ExternalURL != "" && !validation.IsValidReleaseAssetURL(atta.ExternalURL) {
return ErrInvalidExternalURL{ExternalURL: atta.ExternalURL}
}
sess := db.GetEngine(ctx).Cols("name", "issue_id", "release_id", "comment_id", "download_count")

View file

@ -1,4 +1,5 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package unit
@ -69,7 +70,7 @@ func (u Type) LogString() string {
}
var (
// AllRepoUnitTypes contains all the unit types
// AllRepoUnitTypes contains all units
AllRepoUnitTypes = []Type{
TypeCode,
TypeIssues,
@ -83,7 +84,7 @@ var (
TypeActions,
}
// DefaultRepoUnits contains the default unit types
// DefaultRepoUnits contains default units for regular repos
DefaultRepoUnits = []Type{
TypeCode,
TypeIssues,
@ -95,12 +96,22 @@ var (
TypeActions,
}
// ForkRepoUnits contains the default unit types for forks
// ForkRepoUnits contains default units for forks
DefaultForkRepoUnits = []Type{
TypeCode,
TypePullRequests,
}
// DefaultMirrorRepoUnits contains default units for mirrors
DefaultMirrorRepoUnits = []Type{
TypeCode,
TypeIssues,
TypeReleases,
TypeWiki,
TypeProjects,
TypePackages,
}
// NotAllowedDefaultRepoUnits contains units that can't be default
NotAllowedDefaultRepoUnits = []Type{
TypeExternalWiki,
@ -172,6 +183,8 @@ func LoadUnitConfig() error {
if len(DefaultRepoUnits) == 0 {
return errors.New("no default repository units found")
}
// Default fork repo units
setDefaultForkRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultForkRepoUnits...)
if len(invalidKeys) > 0 {
log.Warn("Invalid keys in default fork repo units: %s", strings.Join(invalidKeys, ", "))
@ -181,6 +194,16 @@ func LoadUnitConfig() error {
return errors.New("no default fork repository units found")
}
// Default mirror repo units
setDefaultMirrorRepoUnits, invalidKeys := FindUnitTypes(setting.Repository.DefaultMirrorRepoUnits...)
if len(invalidKeys) > 0 {
log.Warn("Invalid keys in default mirror repo units: %s", strings.Join(invalidKeys, ", "))
}
DefaultMirrorRepoUnits = validateDefaultRepoUnits(DefaultMirrorRepoUnits, setDefaultMirrorRepoUnits)
if len(DefaultMirrorRepoUnits) == 0 {
return errors.New("no default mirror repository units found")
}
// Collect the allowed repo unit groups. Mutually exclusive units are
// grouped together.
AllowedRepoUnitGroups = [][]Type{}

View file

@ -299,6 +299,24 @@ func (w *Webhook) HasPackageEvent() bool {
(w.ChooseEvents && w.Package)
}
// HasActionRunFailureEvent returns if hook enabled action failure event.
func (w *Webhook) HasActionRunFailureEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.ActionRunFailure)
}
// HasActionRunRecoverEvent returns if hook enabled action recover event.
func (w *Webhook) HasActionRunRecoverEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.ActionRunRecover)
}
// HasActionRunSuccessEvent returns if hook enabled action success event.
func (w *Webhook) HasActionRunSuccessEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.ActionRunSuccess)
}
// HasPullRequestReviewRequestEvent returns true if hook enabled pull request review request event.
func (w *Webhook) HasPullRequestReviewRequestEvent() bool {
return w.SendEverything ||
@ -337,6 +355,9 @@ func (w *Webhook) EventCheckers() []struct {
{w.HasReleaseEvent, webhook_module.HookEventRelease},
{w.HasPackageEvent, webhook_module.HookEventPackage},
{w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest},
{w.HasActionRunFailureEvent, webhook_module.HookEventActionRunFailure},
{w.HasActionRunRecoverEvent, webhook_module.HookEventActionRunRecover},
{w.HasActionRunSuccessEvent, webhook_module.HookEventActionRunSuccess},
}
}

View file

@ -74,7 +74,8 @@ func TestWebhook_EventsArray(t *testing.T) {
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
"package", "pull_request_review_request",
"package", "pull_request_review_request", "action_run_failure",
"action_run_recover", "action_run_success",
},
(&Webhook{
HookEvent: &webhook_module.HookEvent{SendEverything: true},
@ -89,15 +90,78 @@ func TestWebhook_EventsArray(t *testing.T) {
}
func TestCreateWebhook(t *testing.T) {
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
unittest.AssertExistsAndLoadBean(t, hook)
t.Run("Some chosen events 1", func(t *testing.T) {
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":true,"events":{"create":false,"push":true,"pull_request":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
hookFromDb := unittest.AssertExistsAndLoadBean(t, hook)
assert.Equal(t, []string{
string(webhook_module.HookEventPush),
string(webhook_module.HookEventPullRequest),
}, hookFromDb.EventsArray())
})
t.Run("Some chosen events 2", func(t *testing.T) {
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":true,"events":{"action_run_recover":false,"action_run_success":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
hookFromDb := unittest.AssertExistsAndLoadBean(t, hook)
assert.Equal(t, []string{string(webhook_module.HookEventActionRunSuccess)}, hookFromDb.EventsArray())
})
t.Run("All events", func(t *testing.T) {
hook := &Webhook{
RepoID: 3,
URL: "https://www.example.com/unit_test",
ContentType: ContentTypeJSON,
Events: `{"push_only":false,"send_everything":false,"choose_events":true,"events":{"create":true,"delete":true,"fork":true,"issues":true,"issue_assign":true,"issue_label":true,"issue_milestone":true,"issue_comment":true,"push":true,"pull_request":true,"pull_request_assign":true,"pull_request_label":true,"pull_request_milestone":true,"pull_request_comment":true,"pull_request_review":true,"pull_request_sync":true,"pull_request_review_request":true,"wiki":true,"repository":true,"release":true,"package":true,"action_run_failure":true,"action_run_recover":true,"action_run_success":true}}`,
}
unittest.AssertNotExistsBean(t, hook)
require.NoError(t, CreateWebhook(db.DefaultContext, hook))
hookFromDb := unittest.AssertExistsAndLoadBean(t, hook)
assert.Equal(t, []string{
string(webhook_module.HookEventCreate),
string(webhook_module.HookEventDelete),
string(webhook_module.HookEventFork),
string(webhook_module.HookEventPush),
string(webhook_module.HookEventIssues),
string(webhook_module.HookEventIssueAssign),
string(webhook_module.HookEventIssueLabel),
string(webhook_module.HookEventIssueMilestone),
string(webhook_module.HookEventIssueComment),
string(webhook_module.HookEventPullRequest),
string(webhook_module.HookEventPullRequestAssign),
string(webhook_module.HookEventPullRequestLabel),
string(webhook_module.HookEventPullRequestMilestone),
string(webhook_module.HookEventPullRequestComment),
string(webhook_module.HookEventPullRequestReviewApproved),
string(webhook_module.HookEventPullRequestReviewRejected),
string(webhook_module.HookEventPullRequestReviewComment),
string(webhook_module.HookEventPullRequestSync),
string(webhook_module.HookEventWiki),
string(webhook_module.HookEventRepository),
string(webhook_module.HookEventRelease),
string(webhook_module.HookEventPackage),
string(webhook_module.HookEventPullRequestReviewRequest),
// these aren't webhook event types
// string(webhook_module.HookEventSchedule),
// string(webhook_module.HookEventWorkflowDispatch),
string(webhook_module.HookEventActionRunFailure),
string(webhook_module.HookEventActionRunRecover),
string(webhook_module.HookEventActionRunSuccess),
},
hookFromDb.EventsArray())
})
}
func TestGetWebhookByRepoID(t *testing.T) {

View file

@ -0,0 +1,57 @@
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
"github.com/google/uuid"
)
// ForgeFollow activity data type
// swagger:model
type ForgeFollow struct {
// swagger:ignore
ap.Activity
}
func NewForgeFollowFromAp(activity ap.Activity) (ForgeFollow, error) {
result := ForgeFollow{}
result.Activity = activity
if valid, err := validation.IsValid(result); !valid {
return ForgeFollow{}, err
}
return result, nil
}
func NewForgeFollow(actor, object string) (ForgeFollow, error) {
result := ForgeFollow{}
result.Type = ap.FollowType
result.ID = ap.IRI(actor + "/follows/" + uuid.New().String())
result.Actor = ap.IRI(actor)
result.Object = ap.IRI(object)
if valid, err := validation.IsValid(result); !valid {
return ForgeFollow{}, err
}
return result, nil
}
func (follow ForgeFollow) MarshalJSON() ([]byte, error) {
return follow.Activity.MarshalJSON()
}
func (follow *ForgeFollow) UnmarshalJSON(data []byte) error {
return follow.Activity.UnmarshalJSON(data)
}
func (follow ForgeFollow) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(follow.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(follow.Type), []any{"Follow"}, "type")...)
result = append(result, validation.ValidateIDExists(follow.Actor, "actor")...)
result = append(result, validation.ValidateIDExists(follow.Object, "object")...)
return result
}

View file

@ -0,0 +1,31 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
func Test_NewForgeFollowValidation(t *testing.T) {
sut := ForgeFollow{}
sut.Type = "Follow"
sut.Actor = ap.IRI("example.org/alice")
sut.Object = ap.IRI("example.org/bob")
if err, _ := validation.IsValid(sut); !err {
t.Errorf("sut is invalid: %v\n", err)
}
sut = ForgeFollow{}
sut.Actor = ap.IRI("example.org/alice")
sut.Object = ap.IRI("example.org/bob")
if err, _ := validation.IsValid(sut); err {
t.Errorf("sut is valid: %v\n", err)
}
}

View file

@ -0,0 +1,77 @@
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"fmt"
"time"
user_model "forgejo.org/models/user"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ForgeFollow activity data type
// swagger:model
type ForgeUserActivity struct {
ap.Activity
Note ForgeUserActivityNote
}
func NewForgeUserActivityFromAp(activity ap.Activity) (ForgeUserActivity, error) {
result := ForgeUserActivity{}
result.Activity = activity
note, err := NewForgeUserActivityNoteFromAp(activity.Object)
if err != nil {
return ForgeUserActivity{}, err
}
result.Note = note
if valid, err := validation.IsValid(result); !valid {
return ForgeUserActivity{}, err
}
return result, nil
}
func NewForgeUserActivity(doer *user_model.User, actionID int64, content string) (ForgeUserActivity, error) {
id := fmt.Sprintf("%s/activities/%d", doer.APActorID(), actionID)
published := time.Now()
result := ForgeUserActivity{}
result.ID = ap.IRI(id + "/activity")
result.Type = ap.CreateType
result.Actor = ap.IRI(doer.APActorID())
result.Published = published
result.To = ap.ItemCollection{
ap.IRI("https://www.w3.org/ns/activitystreams#Public"),
}
result.CC = ap.ItemCollection{
ap.IRI(doer.APActorID() + "/followers"),
}
note, err := newNote(doer, content, id, published)
if err != nil {
return ForgeUserActivity{}, err
}
result.Object = note
return result, nil
}
func (userActivity ForgeUserActivity) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(userActivity.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(userActivity.Type), []any{"Create"}, "type")...)
result = append(result, validation.ValidateIDExists(userActivity.Actor, "actor")...)
if len(userActivity.To) == 0 {
result = append(result, "Missing to")
}
if len(userActivity.CC) == 0 {
result = append(result, "Missing cc")
}
result = append(result, userActivity.Note.Validate()...)
return result
}

View file

@ -0,0 +1,40 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
func Test_ForgeUserActivityValidation(t *testing.T) {
note := ForgeUserActivityNote{}
note.Type = "Note"
note.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content("Any Content!"),
},
}
note.URL = ap.IRI("example.org/user-id/57")
sut := ForgeUserActivity{}
sut.Type = "Create"
sut.Actor = ap.IRI("example.org/user-id/23")
sut.CC = ap.ItemCollection{
ap.IRI("example.org/registration/public#2nd"),
}
sut.To = ap.ItemCollection{
ap.IRI("example.org/registration/public"),
}
sut.Note = note
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
}

View file

@ -10,8 +10,6 @@ import (
"strings"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ----------------------------- ActorID --------------------------------------------
@ -41,12 +39,18 @@ func NewActorID(uri string) (ActorID, error) {
}
func (id ActorID) AsURI() string {
var result string
var result, path string
if id.Path == "" {
path = id.ID
} else {
path = fmt.Sprintf("%s/%s", id.Path, id.ID)
}
if id.IsPortSupplemented {
result = fmt.Sprintf("%s://%s/%s/%s", id.HostSchema, id.Host, id.Path, id.ID)
result = fmt.Sprintf("%s://%s/%s", id.HostSchema, id.Host, path)
} else {
result = fmt.Sprintf("%s://%s:%d/%s/%s", id.HostSchema, id.Host, id.HostPort, id.Path, id.ID)
result = fmt.Sprintf("%s://%s:%d/%s", id.HostSchema, id.Host, id.HostPort, path)
}
return result
@ -54,8 +58,7 @@ func (id ActorID) AsURI() string {
func (id ActorID) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(id.ID, "userId")...)
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
result = append(result, validation.ValidateNotEmpty(id.ID, "ID")...)
result = append(result, validation.ValidateNotEmpty(id.Host, "host")...)
result = append(result, validation.ValidateNotEmpty(id.HostPort, "hostPort")...)
result = append(result, validation.ValidateNotEmpty(id.HostSchema, "hostSchema")...)
@ -68,115 +71,6 @@ func (id ActorID) Validate() []string {
return result
}
// ----------------------------- PersonID --------------------------------------------
type PersonID struct {
ActorID
}
// Factory function for PersonID. Created struct is asserted to be valid
func NewPersonID(uri, source string) (PersonID, error) {
result, err := newActorID(uri)
if err != nil {
return PersonID{}, err
}
result.Source = source
// validate Person specific path
personID := PersonID{result}
if valid, err := validation.IsValid(personID); !valid {
return PersonID{}, err
}
return personID, nil
}
func (id PersonID) AsWebfinger() string {
result := fmt.Sprintf("@%s@%s", strings.ToLower(id.ID), strings.ToLower(id.Host))
return result
}
func (id PersonID) AsLoginName() string {
result := fmt.Sprintf("%s%s", strings.ToLower(id.ID), id.HostSuffix())
return result
}
func (id PersonID) HostSuffix() string {
result := fmt.Sprintf("-%s", strings.ToLower(id.Host))
return result
}
func (id PersonID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...)
switch id.Source {
case "forgejo", "gitea":
if strings.ToLower(id.Path) != "api/v1/activitypub/user-id" && strings.ToLower(id.Path) != "api/activitypub/user-id" {
result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path))
}
}
return result
}
// ----------------------------- RepositoryID --------------------------------------------
type RepositoryID struct {
ActorID
}
// Factory function for RepositoryID. Created struct is asserted to be valid.
func NewRepositoryID(uri, source string) (RepositoryID, error) {
result, err := newActorID(uri)
if err != nil {
return RepositoryID{}, err
}
result.Source = source
// validate Person specific
repoID := RepositoryID{result}
if valid, err := validation.IsValid(repoID); !valid {
return RepositoryID{}, err
}
return repoID, nil
}
func (id RepositoryID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...)
switch id.Source {
case "forgejo", "gitea":
if strings.ToLower(id.Path) != "api/v1/activitypub/repository-id" && strings.ToLower(id.Path) != "api/activitypub/repository-id" {
result = append(result, fmt.Sprintf("path: %q has to be a repo specific api path", id.Path))
}
}
return result
}
func containsEmptyString(ar []string) bool {
for _, elem := range ar {
if elem == "" {
return true
}
}
return false
}
func removeEmptyStrings(ls []string) []string {
var rs []string
for _, str := range ls {
if str != "" {
rs = append(rs, str)
}
}
return rs
}
// ----------------------------- newActorID --------------------------------------------
func newActorID(uri string) (ActorID, error) {
validatedURI, err := url.ParseRequestURI(uri)
if err != nil {
@ -212,28 +106,21 @@ func newActorID(uri string) (ActorID, error) {
return result, nil
}
// ----------------------------- ForgePerson -------------------------------------
// ForgePerson activity data type
// swagger:model
type ForgePerson struct {
// swagger:ignore
ap.Actor
func containsEmptyString(ar []string) bool {
for _, elem := range ar {
if elem == "" {
return true
}
}
return false
}
func (s ForgePerson) MarshalJSON() ([]byte, error) {
return s.Actor.MarshalJSON()
}
func (s *ForgePerson) UnmarshalJSON(data []byte) error {
return s.Actor.UnmarshalJSON(data)
}
func (s ForgePerson) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(s.Type), "Type")...)
result = append(result, validation.ValidateOneOf(string(s.Type), []any{string(ap.PersonType)}, "Type")...)
result = append(result, validation.ValidateNotEmpty(s.PreferredUsername.String(), "PreferredUsername")...)
return result
func removeEmptyStrings(ls []string) []string {
var rs []string
for _, str := range ls {
if str != "" {
rs = append(rs, str)
}
}
return rs
}

View file

@ -0,0 +1,122 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"fmt"
"strings"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ----------------------------- PersonID --------------------------------------------
type PersonID struct {
ActorID
}
const (
personIDapiPathV1 = "api/v1/activitypub/user-id"
personIDapiPathV1Latest = "api/activitypub/user-id"
)
// Factory function for PersonID. Created struct is asserted to be valid
func NewPersonID(uri, source string) (PersonID, error) {
result, err := newActorID(uri)
if err != nil {
return PersonID{}, err
}
result.Source = source
// validate Person specific path
personID := PersonID{result}
if valid, err := validation.IsValid(personID); !valid {
return PersonID{}, err
}
return personID, nil
}
func NewPersonIDFromModel(host, schema string, port uint16, softwareName, id string) (PersonID, error) {
result := PersonID{}
result.ID = id
result.Source = softwareName
result.Host = host
result.HostSchema = schema
result.HostPort = port
result.IsPortSupplemented = false
if softwareName == "forgejo" {
result.Path = personIDapiPathV1
}
result.UnvalidatedInput = result.AsURI()
// validate Person specific path
if valid, err := validation.IsValid(result); !valid {
return PersonID{}, err
}
return result, nil
}
func (id PersonID) AsWebfinger() string {
result := fmt.Sprintf("@%s@%s", strings.ToLower(id.ID), strings.ToLower(id.Host))
return result
}
func (id PersonID) AsLoginName() string {
result := fmt.Sprintf("%s%s", strings.ToLower(id.ID), id.HostSuffix())
return result
}
func (id PersonID) HostSuffix() string {
var result string
if !id.IsPortSupplemented {
result = fmt.Sprintf("-%s-%d", strings.ToLower(id.Host), id.HostPort)
} else {
result = fmt.Sprintf("-%s", strings.ToLower(id.Host))
}
return result
}
func (id PersonID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea", "mastodon", "gotosocial"}, "Source")...)
if id.Source == "forgejo" {
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
if strings.ToLower(id.Path) != personIDapiPathV1 && strings.ToLower(id.Path) != personIDapiPathV1Latest {
result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path))
}
}
return result
}
// ----------------------------- ForgePerson -------------------------------------
// ForgePerson activity data type
// swagger:model
type ForgePerson struct {
// swagger:ignore
ap.Actor
}
func (s ForgePerson) MarshalJSON() ([]byte, error) {
return s.Actor.MarshalJSON()
}
func (s *ForgePerson) UnmarshalJSON(data []byte) error {
return s.Actor.UnmarshalJSON(data)
}
func (s ForgePerson) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(s.Type), "Type")...)
result = append(result, validation.ValidateOneOf(string(s.Type), []any{string(ap.PersonType)}, "Type")...)
result = append(result, validation.ValidateNotEmpty(s.PreferredUsername.String(), "PreferredUsername")...)
return result
}

View file

@ -0,0 +1,268 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"reflect"
"strings"
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewPersonIdFromModel(t *testing.T) {
expected := PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ := NewPersonIDFromModel("an.other.host", "https", 443, "forgejo", "1")
assert.Equal(t, expected, sut)
}
func TestNewPersonId(t *testing.T) {
var sut, expected PersonID
var err error
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = true
expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
sut, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
require.NoError(t, err)
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 80
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://an.other.host:80/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("http://an.other.host:80/api/v1/activitypub/user-id/1", "forgejo")
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("HTTPS://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
assert.Equal(t, expected, sut)
expected = PersonID{}
expected.ID = "@me"
expected.Source = "gotosocial"
expected.HostSchema = "https"
expected.Path = ""
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = true
expected.UnvalidatedInput = "https://an.other.host/@me"
sut, err = NewPersonID("https://an.other.host/@me", "gotosocial")
require.NoError(t, err)
assert.Equal(t, expected, sut)
}
func TestPersonIdValidation(t *testing.T) {
sut := PersonID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = ""
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/1"
result, err := validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: path should not be empty\npath: \"\" has to be a person specific api path")
sut = PersonID{}
sut.ID = "1"
sut.Source = "mastodon"
sut.HostSchema = "https"
sut.Path = ""
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/1"
result, err = validation.IsValid(sut)
assert.True(t, result)
require.NoError(t, err)
sut = PersonID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "path"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/path/1"
result, err = validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: path: \"path\" has to be a person specific api path")
sut = PersonID{}
sut.ID = "1"
sut.Source = "forgejox"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
result, err = validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: Field Source contains the value forgejox, which is not in allowed subset [forgejo gitea mastodon gotosocial]")
}
func TestWebfingerId(t *testing.T) {
sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
assert.Equal(t, "@12345@codeberg.org", sut.AsWebfinger())
}
func TestShouldThrowErrorOnInvalidInput(t *testing.T) {
var err any
_, err = NewPersonID("", "forgejo")
if err == nil {
t.Errorf("empty input should be invalid.")
}
_, err = NewPersonID("http://localhost:3000/api/v1/something", "forgejo")
if err == nil {
t.Errorf("localhost uris are not external")
}
_, err = NewPersonID("./api/v1/something", "forgejo")
if err == nil {
t.Errorf("relative uris are not allowed")
}
_, err = NewPersonID("http://1.2.3.4/api/v1/something", "forgejo")
if err == nil {
t.Errorf("uri may not be ip-4 based")
}
_, err = NewPersonID("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo")
if err == nil {
t.Errorf("uri may not be ip-6 based")
}
_, err = NewPersonID("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo")
if err == nil {
t.Errorf("uri may not contain relative path elements")
}
_, err = NewPersonID("https://myuser@an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err == nil {
t.Errorf("uri may not contain unparsed elements")
}
_, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err != nil {
t.Errorf("this uri should be valid but was: %v", err)
}
}
func Test_PersonMarshalJSON(t *testing.T) {
sut := ForgePerson{}
sut.Type = "Person"
sut.PreferredUsername = ap.NaturalLanguageValuesNew()
sut.PreferredUsername.Set("en", ap.Content("MaxMuster"))
result, _ := sut.MarshalJSON()
assert.JSONEq(t, `{"type":"Person","preferredUsername":"MaxMuster"}`, string(result), "Expected string is not equal")
}
func Test_PersonUnmarshalJSON(t *testing.T) {
expected := &ForgePerson{
Actor: ap.Actor{
Type: "Person",
PreferredUsername: ap.NaturalLanguageValues{
ap.LangRefValue{Ref: "en", Value: []byte("MaxMuster")},
},
},
}
sut := new(ForgePerson)
err := sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
x, _ := expected.MarshalJSON()
y, _ := sut.MarshalJSON()
if !reflect.DeepEqual(x, y) {
t.Errorf("UnmarshalJSON() expected: %q got: %q", x, y)
}
expectedStr := strings.ReplaceAll(strings.ReplaceAll(`{
"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"type":"Person",
"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatar/fa7f9c4af2a64f41b1bef292bf872614"},
"url":"https://federated-repo.prod.meissa.de/stargoose9",
"inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/inbox",
"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/outbox",
"preferredUsername":"stargoose9",
"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10#main-key",
"owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBoj...XAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`,
"\n", ""),
"\t", "")
err = sut.UnmarshalJSON([]byte(expectedStr))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
result, _ := sut.MarshalJSON()
assert.JSONEq(t, expectedStr, string(result), "Expected string is not equal")
}
func TestForgePersonValidation(t *testing.T) {
sut := new(ForgePerson)
sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
}
func TestAsloginName(t *testing.T) {
sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
assert.Equal(t, "12345-codeberg.org", sut.AsLoginName())
sut, _ = NewPersonID("https://codeberg.org:443/api/v1/activitypub/user-id/12345", "forgejo")
assert.Equal(t, "12345-codeberg.org-443", sut.AsLoginName())
}

View file

@ -0,0 +1,52 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"fmt"
"strings"
"forgejo.org/modules/validation"
)
// ----------------------------- RepositoryID --------------------------------------------
type RepositoryID struct {
ActorID
}
const (
repositoryIDapiPathV1 = "api/v1/activitypub/repository-id"
repositoryIDapiPathV1Latest = "api/activitypub/repository-id"
)
// Factory function for RepositoryID. Created struct is asserted to be valid.
func NewRepositoryID(uri, source string) (RepositoryID, error) {
result, err := newActorID(uri)
if err != nil {
return RepositoryID{}, err
}
result.Source = source
// validate Person specific
repoID := RepositoryID{result}
if valid, err := validation.IsValid(repoID); !valid {
return RepositoryID{}, err
}
return repoID, nil
}
func (id RepositoryID) Validate() []string {
result := id.ActorID.Validate()
result = append(result, validation.ValidateNotEmpty(id.Source, "source")...)
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea"}, "Source")...)
if id.Source == "forgejo" {
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
if strings.ToLower(id.Path) != repositoryIDapiPathV1 && strings.ToLower(id.Path) != repositoryIDapiPathV1Latest {
result = append(result, fmt.Sprintf("path: %q has to be a repo specific api path", id.Path))
}
}
return result
}

View file

@ -0,0 +1,45 @@
// Copyright 2023, 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewRepositoryId(t *testing.T) {
var sut, expected RepositoryID
var err error
setting.AppURL = "http://localhost:3000/"
expected = RepositoryID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = ""
expected.Host = "localhost"
expected.HostPort = 3000
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://localhost:3000/1"
_, err = NewRepositoryID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
require.EqualError(t, err, "Validation Error: forgefed.RepositoryID: path: \"api/v1/activitypub/user-id\" has to be a repo specific api path")
expected = RepositoryID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/activitypub/repository-id"
expected.Host = "localhost"
expected.HostPort = 3000
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://localhost:3000/api/activitypub/repository-id/1"
sut, err = NewRepositoryID("http://localhost:3000/api/activitypub/repository-id/1", "forgejo")
require.NoError(t, err)
assert.Equal(t, expected, sut)
}

View file

@ -4,258 +4,71 @@
package forgefed
import (
"reflect"
"strings"
"testing"
"forgejo.org/modules/setting"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewPersonId(t *testing.T) {
expected := PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = true
expected.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
func TestActorNew(t *testing.T) {
sut, err := NewActorID("https://an.other.forgejo.host/api/v1/activitypub/user-id/5")
require.NoError(t, err)
assert.Equal(t, ActorID{
ID: "5",
HostSchema: "https",
Path: "api/v1/activitypub/user-id",
Host: "an.other.forgejo.host",
HostPort: 443,
UnvalidatedInput: "https://an.other.forgejo.host/api/v1/activitypub/user-id/5",
IsPortSupplemented: true,
}, sut)
sut, _ := NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
sut, err = NewActorID("https://an.other.forgejo.host/api/v1/activitypub/actor")
require.NoError(t, err)
assert.Equal(t, ActorID{
ID: "actor",
HostSchema: "https",
Path: "api/v1/activitypub",
Host: "an.other.forgejo.host",
HostPort: 443,
UnvalidatedInput: "https://an.other.forgejo.host/api/v1/activitypub/actor",
IsPortSupplemented: true,
}, sut)
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("https://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 80
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://an.other.host:80/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("http://an.other.host:80/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
expected = PersonID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "https"
expected.Path = "api/v1/activitypub/user-id"
expected.Host = "an.other.host"
expected.HostPort = 443
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "https://an.other.host:443/api/v1/activitypub/user-id/1"
sut, _ = NewPersonID("HTTPS://an.other.host:443/api/v1/activitypub/user-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
}
func TestNewRepositoryId(t *testing.T) {
setting.AppURL = "http://localhost:3000/"
expected := RepositoryID{}
expected.ID = "1"
expected.Source = "forgejo"
expected.HostSchema = "http"
expected.Path = "api/activitypub/repository-id"
expected.Host = "localhost"
expected.HostPort = 3000
expected.IsPortSupplemented = false
expected.UnvalidatedInput = "http://localhost:3000/api/activitypub/repository-id/1"
sut, _ := NewRepositoryID("http://localhost:3000/api/activitypub/repository-id/1", "forgejo")
if sut != expected {
t.Errorf("expected: %v\n but was: %v\n", expected, sut)
}
sut, err = NewActorID("https://an.other.gts.host/users/me")
require.NoError(t, err)
assert.Equal(t, ActorID{
ID: "me",
HostSchema: "https",
Path: "users",
Host: "an.other.gts.host",
HostPort: 443,
UnvalidatedInput: "https://an.other.gts.host/users/me",
IsPortSupplemented: true,
}, sut)
}
func TestActorIdValidation(t *testing.T) {
sut := ActorID{}
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/"
if sut.Validate()[0] != "userId should not be empty" {
t.Errorf("validation error expected but was: %v\n", sut.Validate())
}
result := sut.Validate()
assert.Len(t, result, 1)
assert.Equal(t, "ID should not be empty", result[0])
sut = ActorID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1?illegal=action"
if sut.Validate()[0] != "not all input was parsed, \nUnvalidated Input:\"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" \nParsed URI: \"https://an.other.host/api/v1/activitypub/user-id/1\"" {
t.Errorf("validation error expected but was: %v\n", sut.Validate()[0])
}
}
func TestPersonIdValidation(t *testing.T) {
sut := PersonID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "path"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/path/1"
_, err := validation.IsValid(sut)
if validation.IsErrNotValid(err) && strings.Contains(err.Error(), "path: \"path\" has to be a person specific api path\n") {
t.Errorf("validation error expected but was: %v\n", err)
}
sut = PersonID{}
sut.ID = "1"
sut.Source = "forgejox"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub/user-id"
sut.Host = "an.other.host"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://an.other.host/api/v1/activitypub/user-id/1"
if sut.Validate()[0] != "Field Source contains the value forgejox, which is not in allowed subset [forgejo gitea]" {
t.Errorf("validation error expected but was: %v\n", sut.Validate()[0])
}
}
func TestWebfingerId(t *testing.T) {
sut, _ := NewPersonID("https://codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
if sut.AsWebfinger() != "@12345@codeberg.org" {
t.Errorf("wrong webfinger: %v", sut.AsWebfinger())
}
sut, _ = NewPersonID("https://Codeberg.org/api/v1/activitypub/user-id/12345", "forgejo")
if sut.AsWebfinger() != "@12345@codeberg.org" {
t.Errorf("wrong webfinger: %v", sut.AsWebfinger())
}
}
func TestShouldThrowErrorOnInvalidInput(t *testing.T) {
var err any
_, err = NewPersonID("", "forgejo")
if err == nil {
t.Error("empty input should be invalid.")
}
_, err = NewPersonID("http://localhost:3000/api/v1/something", "forgejo")
if err == nil {
t.Error("localhost uris are not external")
}
_, err = NewPersonID("./api/v1/something", "forgejo")
if err == nil {
t.Error("relative uris are not allowed")
}
_, err = NewPersonID("http://1.2.3.4/api/v1/something", "forgejo")
if err == nil {
t.Error("uri may not be ip-4 based")
}
_, err = NewPersonID("http:///[fe80::1ff:fe23:4567:890a%25eth0]/api/v1/something", "forgejo")
if err == nil {
t.Error("uri may not be ip-6 based")
}
_, err = NewPersonID("https://codeberg.org/api/v1/activitypub/../activitypub/user-id/12345", "forgejo")
if err == nil {
t.Error("uri may not contain relative path elements")
}
_, err = NewPersonID("https://myuser@an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err == nil {
t.Error("uri may not contain unparsed elements")
}
_, err = NewPersonID("https://an.other.host/api/v1/activitypub/user-id/1", "forgejo")
if err != nil {
t.Errorf("this uri should be valid but was: %v", err)
}
}
func Test_PersonMarshalJSON(t *testing.T) {
sut := ForgePerson{}
sut.Type = "Person"
sut.PreferredUsername = ap.NaturalLanguageValuesNew()
sut.PreferredUsername.Set("en", ap.Content("MaxMuster"))
result, _ := sut.MarshalJSON()
if string(result) != "{\"type\":\"Person\",\"preferredUsername\":\"MaxMuster\"}" {
t.Errorf("MarshalJSON() was = %q", result)
}
}
func Test_PersonUnmarshalJSON(t *testing.T) {
expected := &ForgePerson{
Actor: ap.Actor{
Type: "Person",
PreferredUsername: ap.NaturalLanguageValues{
ap.LangRefValue{Ref: "en", Value: []byte("MaxMuster")},
},
},
}
sut := new(ForgePerson)
err := sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
x, _ := expected.MarshalJSON()
y, _ := sut.MarshalJSON()
if !reflect.DeepEqual(x, y) {
t.Errorf("UnmarshalJSON() expected: %q got: %q", x, y)
}
expectedStr := strings.ReplaceAll(strings.ReplaceAll(`{
"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"type":"Person",
"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatar/fa7f9c4af2a64f41b1bef292bf872614"},
"url":"https://federated-repo.prod.meissa.de/stargoose9",
"inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/inbox",
"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10/outbox",
"preferredUsername":"stargoose9",
"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10#main-key",
"owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/10",
"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBoj...XAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`,
"\n", ""),
"\t", "")
err = sut.UnmarshalJSON([]byte(expectedStr))
if err != nil {
t.Errorf("UnmarshalJSON() unexpected error: %v", err)
}
result, _ := sut.MarshalJSON()
if expectedStr != string(result) {
t.Errorf("UnmarshalJSON() expected: %q got: %q", expectedStr, result)
}
}
func TestForgePersonValidation(t *testing.T) {
sut := new(ForgePerson)
sut.UnmarshalJSON([]byte(`{"type":"Person","preferredUsername":"MaxMuster"}`))
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
result = sut.Validate()
assert.Len(t, result, 1)
assert.Equal(t, "not all input was parsed, \nUnvalidated Input:\"https://an.other.host/api/v1/activitypub/user-id/1?illegal=action\" \nParsed URI: \"https://an.other.host/api/v1/activitypub/user-id/1\"", result[0])
}

View file

@ -1,4 +1,4 @@
// Copyright 2023 The Forgejo Authors. All rights reserved.
// Copyright 2023, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed

View file

@ -0,0 +1,68 @@
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"time"
user_model "forgejo.org/models/user"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
// ForgeFollow activity data type
// swagger:model
type ForgeUserActivityNote struct {
// swagger.ignore
ap.Object
}
func NewForgeUserActivityNoteFromAp(item ap.Item) (ForgeUserActivityNote, error) {
result := ForgeUserActivityNote{}
object := item.(*ap.Object)
result.Object = *object
if valid, err := validation.IsValid(result); !valid {
return ForgeUserActivityNote{}, err
}
return result, nil
}
// TODO: Unused - might be removed
func newNote(doer *user_model.User, content, id string, published time.Time) (ForgeUserActivityNote, error) {
note := ForgeUserActivityNote{}
note.Type = ap.NoteType
note.AttributedTo = ap.IRI(doer.APActorID())
note.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content(content),
},
}
note.ID = ap.IRI(id)
note.Published = published
note.URL = ap.IRI(id)
note.To = ap.ItemCollection{
ap.IRI("https://www.w3.org/ns/activitystreams#Public"),
}
note.CC = ap.ItemCollection{
ap.IRI(doer.APActorID() + "/followers"),
}
if valid, err := validation.IsValid(note); !valid {
return ForgeUserActivityNote{}, err
}
return note, nil
}
func (note ForgeUserActivityNote) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(string(note.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(note.Type), []any{"Note"}, "type")...)
result = append(result, validation.ValidateNotEmpty(note.Content.String(), "content")...)
result = append(result, validation.ValidateIDExists(note.URL, "url")...)
return result
}

View file

@ -0,0 +1,28 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
"testing"
"forgejo.org/modules/validation"
ap "github.com/go-ap/activitypub"
)
func Test_UserActivityNoteValidation(t *testing.T) {
sut := ForgeUserActivityNote{}
sut.Type = "Note"
sut.Content = ap.NaturalLanguageValues{
{
Ref: ap.NilLangRef,
Value: ap.Content("Any Content!"),
},
}
sut.URL = ap.IRI("example.org/user-id/57")
if res, _ := validation.IsValid(sut); !res {
t.Errorf("sut expected to be valid: %v\n", sut.Validate())
}
}

View file

@ -35,6 +35,8 @@ type ServeHeaderOptions struct {
Filename string
CacheDuration time.Duration // defaults to 5 minutes
LastModified time.Time
AdditionalHeaders http.Header
RedirectStatusCode int
}
// ServeSetHeaders sets necessary content serve headers
@ -82,6 +84,12 @@ func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
header.Set("Last-Modified", opts.LastModified.UTC().Format(http.TimeFormat))
}
if opts.AdditionalHeaders != nil {
for k, v := range opts.AdditionalHeaders {
header[k] = v
}
}
}
// ServeData download file from io.Reader

View file

@ -260,11 +260,11 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
if opts.Mode == internal.CodeSearchModeUnion {
query := bleve.NewDisjunctionQuery()
for _, field := range strings.Fields(opts.Keyword) {
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, false))
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, false, 1.0))
}
keywordQuery = query
} else {
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, false)
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, false, 1.0)
}
if len(opts.RepoIDs) > 0 {

View file

@ -29,11 +29,12 @@ func MatchQuery(matchTerm, field, analyzer string, fuzziness int) *query.MatchQu
}
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
func MatchPhraseQuery(matchPhrase, field, analyzer string, autoFuzzy bool) *query.MatchPhraseQuery {
func MatchPhraseQuery(matchPhrase, field, analyzer string, autoFuzzy bool, boost float64) *query.MatchPhraseQuery {
q := bleve.NewMatchPhraseQuery(matchPhrase)
q.FieldVal = field
q.Analyzer = analyzer
q.SetAutoFuzziness(autoFuzzy)
q.SetBoost(boost)
return q
}

View file

@ -23,7 +23,7 @@ import (
const (
issueIndexerAnalyzer = "issueIndexer"
issueIndexerDocType = "issueIndexerDocType"
issueIndexerLatestVersion = 4
issueIndexerLatestVersion = 5
)
const unicodeNormalizeName = "unicodeNormalize"
@ -69,6 +69,7 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) {
docMapping.AddFieldMappingsAt("is_public", boolFieldMapping)
docMapping.AddFieldMappingsAt("index", numberFieldMapping)
docMapping.AddFieldMappingsAt("title", textFieldMapping)
docMapping.AddFieldMappingsAt("content", textFieldMapping)
docMapping.AddFieldMappingsAt("comments", textFieldMapping)
@ -163,9 +164,15 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
q := bleve.NewBooleanQuery()
for _, token := range tokens {
innerQ := bleve.NewDisjunctionQuery(
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, token.Fuzzy),
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, token.Fuzzy),
inner_bleve.MatchPhraseQuery(token.Term, "comments", issueIndexerAnalyzer, token.Fuzzy))
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, token.Fuzzy, 2.0),
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, token.Fuzzy, 1.0),
inner_bleve.MatchPhraseQuery(token.Term, "comments", issueIndexerAnalyzer, token.Fuzzy, 1.0))
if issueID, err := token.ParseIssueReference(); err == nil {
idQuery := inner_bleve.NumericEqualityQuery(issueID, "index")
idQuery.SetBoost(5.0)
innerQ.AddQuery(idQuery)
}
switch token.Kind {
case internal.BoolOptMust:

View file

@ -5,6 +5,7 @@ package db
import (
"context"
"strconv"
"forgejo.org/models/db"
issue_model "forgejo.org/models/issues"
@ -71,6 +72,17 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
)),
),
)
term := options.Keyword
if term[0] == '#' || term[0] == '!' {
term = term[1:]
}
if issueID, err := strconv.ParseInt(term, 10, 64); err == nil {
cond = builder.Or(
builder.Eq{"`index`": issueID},
cond,
)
}
}
opt, err := ToDBOptions(ctx, options)

View file

@ -18,7 +18,7 @@ import (
)
const (
issueIndexerLatestVersion = 1
issueIndexerLatestVersion = 2
// multi-match-types, currently only 2 types are used
// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
esMultiMatchTypeBestFields = "best_fields"
@ -56,7 +56,8 @@ const (
"repo_id": { "type": "long", "index": true },
"is_public": { "type": "boolean", "index": true },
"title": { "type": "text", "index": true },
"index": { "type": "long", "index": true },
"title": { "type": "text", "index": true },
"content": { "type": "text", "index": true },
"comments": { "type" : "text", "index": true },
@ -155,21 +156,25 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
return nil, err
}
for _, token := range tokens {
innerQ := elastic.NewMultiMatchQuery(token.Term, "title", "content", "comments")
innerQ := elastic.NewMultiMatchQuery(token.Term, "content", "comments").FieldWithBoost("title", 2.0).TieBreaker(0.5)
if token.Fuzzy {
// If the term is not a phrase use fuzziness set to AUTO
innerQ = innerQ.Type(esMultiMatchTypeBestFields).Fuzziness(esFuzzyAuto)
} else {
innerQ = innerQ.Type(esMultiMatchTypePhrasePrefix)
}
var eitherQ elastic.Query = innerQ
if issueID, err := token.ParseIssueReference(); err == nil {
indexQ := elastic.NewTermQuery("index", issueID).Boost(15.0)
eitherQ = elastic.NewDisMaxQuery().Query(indexQ).Query(innerQ).TieBreaker(0.5)
}
switch token.Kind {
case internal.BoolOptMust:
q.Must(innerQ)
q.Must(eitherQ)
case internal.BoolOptShould:
q.Should(innerQ)
q.Should(eitherQ)
case internal.BoolOptNot:
q.MustNot(innerQ)
q.MustNot(eitherQ)
}
}
query.Must(q)

View file

@ -14,6 +14,7 @@ type IndexerData struct {
ID int64 `json:"id"`
RepoID int64 `json:"repo_id"`
IsPublic bool `json:"is_public"` // If the repo is public
Index int64 `json:"index"`
// Fields used for keyword searching
Title string `json:"title"`

View file

@ -5,6 +5,7 @@ package internal
import (
"io"
"strconv"
"strings"
)
@ -22,6 +23,14 @@ type Token struct {
Fuzzy bool
}
func (tk *Token) ParseIssueReference() (int64, error) {
term := tk.Term
if term[0] == '#' || term[0] == '!' {
term = term[1:]
}
return strconv.ParseInt(term, 10, 64)
}
type Tokenizer struct {
in *strings.Reader
}

View file

@ -549,6 +549,55 @@ var cases = []*testIndexerCase{
}), result.Total)
},
},
{
Name: "Index",
SearchOptions: &internal.SearchOptions{
Keyword: "13",
SortBy: internal.SortByScore,
RepoIDs: []int64{5},
},
ExpectedIDs: []int64{93}, // 93 = #13 in repo 5
ExpectedTotal: 1,
},
{
Name: "Index with prefix",
SearchOptions: &internal.SearchOptions{
Keyword: "#13",
SortBy: internal.SortByScore,
RepoIDs: []int64{5},
},
ExpectedIDs: []int64{93},
ExpectedTotal: 1,
},
{
Name: "Index and title boost",
ExtraData: []*internal.IndexerData{
{ID: 1001, Title: "re #13", RepoID: 5},
{ID: 1002, Title: "re #1001", Content: "leave 13 alone. - 13", RepoID: 5},
},
SearchOptions: &internal.SearchOptions{
Keyword: "!13",
SortBy: internal.SortByScore,
RepoIDs: []int64{5},
},
ExpectedIDs: []int64{93, 1001, 1002},
ExpectedTotal: 3,
},
{
Name: "Index exclude",
ExtraData: []*internal.IndexerData{
{ID: 1001, Index: 101, Title: "Brrr", RepoID: 5},
{ID: 1002, Index: 102, Title: "Brrr", Content: "Brrr", RepoID: 5},
{ID: 1003, Index: 103, Title: "Brrr", RepoID: 5},
{ID: 1004, Index: 104, Title: "Brrr", RepoID: 5},
},
SearchOptions: &internal.SearchOptions{
Keyword: "Brrr -101 -103",
SortBy: internal.SortByScore,
},
ExpectedIDs: []int64{1002, 1004},
ExpectedTotal: 2,
},
{
Name: "SortByCreatedDesc",
SearchOptions: &internal.SearchOptions{
@ -741,6 +790,7 @@ func generateDefaultIndexerData() []*internal.IndexerData {
data = append(data, &internal.IndexerData{
ID: id,
Index: issueIndex,
RepoID: repoID,
IsPublic: repoID%2 == 0,
Title: fmt.Sprintf("issue%d of repo%d", issueIndex, repoID),

View file

@ -95,6 +95,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
return &internal.IndexerData{
ID: issue.ID,
RepoID: issue.RepoID,
Index: issue.Index,
IsPublic: !issue.Repo.IsPrivate,
Title: issue.Title,
Content: issue.Content,

View file

@ -84,6 +84,13 @@ func ParseImageConfig(mt string, r io.Reader) (*Metadata, error) {
func parseOCIImageConfig(r io.Reader) (*Metadata, error) {
var image oci.Image
if err := json.NewDecoder(r).Decode(&image); err != nil {
// Handle empty config blobs (common in OCI artifacts)
if err == io.EOF {
return &Metadata{
Type: TypeOCI,
Platform: DefaultPlatform,
}, nil
}
return nil, err
}

View file

@ -4,6 +4,7 @@
package container
import (
"io"
"strings"
"testing"
@ -60,3 +61,49 @@ func TestParseImageConfig(t *testing.T) {
assert.Equal(t, projectURL, metadata.ProjectURL)
assert.Equal(t, repositoryURL, metadata.RepositoryURL)
}
func TestParseImageConfigEmptyBlob(t *testing.T) {
t.Run("Empty config blob (EOF)", func(t *testing.T) {
// Test empty reader (simulates empty config blob common in OCI artifacts)
metadata, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader(""))
require.NoError(t, err)
assert.Equal(t, TypeOCI, metadata.Type)
assert.Equal(t, DefaultPlatform, metadata.Platform)
assert.Empty(t, metadata.Description)
assert.Empty(t, metadata.Authors)
assert.Empty(t, metadata.Labels)
assert.Empty(t, metadata.Manifests)
})
t.Run("Empty JSON object", func(t *testing.T) {
// Test minimal valid JSON config
metadata, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader("{}"))
require.NoError(t, err)
assert.Equal(t, TypeOCI, metadata.Type)
assert.Equal(t, DefaultPlatform, metadata.Platform)
assert.Empty(t, metadata.Description)
assert.Empty(t, metadata.Authors)
})
t.Run("Invalid JSON still returns error", func(t *testing.T) {
// Test that actual JSON errors (not EOF) are still returned
_, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader("{invalid json"))
require.Error(t, err)
assert.NotEqual(t, io.EOF, err)
})
t.Run("OCI artifact with empty config", func(t *testing.T) {
// Test OCI artifact scenario with minimal config
configOCI := `{"config": {}}`
metadata, err := ParseImageConfig(oci.MediaTypeImageManifest, strings.NewReader(configOCI))
require.NoError(t, err)
assert.Equal(t, TypeOCI, metadata.Type)
assert.Equal(t, DefaultPlatform, metadata.Platform)
assert.Empty(t, metadata.Description)
assert.Empty(t, metadata.Authors)
assert.Empty(t, metadata.ImageLayers)
})
}

View file

@ -69,8 +69,11 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
// insert units for repo
defaultUnits := unit.DefaultRepoUnits
if isFork {
switch {
case isFork:
defaultUnits = unit.DefaultForkRepoUnits
case repo.IsMirror:
defaultUnits = unit.DefaultMirrorRepoUnits
}
units := make([]repo_model.RepoUnit, 0, len(defaultUnits))
for _, tp := range defaultUnits {

View file

@ -1,4 +1,5 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
@ -52,6 +53,7 @@ var (
DisabledRepoUnits []string
DefaultRepoUnits []string
DefaultForkRepoUnits []string
DefaultMirrorRepoUnits []string
PrefixArchiveFiles bool
DisableMigrations bool
DisableStars bool
@ -175,6 +177,7 @@ var (
DisabledRepoUnits: []string{},
DefaultRepoUnits: []string{},
DefaultForkRepoUnits: []string{},
DefaultMirrorRepoUnits: []string{},
PrefixArchiveFiles: true,
DisableMigrations: false,
DisableStars: false,

View file

@ -56,7 +56,7 @@ var SSH = struct {
Domain: "",
Port: 22,
ServerCiphers: []string{"chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"},
ServerKeyExchanges: []string{"curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
ServerKeyExchanges: []string{"mlkem768x25519-sha256", "curve25519-sha256", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group14-sha256", "diffie-hellman-group14-sha1"},
ServerMACs: []string{"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1"},
KeygenPath: "",
MinimumKeySizeCheck: true,

View file

@ -3,6 +3,10 @@
package structs
import (
"time"
)
// ActionRunJob represents a job of a run
// swagger:model
type ActionRunJob struct {
@ -23,3 +27,54 @@ type ActionRunJob struct {
// the action run job status
Status string `json:"status"`
}
// ActionRun represents an action run
// swagger:model
type ActionRun struct {
// the action run id
ID int64 `json:"id"`
// the action run's title
Title string `json:"title"`
// the repo this action is part of
Repo *Repository `json:"repository"`
// the name of workflow file
WorkflowID string `json:"workflow_id"`
// a unique number for each run of a repository
Index int64 `json:"index_in_repo"`
// the user that triggered this action run
TriggerUser *User `json:"trigger_user"`
// the cron id for the schedule trigger
ScheduleID int64
// the commit/tag/… the action run ran on
PrettyRef string `json:"prettyref"`
// has the commit/tag/… the action run ran on been deleted
IsRefDeleted bool `json:"is_ref_deleted"`
// the commit sha the action run ran on
CommitSHA string `json:"commit_sha"`
// If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow.
IsForkPullRequest bool `json:"is_fork_pull_request"`
// may need approval if it's a fork pull request
NeedApproval bool `json:"need_approval"`
// who approved this action run
ApprovedBy int64 `json:"approved_by"`
// the webhook event that causes the workflow to run
Event string `json:"event"`
// the payload of the webhook event that causes the workflow to run
EventPayload string `json:"event_payload"`
// the trigger event defined in the `on` configuration of the triggered workflow
TriggerEvent string `json:"trigger_event"`
// the current status of this run
Status string `json:"status"`
// when the action run was started
Started time.Time `json:"started,omitempty"`
// when the action run was stopped
Stopped time.Time `json:"stopped,omitempty"`
// when the action run was created
Created time.Time `json:"created,omitempty"`
// when the action run was last updated
Updated time.Time `json:"updated,omitempty"`
// how long the action run ran for
Duration time.Duration `json:"duration,omitempty"`
// the url of this action run
HTMLURL string `json:"html_url"`
}

View file

@ -119,6 +119,7 @@ var (
_ Payloader = &RepositoryPayload{}
_ Payloader = &ReleasePayload{}
_ Payloader = &PackagePayload{}
_ Payloader = &ActionPayload{}
)
// _________ __
@ -484,3 +485,36 @@ type PackagePayload struct {
func (p *PackagePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// _ _ _
// / \ ___| |_(_) ___ _ __
// / _ \ / __| __| |/ _ \| '_ \
// / ___ \ (__| |_| | (_) | | | |
// /_/ \_\___|\__|_|\___/|_| |_|
// this name is ridiculous, yes
// it's the sub-type of hook that has something to do with Forgejo Actions
type HookActionAction string
const (
HookActionFailure HookActionAction = "failure"
HookActionRecover HookActionAction = "recover"
HookActionSuccess HookActionAction = "success"
)
// ActionPayload payload for action webhooks
type ActionPayload struct {
Action HookActionAction `json:"action"`
Run *ActionRun `json:"run"`
// the status of this run before it completed
// this must be a not done status
PriorStatus string `json:"prior_status"`
// the last run for the same workflow
// could be nil when Run is the first for it's workflow
LastRun *ActionRun `json:"last_run,omitempty"`
}
// JSONPayload return payload information
func (p *ActionPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}

View file

@ -32,3 +32,23 @@ type ActionTaskResponse struct {
Entries []*ActionTask `json:"workflow_runs"`
TotalCount int64 `json:"total_count"`
}
// ActionRun represents an ActionRun
type RepoActionRun struct {
ID int64 `json:"id"`
Name string `json:"name"`
RunNumber int64 `json:"run_number"`
Event string `json:"event"`
Status string `json:"status"`
HeadBranch string `json:"head_branch"`
HeadSHA string `json:"head_sha"`
WorkflowID string `json:"workflow_id"`
URL string `json:"url"`
TriggeringActor *User `json:"triggering_actor"`
}
// ListActionRunResponse return a list of ActionRun
type ListRepoActionRunResponse struct {
Entries []*RepoActionRun `json:"workflow_runs"`
TotalCount int64 `json:"total_count"`
}

View file

@ -75,6 +75,11 @@ func IsValidExternalURL(uri string) bool {
return true
}
// IsValidReleaseAssetURL checks if the URL is valid for external release assets
func IsValidReleaseAssetURL(uri string) bool {
return IsValidURL(uri)
}
// IsValidExternalTrackerURLFormat checks if URL matches required syntax for external trackers
func IsValidExternalTrackerURLFormat(uri string) bool {
if !IsValidExternalURL(uri) {

View file

@ -4,6 +4,7 @@
package webhook
// HookEvents is a set of web hook events
// update TestCreateWebhook in models/webhook/webhook_test.go when adding or changing values here
type HookEvents struct {
Create bool `json:"create"`
Delete bool `json:"delete"`
@ -26,9 +27,12 @@ type HookEvents struct {
Repository bool `json:"repository"`
Release bool `json:"release"`
Package bool `json:"package"`
ActionRunFailure bool `json:"action_run_failure"`
ActionRunRecover bool `json:"action_run_recover"`
ActionRunSuccess bool `json:"action_run_success"`
}
// HookEvent represents events that will delivery hook.
// HookEvent represents events that will deliver a hook.
type HookEvent struct {
PushOnly bool `json:"push_only"`
SendEverything bool `json:"send_everything"`

View file

@ -7,6 +7,7 @@ package webhook
type HookEventType string
// Types of hook events
// update TestCreateWebhook in models/webhook/webhook_test.go when adding or changing values here
const (
HookEventCreate HookEventType = "create"
HookEventDelete HookEventType = "delete"
@ -33,6 +34,9 @@ const (
HookEventPackage HookEventType = "package"
HookEventSchedule HookEventType = "schedule"
HookEventWorkflowDispatch HookEventType = "workflow_dispatch"
HookEventActionRunFailure HookEventType = "action_run_failure"
HookEventActionRunRecover HookEventType = "action_run_recover"
HookEventActionRunSuccess HookEventType = "action_run_success"
)
// Event returns the HookEventType as an event string
@ -65,6 +69,12 @@ func (h HookEventType) Event() string {
return "repository"
case HookEventRelease:
return "release"
case HookEventActionRunFailure:
return "action_run_failure"
case HookEventActionRunRecover:
return "action_run_recover"
case HookEventActionRunSuccess:
return "action_run_success"
}
return ""
}

View file

@ -2915,6 +2915,13 @@ comment.blocked_by_user = Komentování není možné, protože jste byli zablok
sync_fork.branch_behind_few = Tato větev je %[1]d revizí pozadu za %[2]s
sync_fork.button = Synchronizovat
sync_fork.branch_behind_one = Tato větev je %[1]d revizi pozadu za %[2]s
settings.event_action_failure = Selhání
settings.event_action_failure_desc = Běh akce selhal.
settings.event_action_recover = Obnovit
settings.event_action_success = Úspěch
settings.event_action_success_desc = Běh akce byl úspěšný.
settings.event_header_action = Události běhu akce
settings.event_action_recover_desc = Běh akce byl úspěšný, předchozí běh akce ve stejném workflow selhal.
[graphs]
component_loading_info = Tohle může chvíli trvat…

View file

@ -10,7 +10,7 @@ logo = Logo
sign_in = Login
sign_in_with_provider = Login med %s
sign_in_or = eller
sign_out = Logud
sign_out = Log ud
sign_up = Register
return_to_forgejo = Vend tilbage til Forgejo
new_repo.title = Ny repository
@ -1432,7 +1432,7 @@ issues.new.no_items = Ingen elementer
issues.new.milestone = Milepæl
issues.new.no_milestone = Ingen milepæl
issues.filter_assignees = Filter tildelt
issues.filter_milestones = Filter Milepæl
issues.filter_milestones = Filter milepæl
issues.filter_projects = Filter projekt
issues.filter_labels = Filter etiket
issues.filter_reviewers = Filter anmelder
@ -2018,7 +2018,7 @@ settings.lfs_pointers.inRepo = i depot
settings.lfs_pointers.exists = Eksisterer i lager
settings.lfs_pointers.accessible = Tilgængeligt for bruger
signing.wont_sign.not_signed_in = Du er ikke logget ind.
wiki.welcome = Velkommen til Wikien
wiki.welcome = Velkommen til wikien
milestones.modify = Opdater milepæl
milestones.edit_success = Milepæl "%s" er blevet opdateret.
milestones.filter_sort.least_issues = Mindst problemer
@ -2262,7 +2262,7 @@ settings.wiki_delete_notices_1 = - Dette vil permanent slette og deaktivere depo
settings.wiki_branch_rename_failure = Det lykkedes ikke at normalisere depotwikiens filialnavn.
settings.add_collaborator_duplicate = Samarbejdspartneren er allerede føjet til dette depot.
settings.add_collaborator_owner = Kan ikke tilføje en ejer som samarbejdspartner.
settings.collaborator_deletion = Fjern Samarbejdspartner
settings.collaborator_deletion = Fjern samarbejdspartner
settings.collaborator_deletion_desc = Fjernelse af en samarbejdspartner vil tilbagekalde deres adgang til dette depot. Vil du fortsætte?
settings.add_team_duplicate = Teamet har allerede depotet
settings.add_collaborator_blocked_our = Samarbejdspartneren kan ikke tilføjes, fordi depots ejer har blokeret dem.
@ -2728,6 +2728,13 @@ comment.blocked_by_user = Det er ikke muligt at kommentere, fordi du er blokeret
sync_fork.branch_behind_few = Denne gren er %[1]d commits bag %[2]s
sync_fork.button = Sync
sync_fork.branch_behind_one = Denne gren er %[1]d commit bag %[2]s
settings.event_header_action = Handling Run-begivenheder
settings.event_action_failure = Mislykket
settings.event_action_success_desc = Handlingen blev udført.
settings.event_action_success = Success
settings.event_action_recover_desc = Handlingskørsel lykkedes efter at den sidste handlingskørsel i samme arbejdsgang mislykkedes.
settings.event_action_failure_desc = Handlingskørsel sluttede som en fejl.
settings.event_action_recover = Gendan
[notification]
watching = Overvåger
@ -3529,8 +3536,8 @@ composer.install = For at installere pakken ved hjælp af Composer skal du køre
container.multi_arch = OS / Arch
rubygems.required.ruby = Kræver Ruby version
swift.install = Tilføj pakken i din <code>Package.swift</code>-fil:
settings.link.select = Vælg Depot
settings.link.button = Opdater Depot Link
settings.link.select = Vælg depot
settings.link.button = Opdater depot link
settings.link.error = Kunne ikke opdatere depotlinket.
owner.settings.cargo.initialize.success = Cargo-indekset blev oprettet.
owner.settings.cargo.rebuild.description = Genopbygning kan være nyttig, hvis indekset ikke er synkroniseret med de lagrede Cargo-pakker.

View file

@ -745,7 +745,7 @@ social=Soziale Konten
applications=Anwendungen
orgs=Organisationen
repos=Repositorys
delete=Konto löschen
delete=Account löschen
twofa=Zwei-Faktor-Authentifizierung (TOTP)
account_link=Verknüpfte Benutzerkonten
organization=Organisationen
@ -1511,7 +1511,7 @@ projects.card_type.images_and_text=Bilder und Text
projects.card_type.text_only=Nur Text
issues.desc=Verwalte Bug-Reports, Aufgaben und Meilensteine.
issues.filter_assignees=Filter
issues.filter_assignees=Verantwortliche filtern
issues.filter_milestones=Meilenstein filtern
issues.filter_projects=Projekt filtern
issues.filter_labels=Label filtern
@ -4031,7 +4031,7 @@ repo_kind = Repos suchen …
user_kind = Benutzer suchen …
org_kind = Orgs suchen …
team_kind = Teams suchen …
code_kind = Code suchen…
code_kind = Code durchsuchen
package_kind = Pakete suchen …
project_kind = Projekte suchen …
branch_kind = Branches suchen …

View file

@ -2486,6 +2486,13 @@ settings.event_pull_request_review_request_desc = Pull request review requested
settings.event_pull_request_approvals = Pull request approvals
settings.event_pull_request_merge = Pull request merge
settings.event_pull_request_enforcement = Enforcement
settings.event_header_action = Action Run events
settings.event_action_failure = Failure
settings.event_action_failure_desc = Action Run ended as failure.
settings.event_action_recover = Recover
settings.event_action_recover_desc = Action Run succeeded after last Action Run in the same workflow failed.
settings.event_action_success = Success
settings.event_action_success_desc = Action Run succeeded.
settings.event_package = Package
settings.event_package_desc = Package created or deleted in a repository.
settings.branch_filter = Branch filter
@ -2978,8 +2985,6 @@ teams.invite_team_member.list = Pending invitations
teams.delete_team_title = Delete team
teams.delete_team_desc = Deleting a team revokes repository access from its members. Continue?
teams.delete_team_success = The team has been deleted.
teams.read_permission_desc = This team grants <strong>Read</strong> access: members can view and clone team repositories.
teams.write_permission_desc = This team grants <strong>Write</strong> access: members can read from and push to team repositories.
teams.admin_permission_desc = This team grants <strong>Administrator</strong> access: members can read from, push to and add collaborators to team repositories.
teams.create_repo_permission_desc = Additionally, this team grants <strong>Create repository</strong> permission: members can create new repositories in organization.
teams.repositories = Team repositories

View file

@ -103,7 +103,7 @@ ok = Bone
download_logs = Elsuti protokolojn
unknown = Nekonata
issues = Eraroj
error404 = Aŭ tiu ĉi paĝo <strong>ne ekzistas</strong> aŭ <strong>vi ne rajtas</strong> vidi ĝin.
error404 = Aŭ tiu ĉi paĝo <strong>ne ekzistas</strong>, <strong>estis forigita</strong> aŭ <strong>vi ne rajtas</strong> vidi ĝin.
retry = Reprovi
activities = Aktivecoj
confirm_delete_selected = Konfirmi forigon de ĉiu elektito?
@ -171,6 +171,7 @@ table_modal.placeholder.header = Kapo
table_modal.placeholder.content = Enhavo
table_modal.label.rows = Horizontaloj
table_modal.label.columns = Vertikaloj
link_modal.description = Priskribo
[aria]
navbar = Esplora breto
@ -523,6 +524,7 @@ totp_enrolled.text_1.has_webauthn = Vi ĵus aktivigis TOTP-n por via konto. Tio
totp_enrolled.text_1.no_webauthn = Vi ĵus aktivigis TOTP-n por via konto. Tio volas diri ke por ĉiuj venontaj salutoj al via konto, vi devos uzi TOTP-n kiel 2FA metodo.
removed_security_key.no_2fa = Ne estas aliaj 2FA agorditaj metodoj, tio estas ke ne plus necesas uzi 2FA-n por saluti.
totp_disabled.no_2fa = Ne estas plu aliaj 2FA agorditaj metodoj, tio estas ke ne plus necesas uzi 2FA-n por saluti.
account_security_caution.text_1 = Se tio estis vi, vi povas sekure ignori ĉi tiun retmesaĝon.
[form]
TeamName = Gruponomo
@ -861,30 +863,30 @@ npm.details.tag = Etikedo
[search]
search = Serĉi...
search = Serĉi
regexp = RegEsp
milestone_kind = Serĉi celojn...
code_search_by_git_grep = Nunaj rezultoj de kodoserĉo estas provizitaj de "git grep". Eble estas plibonaj rezultoj se la retejestro aktivigas la indeksilon de kodo.
code_search_unavailable = Kodoserĉo ne haveblas nune. Bonvolu kontakti la retejestron.
package_kind = Serĉi pakojn...
package_kind = Serĉi pakojn
type_tooltip = Serĉotipo
user_kind = Serĉi uzantojn...
user_kind = Serĉi uzantojn
fuzzy_tooltip = Inkluzivas rezultojn proksime kongruantajn kun la serĉoterminoj
repo_kind = Serĉi deponejojn...
org_kind = Serĉi organizaĵojn...
code_kind = Serĉi kodon...
project_kind = Serĉi projektojn...
team_kind = Serĉi teamojn...
repo_kind = Serĉi deponejojn
org_kind = Serĉi organizaĵojn
code_kind = Serĉi kodon
project_kind = Serĉi projektojn
team_kind = Serĉi teamojn
keyword_search_unavailable = Serĉo per ŝlosilvortoj ne haveblas nune. Bonvolu kontakti la retejestron.
union = Ŝlosilvortoj
union_tooltip = Inkluzivas rezultojn kongruantajn kun la ajnaj blankaspacitaj ŝlosilvortoj
commit_kind = Serĉi enmetojn...
commit_kind = Serĉi enmetojn
no_results = Ne trovis kongruantajn rezultojn.
exact = Ĝusta
exact_tooltip = Inkluzivas nur rezultojn kongruantajn kun la ĝustaj serĉoterminoj
issue_kind = Serĉi erarojn...
regexp_tooltip = Interpretas la serĉoterminoj kiel regulesprimo
fuzzy = Svaga
branch_kind = Serĉi disbranĉigojn...
branch_kind = Serĉi disbranĉigojn
runner_kind = Serĉi rulantojn...
pull_kind = Serĉi tirpetojn...

View file

@ -8,7 +8,7 @@ sign_in=Kirjaudu sisään
sign_in_or=tai
sign_out=Kirjaudu ulos
sign_up=Rekisteröidy
link_account=Yhdistä tili
link_account=Linkitä tili
register=Rekisteröidy
version=Versio
powered_by=Voimanlähteenä %s
@ -23,7 +23,7 @@ toc=Sisällysluettelo
licenses=Lisenssit
return_to_forgejo=Palaa Forgejohon
username=Käyttäjätunnus
username=Käyttäjänimi
email=Sähköpostiosoite
password=Salasana
access_token=Pääsypoletti
@ -31,7 +31,7 @@ re_type=Vahvista salasana
captcha=CAPTCHA
twofa=Kaksivaiheinen todennus
twofa_scratch=Kaksivaiheinen kertakäyttöinen koodi
passcode=Tunnuskoodi
passcode=Pääsykoodi
webauthn_insert_key=Aseta turva-avaimesi
webauthn_sign_in=Paina turva-avaimesi painiketta. Jos turva-avaimessasi ei ole painiketta, irrota se ja aseta uudelleen.
@ -40,7 +40,7 @@ webauthn_use_twofa=Käytä kaksivaihesta todennusta puhelimestasi
webauthn_error=Turva-avainta ei voitu lukea.
webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia.
webauthn_error_unknown=Tuntematon virhe. Yritä uudelleen.
webauthn_error_insecure=`WebAuthn tukee vain suojattuja yhteyksiä. Testaukseen HTTP:n yli, voit käyttää osoitetta "localhost" tai "127.0.0.1"`
webauthn_error_insecure=WebAuthn tukee vain suojattuja yhteyksiä. Testatessa HTTP-yhteydellä voit käyttää osoitetta "localhost" tai "127.0.0.1"
webauthn_error_unable_to_process=Palvelin ei pystynyt käsittelemään pyyntöä.
webauthn_error_duplicated=Turva-avainta ei ole sallittu tässä pyynnössä. Varmista, ettei avainta ole jo rekisteröity.
webauthn_error_empty=Sinun täytyy asettaa nimi tälle avaimelle.
@ -228,22 +228,22 @@ report_message = Jos uskot tämän olevan Forgejon virhe, etsi ongelmia <a href=
app_desc=Kivuton, itsehostattu Git-palvelu
install=Helppo asentaa
platform=Alustariippumaton
platform_desc=Forgejo on mahdollista suorittaa vapaissa käyttöjärjestelmissä kuten Linux ja FreeBSD, ja se toimii eri suoritinarkkitehtuureilla. Valitse omasi!
platform_desc=Forgejo on mahdollista suorittaa Linuxin ja FreeBSD:n kaltaisissa vapaissa käyttöjärjestelmissä, ja se toimii eri suoritinarkkitehtuureilla. Valitse omasi!
lightweight=Kevyt
lightweight_desc=Forgejolla on vähäiset vähimmäisvaatimukset, joten se toimii jopa halvassa Raspberry Pi:ssä. Säästä koneesi energiaa!
license=Avoin lähdekoodi
license_desc=Mene ja lataa <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Liity tekemään <a target="_blank" rel="noopener noreferrer" href="%[2]s">projektista</a> entistäkin parempi. Älä ujostele avustamista!
install_desc = <a target="_blank" rel="noopener noreferrer" href="%[1]s">Suorita alustallesi sopiva binääritiedosto</a>, <a target="_blank" rel="noopener noreferrer" href="%[2]s">kontita se</a>, tai <a target="_blank" rel="noopener noreferrer" href="%[3]s">hanki se paketoituna</a>.
install_desc = <a target="_blank" rel="noopener noreferrer" href="%[1]s">Suorita alustallesi tarkoitettu binääritiedosto</a>, <a target="_blank" rel="noopener noreferrer" href="%[2]s">kontita se</a>, tai <a target="_blank" rel="noopener noreferrer" href="%[3]s">hanki se paketoituna</a>.
[install]
install=Asennus
title=Aloitusasetukset
docker_helper=Jos ajat Forgejoa Dockerin sisällä, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a> ennen minkään asetuksen muuttamista.
docker_helper=Jos suoritat Forgejoa kontitettuna, lue <a target="_blank" rel="noopener noreferrer" href="%s">ohjeet</a>, ennen kuin muutat yhtäkään asetusta.
require_db_desc=Forgejo tarvitsee toimiakseen MySQL-, PostgreSQL-, SQLite3- tai TiDB- (MySQL-protokolla) tietokannan.
db_title=Tietokannan asetukset
db_type=Tietokannan tyyppi
host=Isäntä
user=Käyttäjätunnus
user=Käyttäjänimi
password=Salasana
db_name=Tietokannan nimi
db_schema=Skeema
@ -259,8 +259,8 @@ err_empty_db_path=SQLite3-tietokannan polku ei voi olla tyhjä.
no_admin_and_disable_registration=Et voi kytkeä rekisteröintiä pois luomatta sitä ennen ylläpitotiliä.
err_empty_admin_password=Ylläpitäjän salasana ei voi olla tyhjä.
err_empty_admin_email=Ylläpitäjän sähköpostiosoite ei voi olla tyhjä.
err_admin_name_is_reserved=Ylläpitäjän käyttäjätunnus on virheellinen; käyttäjätunnus on varattu
err_admin_name_is_invalid=Ylläpitäjän käyttäjätunnus on virheellinen
err_admin_name_is_reserved=Ylläpitäjän käyttäjänimi on virheellinen; käyttäjänimi on varattu
err_admin_name_is_invalid=Ylläpitäjän käyttäjänimi on virheellinen
general_title=Yleiset asetukset
app_name=Instanssin otsikko
@ -286,7 +286,7 @@ smtp_addr=SMTP-isäntä
smtp_port=SMTP-portti
smtp_from=Lähetä sähköpostit osoitteella
smtp_from_helper=Sähköpostiosoite, jota Forgejo käyttää. Kirjoita pelkkä sähköpostiosoite tai "Nimi” <email@example.com> -muodossa.
mailer_user=SMTP-käyttäjätunnus
mailer_user=SMTP-käyttäjänimi
mailer_password=SMTP-salasana
register_confirm=Vaadi sähköpostinvahvistus rekisteröinnin edellytykseksi
mail_notify=Ota sähköposti-ilmoitukset käyttöön
@ -326,7 +326,7 @@ default_keep_email_private.description=Piilota oletusarvoisesti uusien käyttäj
default_enable_timetracking=Ota ajanseuranta oletusarvoisesti käyttöön
default_enable_timetracking.description=Salli ajanseuranta-ominaisuuden käyttöönotto oletuksena uusille tietovarastoille.
no_reply_address=Piilotetun sähköpostin toimialue
no_reply_address_helper=Verkkotunnuksen nimi käyttäjille, joilla on piilotettu sähköpostiosoite. Esimerkiksi käyttäjätunnus 'joe' kirjataan Git-palveluun nimellä 'joe@noreply.example.org' jos piilotetun sähköpostiosoitteen arvoksi on asetettu 'noreply.example.org'.
no_reply_address_helper=Verkkotunnuksen nimi käyttäjille, joilla on piilotettu sähköpostiosoite. Esimerkiksi käyttäjänimi 'joe' kirjataan Git-palveluun nimellä 'joe@noreply.example.org' jos piilotetun sähköpostiosoitteen arvoksi on asetettu 'noreply.example.org'.
password_algorithm=Salasanan hajautusalgoritmi
enable_update_checker_helper_forgejo = Se tarkistaa väliajoin uusia Forgejo-versioita tutkimalla TXT DNS -tietueen osoitteesta release.forgejo.org .
invalid_admin_setting = Ylläpitotilin asetukset eivät kelpaa: %v
@ -354,7 +354,7 @@ smtp_from_invalid = "Lähetä sähköpostit osoitteella"-osoite on epäkelvollin
err_admin_name_pattern_not_allowed = Ylläpitäjän käyttäjänimi on epäkelpo, se vastaa varattua kaavaa
[home]
uname_holder=Käyttäjätunnus tai sähköpostiosoite
uname_holder=käyttäjänimi tai sähköpostiosoite
password_holder=Salasana
switch_dashboard_context=Vaihda kojelaudan kontekstia
my_repos=Tietovarastot
@ -410,10 +410,10 @@ remember_me=Muista tämä laite
forgot_password_title=Unohtuiko salasana
forgot_password=Unohtuiko salasana?
sign_up_now=Tarvitsetko tilin? Rekisteröidy nyt.
confirmation_mail_sent_prompt=Uusi varmistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa saamaasi linkkiä seuraavan %s aikana viimeistelläksesi rekisteröinnin. Mikäli annettu sähköpostiosoite on väärin, voit kirjautua sisään ja pyytää uutta varmistussähköpostia toiseen osoitteeseen.
confirmation_mail_sent_prompt=Uusi vahvistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa saamaasi linkkiä seuraavan %s aikana viimeistelläksesi rekisteröinnin. Mikäli annettu sähköpostiosoite on väärin, voit kirjautua sisään ja pyytää uutta vahvistussähköpostia toiseen osoitteeseen.
must_change_password=Vaihda salasanasi
allow_password_change=Vaadi käyttäjää vaihtamaan salasanansa (suositeltava)
reset_password_mail_sent_prompt=Varmistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa annettua linkkiä seuraavan %s aikana saadaksesi tilin palauttamisen valmiiksi.
reset_password_mail_sent_prompt=Vahvistussähköposti on lähetetty osoitteeseen <b>%s</b>. Tarkista sähköpostisi ja seuraa annettua linkkiä seuraavan %s aikana saadaksesi tilin palauttamisen valmiiksi.
active_your_account=Aktivoi tilisi
account_activated=Tili on aktivoitu
prohibit_login=Tili on jäädytetty
@ -431,7 +431,7 @@ verify=Vahvista
scratch_code=Kertakäyttökoodi
use_scratch_code=Käytä kertakäyttökoodia
twofa_scratch_used=Olet käyttänyt kertakäyttökoodisi. Sinut on uudelleenohjattu kaksivaiheisen kirjautumisen asetussivulle, jotta voit kytkeä sen pois tai luoda uuden kertakäyttökoodin.
twofa_passcode_incorrect=Salasanasi on väärä. Jos olet hukannut laitteesi, käytäthän kertakäyttökoodia sisäänkirjautumiseen.
twofa_passcode_incorrect=Pääsykoodi on väärä. Jos olet hukannut laitteesi, käytäthän kertakäyttökoodia sisäänkirjautumiseen.
twofa_scratch_token_incorrect=Kertakäyttökoodisi on virheellinen.
login_userpass=Kirjaudu sisään
tab_openid=OpenID
@ -440,7 +440,7 @@ oauth_signup_title=Viimeistele uusi tili
oauth_signup_submit=Viimeistele tili
oauth_signin_tab=Linkitä olemassa olevaan tiliin
oauth_signin_title=Kirjaudu sisään valtuuttaaksesi linkitetyn tilin
oauth_signin_submit=Yhdistä tiliin
oauth_signin_submit=Linkitä tili
oauth.signin.error.access_denied=Valtuutuspyyntö on evätty.
openid_connect_submit=Yhdistä
openid_connect_title=Yhdistä olemassa olevaan tiliin
@ -483,7 +483,7 @@ prohibit_login_desc = Tilisi käyttö instanssin kanssa on estetty. Ota yhteytt
[mail]
view_it_on=Näytä %s
link_not_working_do_paste=Eikö linkki toimi? Yritä kopioida ja liittää se selaimesi osoitepalkkiin.
link_not_working_do_paste=Eikö linkki toimi? Kopioi ja liitä se selaimesi osoiteriville.
hi_user_x=Hei <b>%s</b>,
activate_account=Ole hyvä ja aktivoi tilisi
@ -491,7 +491,7 @@ activate_account=Ole hyvä ja aktivoi tilisi
activate_email=Vahvista sähköpostiosoitteesi
register_notify=Tervetuloa %s-palveluun
register_notify.text_2=Voit nyt kirjautua tilillesi käyttäjätunnuksella: %s
register_notify.text_2=Voit nyt kirjautua tilillesi käyttäjänimellä: %s
reset_password=Palauta käyttäjätili
reset_password.title=%s, olet pyytänyt tilisi palauttamista
@ -517,7 +517,7 @@ removed_security_key.subject = Turva-avain on poistettu
removed_security_key.text_1 = Turva-avain "%[1]s" on poistettu tililtäsi.
team_invite.text_2 = Napsauta seuraavaa linkkiä liittyäksesi tiimiin:
activate_account.text_1 = Hei <b>%[1]s</b>, kiitos kun rekisteröidyit palveluun %[2]s!
activate_account.text_2 = Aktivoidaksesi tilin, napsauta alla olevaa linkkiä aikaikkunan <b>%s</b> sisällä:
activate_account.text_2 = Aktivoi tilisi napsauttamalla alla olevaa linkkiä aikaikkunan <b>%s</b> sisällä:
totp_disabled.subject = TOTP on poistettu käytöstä
primary_mail_change.subject = Ensisijainen sähköpostiosoitteesi on vaihdettu
admin.new_user.user_info = Käyttäjätiedot
@ -570,7 +570,7 @@ modify=Päivitä
confirm = Vahvista
[form]
UserName=Käyttäjätunnus
UserName=Käyttäjänimi
RepoName=Tietovaraston nimi
Email=Sähköpostiosoite
Password=Salasana
@ -601,14 +601,14 @@ captcha_incorrect=CAPTCHA-koodi on virheellinen.
password_not_match=Salasanat eivät täsmää.
lang_select_error=Valitse kieli listalta.
username_been_taken=Käyttäjätunnus on jo varattu.
username_been_taken=Käyttäjänimi on jo varattu.
repo_name_been_taken=Tietovaraston nimi on jo käytössä.
repository_force_private=Pakotettu yksityisyys käytössä: yksityisiä tietovarastoja ei voida muuttaa julkisiksi.
org_name_been_taken=Organisaation nimi on jo käytössä.
team_name_been_taken=Tiimin nimi on jo varattu.
email_been_used=Sähköpostiosoite on jo käytössä.
email_invalid=Sähköpostiosoite on virheellinen.
username_password_incorrect=Käyttäjätunnus tai salasana on virheellinen.
username_password_incorrect=Käyttäjänimi tai salasana on virheellinen.
password_lowercase_one=Ainakin yksi pieni kirjan
password_uppercase_one=Ainakin yksi iso kirjain
password_digit_one=Ainakin yksi numero
@ -663,6 +663,10 @@ org_still_own_repo = Organisaatio omistaa yhden tai useamman tietovaraston. Pois
org_still_own_packages = Organisaatio omistaa yhden tai useamman paketin. Poista ne ensin.
team_no_units_error = Salli pääsy vähintään yhteen tietovaraston osioon.
repository_files_already_exist.adopt_or_delete = Tässä tietovarastossa on jo tiedostoja. Omaksu ne itsellesi tai poista ne.
username_change_not_local_user = Ei-paikallisten käyttäjien ei sallita vaihtaa käyttäjänimeä.
admin_cannot_delete_self = Et voi poistaa itseäsi, kun olet ylläpitäjä. Poista ensin ylläpito-oikeudet itseltäsi.
username_claiming_cooldown = Käyttäjänimeä ei voi ottaa käyttöön, koska siihen kohdistuva suojaamisjakso ei ole vielä päättynyt. Käyttäjänimen voi ottaa käyttöön %[1]s.
email_domain_is_not_allowed = Käyttäjän sähköpostiosoitteen <b>%s</b> verkkotunnus on ristiriidassa EMAIL_DOMAIN_ALLOWLIST:in tai EMAIL_DOMAIN_BLOCKLIST:in kanssa. Varmista, että olen asettanut sähköpostiosoitteen oikein.
[user]
@ -694,11 +698,11 @@ unblock = Poista esto
following_one = %d seurataan
block_user.detail = Huomaa, että käyttäjän estämisellä on muita vaikutuksia, kuten:
show_on_map = Näytä paikka kartalla
form.name_chars_not_allowed = Käyttäjätunnus "%s" sisältää virheellisiä merkkejä.
form.name_chars_not_allowed = Käyttäjänimi "%s" sisältää virheellisiä merkkejä.
follow_blocked_user = Et voi seurata tätä käyttäjää, koska olet estänyt kyseisen käyttäjän tai kyseinen käyttäjä on estänyt sinut.
disabled_public_activity = Käyttäjä on poistanut käytöstä toiminnan julkisen näkyvyyden.
form.name_reserved = Käyttäjätunnus "%s" on varattu.
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu käyttäjätunnuksessa.
form.name_reserved = Käyttäjänimi "%s" on varattu.
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu käyttäjänimessä.
public_activity.visibility_hint.admin_private = Aktiivisuus on näkyvissä sinulle, koska olet ylläpitäjä, mutta käyttäjä haluaa pitää aktiivisuutensa yksityisenä.
public_activity.visibility_hint.self_private_profile = Aktiivisuutesi on näkyvissä vain sinulle ja instanssin ylläpitäjille, koska profiilisi on yksityinen. <a href="%s">Määritä</a>.
watched = Tarkaillut tietovarastot
@ -727,7 +731,7 @@ organization=Organisaatiot
webauthn=Kaksivaiheinen todennus (Turva-avaimet)
public_profile=Julkinen profiili
password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjätunnustaan. Ole hyvä ja ota yhteyttä sivuston ylläpitäjään saadaksesi lisätietoa.
password_username_disabled=Ei-paikalliset käyttäjät eivät voi muuttaa käyttäjänimeään. Ota yhteys sivuston ylläpitoon saadaksesi lisätietoa.
full_name=Koko nimi
website=Verkkosivusto
location=Sijainti
@ -736,14 +740,14 @@ update_profile=Päivitä profiili
update_language=Vaihda kieli
update_language_success=Kieli on päivitetty.
update_profile_success=Profiilisi on päivitetty.
change_username=Käyttäjätunnuksesi on muutettu.
change_username=Käyttäjänimesi on muutettu.
continue=Jatka
cancel=Peruuta
language=Kieli
ui=Teema
hidden_comment_types=Piilotetut kommenttityypit
comment_type_group_reference=Viittaus
comment_type_group_label=Tunniste
comment_type_group_label=Nimilappu
comment_type_group_milestone=Merkkipaalu
comment_type_group_assignee=Osoitettu henkilölle
comment_type_group_title=Otsikko
@ -888,10 +892,10 @@ twofa_enrolled=Tiliisi on otettu käyttöön kaksivaiheinen todennus. Ota kertak
webauthn_nickname=Nimimerkki
manage_account_links=Yhdistetyt tilit
manage_account_links=Linkitetyt tilit
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Forgejo-tiliisi.
link_account=Yhdistä tili
remove_account_link=Poista yhdistetty tili
link_account=Linkitä tili
remove_account_link=Poista linkitetty tili
remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Forgejo-tiliisi linkitetyn tilin kautta. Jatketaanko?
remove_account_link_success=Linkitetty tili on poistettu.
@ -968,14 +972,14 @@ webauthn_alternative_tip = Saatat haluta määrittää lisätodennusmenetelmän.
twofa_disable = Poista kaksivaiheinen todennus käytöstä
twofa_disable_desc = Kaksivaiheisen todennuksen poistaminen asettaa tilisi aiempaa suurempaan uhkaan. Jatketaanko?
update_language_not_found = Kieli "%s" ei ole käytettävissä.
change_username_prompt = Huomio: Käyttäjätunnuksen vaihtaminen muuttaa myös tilisi URL-osoitteen.
change_username_prompt = Huomio: Käyttäjänimen vaihtaminen muuttaa myös tilisi URL-osoitteen.
oauth2_client_secret_hint = Tätä salaisuutta ei näytetä uudelleen, kun olet poistunut sivulta tai päivittänyt sivun. Varmista, että olet ottanut salaisuuden talteen.
blocked_since = Estetty %s lähtien
user_unblock_success = Käyttäjän esto on poistettu.
oauth2_redirect_uris = Uudelleenohjaus-URI:t. Käytä uutta riviä (newline) jokaista URI:a kohden.
oauth2_client_secret = Asiakkaan salaisuus
verify_ssh_key_success = SSH-avain "%s" on vahvistettu.
change_username_redirect_prompt = Vanha käyttäjätunnus uudelleenohjaa, kunnes joku muu ottaa käyttäjätunnuksen käyttönsä.
change_username_redirect_prompt = Vanha käyttäjänimi uudelleenohjaa, kunnes joku muu ottaa käyttäjänimen käyttöönsä.
uploaded_avatar_is_too_big = Lähetetyn tiedoston koko (%d KiB) ylittää enimmäiskoon (%d KiB).
ssh_key_been_used = Tämä SSH-avain on jo lisätty palvelimelle.
verify_gpg_key_success = GPG-avain "%s" on vahvistettu.
@ -1023,9 +1027,16 @@ keep_pronouns_private = Näytä pronominit vain tunnistautuneille käyttäjille
keep_pronouns_private.description = Tämä piilottaa pronominisi käyttäjiltä, jotka eivät ole kirjautuneet sisään.
comment_type_group_issue_ref = Ongelmaviittaus
twofa_scratch_token_regenerated = Kertakäyttöinen palautusavaimesi on nyt %s. Talleta se turvalliseen sijaintiin, koska sitä ei näytetä uudelleen.
change_username_redirect_prompt.with_cooldown.few = Vanha käyttäjätunnus on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjätunnuksen itsellesi suojaamisjakson aikana.
change_username_redirect_prompt.with_cooldown.few = Vanha käyttäjänimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjänimen itsellesi suojaamisjakson aikana.
additional_repo_units_hint_description = Näytä "Ota lisää käyttöön"-vihje tietovarastoissa, missä kaikki saatavilla olevat yksiköt eivät ole käytössä.
change_username_redirect_prompt.with_cooldown.one = Vanha käyttäjätunnus on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjätunnuksen itsellesi suojaamisjakson aikana.
change_username_redirect_prompt.with_cooldown.one = Vanha käyttäjänimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa käyttäjänimen itsellesi suojaamisjakson aikana.
gpg_key_matched_identities = Vastaavat identiteetit:
delete_token_success = Pääsypoletti on poistettu. Sitä käyttävillä sovelluksilla ei ole enää pääsyä tilillesi.
ssh_externally_managed = Tämän käyttäjän SSH-avainta hallitaan ulkoisesti
passcode_invalid = Virheellinen pääsykoodi. Yritä uudelleen.
then_enter_passcode = Kirjoita sovelluksessa näkyvä pääsykoodi:
gpg_key_matched_identities_long = Tähän avaimeen upotetut identiteetit vastaavat tämän käyttäjän seuraavia aktivoituja sähköpostiosoitteita. Kommitit, jotka vastaavat näitä sähköpostiosoitteita, voidaan vahvistaa tällä avaimella.
twofa_failed_get_secret = Salaisuuden saaminen epäonnistui.
[repo]
owner=Omistaja
@ -1048,8 +1059,8 @@ download_tar=Lataa TAR.GZ
repo_desc=Kuvaus
repo_lang=Kieli
repo_gitignore_helper=Valitse .gitignore-mallit
issue_labels=Tunnisteet
issue_labels_helper=Valitse tunnistejoukko
issue_labels=Nimilaput
issue_labels_helper=Valitse nimilappujoukko
license=Lisenssi
license_helper=Valitse lisenssitiedosto
readme=README
@ -1074,14 +1085,14 @@ template.git_hooks=Git-koukut
template.webhooks=Webkoukut
template.topics=Aiheet
template.avatar=Profiilikuva
template.issue_labels=Ongelmatunnisteet
template.issue_labels=Ongelmanimilaput
migrate_items=Migraation kohteet
migrate_items_wiki=Wiki
migrate_items_milestones=Merkkipaalut
migrate_items_labels=Tunnisteet
migrate_items_labels=Nimilaput
migrate_items_issues=Ongelmat
migrate_items_pullrequests=Vetopyynnöt
migrate_items_releases=Julkaisut
@ -1118,7 +1129,7 @@ issues=Ongelmat
pulls=Vetopyynnöt
project_board=Projektit
packages=Paketit
labels=Tunnisteet
labels=Nimilaput
milestones=Merkkipaalut
commits=Kommitit
@ -1129,7 +1140,7 @@ released_this=julkaisi tämän
file_raw=Raaka
file_history=Historia
file_view_raw=Näytä raaka
file_permalink=Pysyvä linkki
file_permalink=Pysyväislinkki
video_not_supported_in_browser=Selaimesi ei tue HTML5:n video-tagia.
audio_not_supported_in_browser=Selaimesi ei tue HTML5:n audio-tagia.
@ -1201,9 +1212,9 @@ issues.desc=Ongelmien, tehtävien ja merkkipaalujen hallinta.
issues.filter_assignees=Suodata käyttäjiä
issues.filter_milestones=Suodata merkkipaalu
issues.new=Uusi ongelma
issues.new.labels=Tunnisteet
issues.new.no_label=Ei tunnisteita
issues.new.clear_labels=Tyhjennä tunnisteet
issues.new.labels=Nimilaput
issues.new.no_label=Ei nimilappuja
issues.new.clear_labels=Tyhjennä nimilaput
issues.new.projects=Projektit
issues.new.no_items=Ei kohteita
issues.new.milestone=Merkkipaalu
@ -1218,11 +1229,11 @@ issues.choose.open_external_link=Avaa
issues.choose.blank=Oletus
issues.no_ref=Haaraa/tagia ei määritelty
issues.create=Luo ongelma
issues.new_label=Uusi tunniste
issues.new_label_placeholder=Tunnisteen nimi
issues.new_label=Uusi nimilappu
issues.new_label_placeholder=Nimilapun nimi
issues.new_label_desc_placeholder=Kuvaus
issues.create_label=Luo tunniste
issues.label_templates.helper=Valitse tunnisteen esiasetus
issues.create_label=Luo nimilappu
issues.label_templates.helper=Valitse nimilapun esiasetus
issues.add_milestone_at=`lisäsi tämän merkkipaaluun <b>%s</b> %s`
issues.change_milestone_at=`vaihtoi merkkipaalun <b>%s</b> merkkipaaluun <b>%s</b> %s`
issues.remove_milestone_at=`poisti tämän <b>%s</b> merkkipaalusta %s`
@ -1232,9 +1243,9 @@ issues.deleted_project=`(poistettu)`
issues.self_assign_at=`itse otti tämän käsittelyyn %s`
issues.change_title_at=`muutti otsikon <b><strike>%s</strike></b> otsikoksi <b>%s</b> %s`
issues.delete_branch_at=`poisti haaran <b>%s</b> %s`
issues.filter_label=Tunniste
issues.filter_label_exclude=`Käytä <code>alt</code> + <code>klikkaus/rivinvaihto</code> poissulkeaksesi tunnisteita`
issues.filter_label_no_select=Kaikki tunnisteet
issues.filter_label=Nimilappu
issues.filter_label_exclude=`Käytä <code>alt</code> + <code>napsautus/rivinvaihto</code> poissulkeaksesi nimilappuja`
issues.filter_label_no_select=Kaikki nimilaput
issues.filter_milestone=Merkkipaalu
issues.filter_project=Projekti
issues.filter_assignee=Käsittelijä
@ -1252,15 +1263,15 @@ issues.filter_sort.recentupdate=Äskettäin päivitetty
issues.filter_sort.leastupdate=Kauiten aikaa sitten päivitetty
issues.filter_sort.mostcomment=Eniten kommentoidut
issues.filter_sort.leastcomment=Vähiten kommentoidut
issues.filter_sort.nearduedate=Lähin määräpäivä
issues.filter_sort.farduedate=Kaukaisin määräpäivä
issues.filter_sort.nearduedate=Lähin eräpäivä
issues.filter_sort.farduedate=Kaukaisin eräpäivä
issues.filter_sort.moststars=Eniten tähtiä
issues.filter_sort.feweststars=Vähiten tähtiä
issues.filter_sort.mostforks=Eniten forkattu
issues.filter_sort.fewestforks=Vähiten forkattu
issues.action_open=Avaa
issues.action_close=Sulje
issues.action_label=Tunniste
issues.action_label=Nimilappu
issues.action_milestone=Merkkipaalu
issues.action_milestone_no_select=Ei merkkipaalua
issues.action_assignee=Osoitettu henkilölle
@ -1291,15 +1302,15 @@ issues.role.member=Jäsen
issues.edit=Muokkaa
issues.cancel=Peruuta
issues.save=Tallenna
issues.label_title=Tunnisteen nimi
issues.label_title=Nimi
issues.label_description=Kuvaus
issues.label_color=Tunnisteen väri
issues.label_count=%d tunnistetta
issues.label_color=Väri
issues.label_count=%d nimilappua
issues.label_open_issues=%d avointa ongelmaa/vetopyyntöä
issues.label_edit=Muokkaa
issues.label_delete=Poista
issues.label_modify=Muokkaa tunnistetta
issues.label_deletion=Poista tunniste
issues.label_modify=Muokkaa nimilappua
issues.label_deletion=Poista nimilappu
issues.label.filter_sort.alphabetically=Aakkosjärjestyksessä
issues.label.filter_sort.reverse_alphabetically=Käänteisessä aakkosjärjestyksessä
issues.label.filter_sort.by_size=Pienin koko
@ -1334,13 +1345,13 @@ issues.add_time_hours=Tuntia
issues.add_time_minutes=Minuuttia
issues.add_time_sum_to_small=Aikaa ei syötetty.
issues.time_spent_from_all_authors=`Käytetty kokonaisaika: %s`
issues.due_date=Määräpäivä
issues.due_date=Eräpäivä
issues.push_commit_1=lisäsi %d kommitin %s
issues.push_commits_n=lisäsi %d kommittia %s
issues.due_date_form=vvvv-kk-pp
issues.due_date_form_edit=Muokkaa
issues.due_date_form_remove=Poista
issues.due_date_not_set=Määräpäivää ei ole asetettu.
issues.due_date_not_set=Eräpäivää ei ole asetettu.
issues.due_date_overdue=Myöhässä
issues.dependency.title=Riippuvuudet
issues.dependency.issue_no_dependencies=Riippuvuuksia ei ole asetettu.
@ -1394,13 +1405,13 @@ pulls.can_auto_merge_desc=Tämä vetopyyntö voidaan yhdistää automaattisesti.
milestones.new=Uusi merkkipaalu
milestones.closed=Suljettu %s
milestones.no_due_date=Ei määräpäivää
milestones.no_due_date=Ei eräpäivää
milestones.open=Avaa uudelleen
milestones.close=Sulje
milestones.create=Luo merkkipaalu
milestones.title=Otsikko
milestones.desc=Kuvaus
milestones.due_date=Määräpäivä (valinnainen)
milestones.due_date=Eräpäivä (valinnainen)
milestones.clear=Tyhjennä
milestones.edit=Muokkaa merkkipaalua
milestones.cancel=Peruuta
@ -1411,7 +1422,7 @@ milestones.filter_sort.least_issues=Vähiten ongelmia
wiki=Wiki
wiki.welcome=Tervetuloa Wikiin.
wiki.welcome=Tervetuloa wikiin.
wiki.welcome_desc=Wikissä voit kirjoittaa ja jakaa dokumentaatiota käyttäjien kesken.
wiki.create_first_page=Luo ensimmäinen sivu
wiki.page=Sivu
@ -1522,9 +1533,9 @@ settings.update_githook=Päivitä koukku
settings.payload_url=Kohde-URL
settings.http_method=HTTP-menetelmä
settings.secret=Salaisuus
settings.slack_username=Käyttäjätunnus
settings.slack_username=Käyttäjänimi
settings.slack_icon_url=Kuvakkeen URL-osoite
settings.discord_username=Käyttäjätunnus
settings.discord_username=Käyttäjänimi
settings.event_desc=Laukaisu päällä:
settings.event_send_everything=Kaikki tapahtumat
settings.event_choose=Mukautetut tapahtumat…
@ -1544,7 +1555,7 @@ settings.event_issues=Muokkaus
settings.event_issues_desc=Ongelma avattu, suljettu, avattu uudelleen tai muokattu.
settings.event_issue_assign=Toimeksianto
settings.event_issue_assign_desc=Ongelma osoitettu tai osoitus poistettu.
settings.event_issue_label_desc=Ongelmatunnisteet lisätty tai poistettu.
settings.event_issue_label_desc=Ongelmanimilaput lisätty tai poistettu.
settings.event_issue_milestone_desc=Merkkipaalu lisätty, poistettu tai muokattu.
settings.event_issue_comment_desc=Ongelman kommentti luotu, muokattu tai poistettu.
settings.event_header_pull_request=Vetopyyntöjen tapahtumat
@ -1744,7 +1755,7 @@ release.detail = Julkaisun tiedot
diff.hide_file_tree = Piilota tiedostopuu
issues.role.owner_helper = Tämä käyttäjä on tämän tietovaraston omistaja.
issues.all_title = Kaikki
issues.label_archived_filter = Näytä arkistoidut tunnisteet
issues.label_archived_filter = Näytä arkistoidut nimilaput
pulls.close = Sulje vetopyyntö
branch.already_exists = Haara nimellä "%s" on jo olemassa.
diff.show_file_tree = Näytä tiedostopuu
@ -1793,7 +1804,7 @@ milestones.deletion_success = Merkkipaalu on poistettu.
project = Projektit
pulls.delete.title = Poistetaanko tämä vetopyyntö?
activity.title.issues_1 = %d ongelma
contributors.contribution_type.filter_label = Avustuksen tyyppi:
contributors.contribution_type.filter_label = Kontribuution tyyppi:
settings.protected_branch.delete_rule = Poista sääntö
settings.archive.success = Tietovarasto arkistoitiin onnistuneesti.
diff.comment.placeholder = Jätä kommentti
@ -1897,7 +1908,7 @@ pulls.expand_files = Laajenna kaikki tiedostot
issues.content_history.delete_from_history = Poista historiasta
milestones.filter_sort.name = Nimi
issues.filter_milestone_all = Kaikki merkkipaalut
issues.filter_label_select_no_label = Ei tunnistetta
issues.filter_label_select_no_label = Ei nimilappua
projects.column.set_default = Aseta oletukseksi
projects.edit_success = Projekti "%s" on päivitetty.
desc.sha256 = SHA256
@ -1942,7 +1953,7 @@ settings.branches.update_default_branch = Päivitä oletushaara
settings.transfer.success = Tietovaraston siirto onnistui.
settings.transfer_abort = Peru siirto
settings.sync_mirror = Synkronoi nyt
settings.mirror_settings.docs.doc_link_title = Kuinka peilaan tietovarastot?
settings.mirror_settings.docs.doc_link_title = Kuinka peilaan tietovarastoja?
tag.create_tag_operation = Luo tagi
branch.rename = Nimeä haara "%s" uudelleen
branch.download = Lataa haara "%s"
@ -2016,9 +2027,9 @@ migrate.git.description = Suorita tietovaraston migraatio mistä tahansa Git-pal
migrate.gitlab.description = Tee migraatio gitlab.comista tai muista GitLab-instansseista.
migrate.gitea.description = Tee migraatio gitea.comista tai muista Gitea-instansseista.
repo_gitignore_helper_desc = Valitse mitä tiedostoja ei seurata yleisimpien kielten mallipohjista. Tyypilliset artefaktit, joita eri kielten koostamistyökalut tuottavat, lisätään .gitignore-tiedostoon oletusarvoisesti.
milestones.filter_sort.latest_due_date = Kaukaisin määräpäivä
milestones.filter_sort.latest_due_date = Kaukaisin eräpäivä
license_helper_desc = Lisenssi määrää, mitä muut voivat ja eivät voi tehdä koodillasi. Etkö ole varma, mikä lisenssi soveltuu projektillesi? Lue <a target="_blank" rel="noopener noreferrer" href="%s">ohje lisenssin valinnasta</a>.
milestones.filter_sort.earliest_due_data = Lähin määräpäivä
milestones.filter_sort.earliest_due_data = Lähin eräpäivä
issues.filter_type.reviewed_by_you = Katselmoitu toimestasi
settings.units.overview = Yleisnäkymä
settings.remove_team_success = Tiimin pääsy tietovarastoon on poistettu.
@ -2185,21 +2196,21 @@ transfer.no_permission_to_accept = Sinulla ei ole oikeutta hyväksyä tätä sii
settings.web_hook_name_feishu = Feishu / Lark Suite
issues.review.reviewers = Katselmoijat
issues.new.no_reviewers = Ei katselmoijia
issues.add_label = lisäsi tunnisteen %s %s
issues.due_date_added = lisäsi määräpäivän %s %s
issues.add_label = lisäsi nimilapun %s %s
issues.due_date_added = lisäsi eräpäivän %s %s
issues.review.add_review_request = pyysi katselmointia käyttäjältä %[1]s %[2]s
issues.ref_pull_from = `<a href="%[3]s">viittasi tähän vetopyyntöön %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
pulls.commit_ref_at = `viittasi tähän vetopyyntöön kommitista <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.review.comment = katselmoi %s
issues.add_labels = lisäsi tunnisteet %s %s
issues.add_labels = lisäsi nimilaput %s %s
issues.review.add_review_requests = pyysi katselmointeja käyttäjiltä %[1]s %[2]s
pulls.blocked_by_official_review_requests = Tämä vetopyyntö on estetty, koska siltä puuttuu hyväksyntä yhdeltä tai useammalta viralliselta katselmoijalta.
issues.author.tooltip.issue = Tämä käyttäjä on tämän ongelman tekijä.
issues.author.tooltip.pr = Tämä käyttäjä on tämän vetopyynnön tekijä.
issues.role.contributor_helper = Tämä käyttäjä on aiemmin kommitoinut tähän tietovarastoon.
settings.event_pull_request_label = Tunnisteet
issues.due_date_remove = poisti määräpäivän %s %s
settings.event_issue_label = Tunnisteet
settings.event_pull_request_label = Nimilaput
issues.due_date_remove = poisti eräpäivän %s %s
settings.event_issue_label = Nimilaput
settings.authorization_header = Authorization-otsake
diff.has_escaped = Tällä rivillä on piilotettuja Unicode-merkkejä
issues.max_pinned = Et voi kiinnittää enempää ongelmia
@ -2211,8 +2222,8 @@ issues.num_reviews_few = %d katselmointia
issues.filter_no_results = Ei tuloksia
issues.filter_no_results_placeholder = Kokeile määrittää eri hakusuodattimet.
projects.edit_subheader = Projektit organisoivat ongelmia ja seuraavat edistymistä.
issues.label_templates.title = Lataa tunnisteen esiasetus
issues.label_deletion_desc = Tunnisteen poistaminen poistaa sen kaikista ongelmista. Jatketaanko?
issues.label_templates.title = Lataa nimilapun esiasetus
issues.label_deletion_desc = Nimilapun poistaminen poistaa sen kaikista ongelmista. Jatketaanko?
issues.attachment.download = `Napsauta ladataksesi "%s"`
issues.review.option.hide_outdated_comments = Piilota vanhentuneet kommentit
issues.review.show_outdated = Näytä vanhentuneet
@ -2223,8 +2234,8 @@ issues.unpin_issue = Poista ongelman kiinnitys
issues.review.outdated_description = Sisältö on muuttunut siitä ajanhetkestä, kun tämä kommentti luotiin
issues.review.option.show_outdated_comments = Näytä vanhentuneet kommentit
issues.review.outdated = Vanhentunut
issues.label_templates.use = Käytä tunnisteen esiasetusta
issues.label_deletion_success = Tunniste on poistettu.
issues.label_templates.use = Käytä nimilapun esiasetusta
issues.label_deletion_success = Nimilappu on poistettu.
issues.cancel_tracking = Hylkää
issues.choose.get_started = Aloitetaan
settings.event_fork = Forkkaus
@ -2239,7 +2250,7 @@ pulls.no_merge_wip = Tätä vetopyyntöä ei voida yhdistää, koska se on merki
pulls.clear_merge_message = Tyhjennä yhdistämisviesti
activity.title.prs_merged_by = %s yhdisti %s
settings.protect_status_check_patterns_desc = Syötä kaavat määrittääksesi, mitkä tilatarkistukset on läpäistävä, ennen kuin haarat voidaan yhdistää tätä sääntöä vastaavaan haaraan. Jokainen rivi määrittää kaavan. Kaavat eivät saa olla tyhjiä.
adopt_search = Syötä käyttäjänimi etsiäksesi omaksumattomia tietovarastoja (jätä tyhjäksi löytääksesi kaikki)
adopt_search = Syötä käyttäjänimi etsiäksesi omaksumattomia tietovarastoja (jätä tyhjäksi löytääksesi kaikki)
pulls.cmd_instruction_merge_warning = <b>Varoitus:</b> Asetusta ”Tunnista manuaalinen yhdistäminen automaattisesti” ei ole otettu käyttöön tässä tietovarastossa. Sinun on merkittävä tämä vetopyyntö manuaalisesti yhdistetyksi jälkikäteen.
pulls.cmd_instruction_merge_desc = Yhdistä muutokset ja päivitä Forgejossa.
pulls.cannot_auto_merge_desc = Tätä vetopyyntöä ei voida yhdistää automaattisesti ristiriitojen vuoksi.
@ -2316,13 +2327,13 @@ migrate_options_lfs = Tee migraatio LFS-tiedostoille
migrate_options_lfs_endpoint.label = LFS-päätepiste
commits.browse_further = Selaa kauemmas
issues.filter_projects = Suodata projekti
issues.filter_labels = Suodata tunniste
issues.filter_labels = Suodata nimilappu
commits.no_commits = Ei yhteisiä kommitteja. "%s" ja "%s" omaavat täysin eri historiat.
projects.column.deletion_desc = Projektin sarakkeen poistaminen siirtää kaikki siihen liittyvät ongelmat oletussarakkeeseen. Jatketaanko?
issues.del_time = Poista tämä aikaloki
migrated_from_fake = Suoritettu migraatio lähteestä %[1]s
migrate.migrate = Tee migraatio lähteestä %s
migrate.migrating_labels = Suoritetaan tunnisteiden migraatiota
migrate.migrating_labels = Suoritetaan nimilappujen migraatiota
file_view_rendered = Näytä renderöitynä
editor.invalid_commit_mail = Virheellinen sähköposti kommitin luomista varten.
sync_fork.branch_behind_one = Tämä haara on %[1]d kommitin jäljessä %[2]s
@ -2360,7 +2371,7 @@ pulls.is_ancestor = Tämä haara on jo sisällytetty kohdehaaraan. Yhdistettäv
pulls.blocked_by_rejection = Tämä vetopyyntö sisältää virallisen katselmoijan vaatimisia muutoksia.
pulls.status_checks_success = Kaikki tarkistukset onnistuivat
pulls.agit_explanation = Luotu käyttäen AGit-työnkulkua. AGit antaa avustajien ehdottaa muutoksia käyttämällä "git push" ilman, että uutta forkkia tai uutta haaraa luodaan.
milestones.invalid_due_date_format = Määräpäivän muodon tulee olla "yyyy-mm-dd".
milestones.invalid_due_date_format = Eräpäivän muodon tulee olla "yyyy-mm-dd".
wiki.original_git_entry_tooltip = Näytä alkuperäinen Git-tiedosto sen sijaan, että ystävällistä linkkiä käytetään.
pulls.blocked_by_approvals = Tällä vetopyynnöllä ei ole riittävästi hyväksyntöjä. %d/%d hyväksyntää myönnetty.
pulls.status_checks_hide_all = Piilota kaikki tarkistukset
@ -2393,7 +2404,7 @@ settings.trust_model.collaborator.desc = Tämän tietovaraston avustajien kelvol
settings.confirm_wiki_branch_rename = Nimeä uudelleen wikin haara
settings.event_pull_request_assign = Toimeksianto
settings.event_pull_request_assign_desc = Vetopyynnön toimeksianto luotu tai toimeksiannon osoitus poistettu.
settings.event_pull_request_label_desc = Vetopyynnön tunnisteita lisätty tai poistettu.
settings.event_pull_request_label_desc = Vetopyynnön nimilappuja lisätty tai poistettu.
settings.active = Aktiivinen
settings.packagist_api_token = API-poletti
settings.protect_whitelist_committers = Sallittujen listalla rajoitettu työntö
@ -2431,7 +2442,7 @@ settings.event_pull_request_review_request_desc = Vetopyynnön katselmointi pyyd
settings.event_pull_request_merge = Vetopyynnön yhdistäminen
settings.protect_approvals_whitelist_enabled = Rajoita hyväksynnät vain sallittujen käyttäjien tai tiimien listoilla oleviin
settings.packagist_package_url = Packagist-paketin URL-osoite
settings.packagist_username = Packagist-käyttäjätunnus
settings.packagist_username = Packagist-käyttäjänimi
settings.sourcehut_builds.manifest_path = Koontimanifestin polku
settings.event_pull_request_sync_desc = Haara päivitetty automaattisesti kohdehaaralla.
settings.trust_model.committer = Kommitoija
@ -2539,6 +2550,33 @@ form.reach_limit_of_creation_n = Omistajan %d tietovaraston rajoitus on jo täyn
form.string_too_long = Merkkijono on pidempi kuin %d merkkiä.
mirror_address_protocol_invalid = Määritetty URL-osoite on virheellinen. Vain http(s):// tai git:// -sijainteja voi käyttää peilaukseen.
form.name_pattern_not_allowed = Kaava "%s" ei ole sallittu tietovaraston nimessä.
migrate_options_lfs_endpoint.description.local = Paikallinen palvelinpolku on myös tuettu.
pulls.showing_only_single_commit = Näytetään vain kommitin %[1]s muutokset
pulls.invalid_merge_option = Et voi käyttää tätä yhdistämisvalintaa tälle vetopyynnölle.
pulls.squash_merge_pull_request = Luo squash-kommitti
issues.label_templates.info = Nimilappuja ei ole. Luo nimilappu napsauttamalla "Uusi nimilappu" tai käytä nimilapun esiasetusta:
issues.label_archive = Arkistoi nimilappu
mirror_lfs_desc = Aktivoi LFS-datan peilaaminen.
editor.directory_is_a_file = Hakemiston nimi "%s" on jo käytössä tiedoston nimenä tässä tietovarastossa.
projects.desc = Hallitse ongelmia ja vetoja projektitauluilla.
ext_issues = Ulkoiset ongelmat
issues.label_archive_tooltip = Arkistoidut nimilaput on suljettu pois ehdotuksista oletusarvoisesti, kun haku suoritetaan nimilapulla.
issues.ref_reopened_from = `<a href="%[3]s">avasi uudelleen tämän ongelman %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_closed_from = `<a href="%[3]s">sulki tämän ongelman %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
migrate_options_lfs_endpoint.description = Migraatio yrittää käyttää Git-etätietovarastoasi <a target="_blank" rel="noopener noreferrer" href="%s">LFS-palvelimen määrittämiseen</a>. Voit määrittää omavalintaisen päätepisteen, jos tietovarastosi LFS-data on talletettu jonnekin muualle.
settings.mirror_settings.docs.pull_mirror_instructions = Vetopeilin määrittämiseksi konsultoi:
issues.archived_label_description = (Arkistoitu) %s
editor.filename_is_a_directory = Tiedoston nimi "%s" on jo käytössä hakemiston nimenä tässä tietovarastossa.
pulls.fast_forward_only_merge_pull_request = Pelkkä fast-forward
pulls.rebase_merge_commit_pull_request = Rebase, luo sitten yhdistämiskommitti
pulls.rebase_merge_pull_request = Rebase, sitten fast-forward
admin.enabled_flags = Tässä tietovarastossa käytössä olevat liput:
admin.update_flags = Päivitä liput
admin.failed_to_replace_flags = Tietovaraston lippujen korvaaminen epäonnistui
admin.flags_replaced = Tietovaraston liput korvattu
admin.manage_flags = Hallitse lippuja
editor.file_is_a_symlink = `"%s" on symbolinen linkki. Symbolisia linkkejä ei voi muokata selainkäyttöliittymän editorissa`
rss.must_be_on_branch = Sinun täytyy olla haarassa saadaksesi RSS-syötteen.
@ -2667,6 +2705,7 @@ teams.add_nonexistent_repo = Tietovarasto, jota yrität lisätä, ei ole olemass
teams.repos.none = Tällä tiimillä ei ole pääsyä tietovarastoihin.
settings.change_orgname_redirect_prompt.with_cooldown.one = Vanha organisaation nimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa organisaation nimen itsellesi suojaamisjakson aikana.
settings.change_orgname_redirect_prompt.with_cooldown.few = Vanha organisaation nimi on kenen tahansa saatavilla %[1]d päivän suojaamisjakson jälkeen. Voit palauttaa organisaation nimen itsellesi suojaamisjakson aikana.
teams.all_repositories_helper = Tiimillä on pääsy kaikkiin tietovarastoihin. Tämän valitseminen <strong>lisää kaikki olemassa olevat</strong> tietovarastot tiimiin.
[admin]
dashboard=Kojelauta
@ -2720,7 +2759,7 @@ dashboard.gc_times=Roskienkeruuajat
users.user_manage_panel=Käyttäjätilien hallinta
users.new_account=Luo käyttäjätili
users.name=Käyttäjätunnus
users.name=Käyttäjänimi
users.full_name=Koko nimi
users.activated=Aktivoitu
users.admin=Ylläpito
@ -2854,7 +2893,7 @@ config.db_config=Tietokannan asetukset
config.db_type=Tyyppi
config.db_host=Isäntä
config.db_name=Nimi
config.db_user=Käyttäjätunnus
config.db_user=Käyttäjänimi
config.db_ssl_mode=SSL
config.db_path=Polku
@ -3357,6 +3396,8 @@ alt.repository = Tietovaraston tiedot
arch.version.replaces = Korvaa
debian.repository = Tietovaraston tiedot
conda.registry = Määritä tämä rekisteri Conda-tietovarastoksi <code>.condarc</code>-tiedostossa:
container.labels = Nimilaput
settings.link.description = Jos linkität paketin tietovarastoon, paketti listataan tietovaraston pakettilistalla.
[secrets]
creation.failed = Salaisuuden lisääminen epäonnistui.
@ -3371,6 +3412,7 @@ deletion.description = Salaisuuden poistaminen on pysyvä toimenpide, eikä sit
deletion.success = Salaisuus on poistettu.
description = Salaisuudet välitetään tietyille toimenpiteille, eikä niitä voi muuten lukea.
creation.name_placeholder = kirjoinkoolla ei merkitystä, vain aakkosnumeerisia merkkejä ja alaviivoja, ei voi alkaa GITEA_ tai GITHUB_
creation.value_placeholder = Syötä mitä tahansa sisältöä. Tyhjätila alussa ja lopussa jätetään huomiotta.
[actions]
runners.name=Nimi
@ -3405,7 +3447,7 @@ workflow.dispatch.input_required = Arvo syötteelle "%s" vaadittu.
runners.status.active = Aktiivinen
runs.no_workflows.documentation = Katso lisätietoja Forgejo Actions -ohjelmistosta <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaatiosta</a>.
variables.description = Muuttujat asetetaan tietyille toiminnoille eikä niitä voida lukea muutoin.
runners.labels = Tunnisteet
runners.labels = Nimilaput
runners.delete_runner_failed = Testinajajan poisto epäonnistui
runners.delete_runner_header = Varmista testinajajan poisto
runners.task_list.status = Tila
@ -3418,7 +3460,7 @@ runners.task_list.no_tasks = Tehtäviä ei ole vielä määritelty.
runners.last_online = Viimeisin käynnissäoloajankohta
runners.runner_title = Testinajaja
runners.task_list.done_at = Valmistunut ajankohtana
runs.no_matching_online_runner_helper = Testiajajaa tunnisteella %s ei löytynyt
runs.no_matching_online_runner_helper = Testiajajaa nimilapulla %s ei löytynyt
runs.no_results = Ei tuloksia.
runners.delete_runner = Poista testinajaja
variables.deletion.description = Muuttujan poistaminen on lopullista, eikä sitä voi perua. Jatketaanko?
@ -3465,6 +3507,7 @@ runners.status.offline = Ei-verkkotilassa
runs.no_job_without_needs = Työnkulun tulee sisältää vähintään yksi työ ilman riippuvuuksia.
runs.no_runs = Työnkululla ei ole vielä suorituksia.
variables.not_found = Muuttujaa ei löytynyt.
runs.no_workflows.help_write_access = Etkö tiedä, miten aloittaa Forgejo Actionsin käyttö? Lue <a target="_blank" rel="noopener noreferrer" href="%s">pikaopas</a> kirjoittaaksesi ensimmäisen työnkulun, sen jälkeen <a target="_blank" rel="noopener noreferrer" href="%s">määritä Forgejo-ajaja</a> suorittamaan asettamiasi töitä.
@ -3520,4 +3563,12 @@ issues.read = <b>Lue:</b> Lue ja luo ongelmia ja kommentteja.
releases.read = <b>Lue:</b> Katsele ja lataa julkaisuja.
pulls.read = <b>Lue:</b> Vetopyyntöjen lukeminen ja luominen.
ext_issues = Pääsy ulkoisen ongelmanseurannan linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.
ext_wiki = Pääsy ulkoisen wikin linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.
ext_wiki = Pääsy ulkoisen wikin linkkiin. Käyttöoikeuksia hallitaan ulkoisesti.
projects.read = <b>Lue:</b> Pääsy tietovaraston projektitauluille.
wiki.write = <b>Kirjoita:</b> Luo, päivitä ja poista integroidun wikin sivuja.
[markup]
filepreview.truncated = Esikatselu on typistetty
[translation_meta]
test = This is a test string. It is not displayed in Forgejo UI but is used for testing purposes. Feel free to enter "ok" to save time (or a fun fact of your choice) to hit that sweet 100% completion mark :) :) :)

View file

@ -38,9 +38,9 @@ logo = Logo
sign_in = Mag-sign in
sign_in_with_provider = Mag-sign in gamit ang %s
sign_in_or = o
sign_out = Mag-Sign Out
sign_out = Mag-sign out
sign_up = Magrehistro
link_account = Mag-link ng Account
link_account = Mag-link ng account
template = Template
tracked_time_summary = Buod ng mga nakasubaybay na oras base sa filter ng listahan ng isyu
webauthn_sign_in = Pindutin ang button ng iyong security key. Kung walang button ang iyong security key, ilagay muli.
@ -701,7 +701,7 @@ ssh_gpg_keys = Mga SSH / GPG key
applications = Mga Aplikasyon
orgs = Ipamahala ang mga organisasyon
repos = Mga Repositoryo
delete = Burahin ang Account
delete = Burahin ang account
twofa = Authentikasyong two-factor (TOTP)
account_link = Mga naka-link na account
uid = UID
@ -1674,10 +1674,10 @@ issues.new_label = Bagong label
issues.label_templates.title = Mag-load ng isang label preset
issues.new.clear_milestone = I-clear ang milestone
issues.new.open_milestone = Mga bukas na milestone
issues.filter_milestones = I-filter ang Milestone
issues.filter_projects = I-filter ang Proyekto
issues.filter_labels = I-filter ang Label
issues.filter_reviewers = I-filter ang Tagasuri
issues.filter_milestones = I-filter ang milestone
issues.filter_projects = I-filter ang proyekto
issues.filter_labels = I-filter ang label
issues.filter_reviewers = I-filter ang tagasuri
issues.remove_labels = tinanggal ang mga label na %s %s
issues.add_remove_labels = idinagdag ang %s at tinanggal ang %s na mga label %s
issues.add_milestone_at = `idinagdag ito sa <b>%s</b> na milestone %s`
@ -1688,7 +1688,7 @@ issues.add_label = idinagdag ang %s na label %s
issues.add_labels = idinagdag ang mga label na %s %s
issues.remove_label = tinanggal ang %s na label %s
issues.desc = Ayusin ang mga ulat ng bug, gawain, at milestone.
issues.filter_assignees = I-filter ang Mangangasiwa
issues.filter_assignees = I-filter ang mangangasiwa
issues.new.labels = Mga label
issues.new.no_label = Walang mga label
issues.new.clear_labels = I-clear ang mga label
@ -1893,7 +1893,7 @@ settings.collaboration.owner = May-ari
pulls.showing_only_single_commit = Ipinapakita lamang ang mga pagbago ng commit na %[1]s
comments.edit.already_changed = Hindi maimbak ang mga pagbabago sa komento. Mukhang nabago na ng ibang tagagamit ang nilalaman. Mangyaring i-refresh ang pahina at subukang baguhin muli upang maiwasang ma-overwrite ang kanilang pagbago
milestones.completeness = <strong>%d%%</strong> nakumpleto
wiki.welcome = Maligayang pagdating sa Wiki.
wiki.welcome = Maligayang pagdating sa wiki.
wiki.create_first_page = Gawin ang unang pahina
pulls.switch_comparison_type = Ilipat ang uri ng pagkumpara
settings.collaboration.read = Basahin
@ -2278,7 +2278,7 @@ settings.add_collaborator = Magdagdag ng katulong
settings.add_collaborator_duplicate = Nadagdag na ang tagatulong na ito sa repositoryo.
settings.add_collaborator_blocked_our = Hindi madagdag ang tagatulong, dahil hinarang siya ng may-ari ng repositoryo.
settings.add_collaborator_blocked_them = Hindi madagdag ang tagatulong, dahil hinarang niya ang may-ari ng repositoryo.
settings.collaborator_deletion = Tanggalin ang Tagatulong
settings.collaborator_deletion = Tanggalin ang tagatulong
settings.team_not_in_organization = Ang koponan ay hindi nasa katulad na organisasyon sa repositoryo
settings.teams = Mga Koponan
settings.add_team_success = May access na ang koponan sa repositoryo na ito.
@ -3568,8 +3568,8 @@ npm.details.tag = Tag
swift.install = Idagdag ang package sa iyong <code>Package.swift</code> na file:
vagrant.install = Para magdagdag ng Vagrant box, patakbuhin ang sumusunod na command:
settings.link = I-link ang package na ito sa repository
settings.link.select = Pumili ng Repositoryo
settings.link.button = I-update ang Link ng Repositoryo
settings.link.select = Pumili ng repositoryo
settings.link.button = I-update ang link ng repositoryo
settings.link.error = Nabigong i-update ang link ng repositoryo.
settings.delete = Burahin ang package
owner.settings.cargo.initialize = I-initialize ang index
@ -3712,7 +3712,7 @@ runners.reset_registration_token = I-reset ang token ng pagrehistro
runners.status.offline = Offline
workflow.dispatch.invalid_input_type = Hindi wastong input type "%s".
runners.task_list.commit = Commit
runners.task_list.done_at = Natapos Sa
runners.task_list.done_at = Natapos sa
runners.reset_registration_token_success = Matagumpay na na-reset ang token ng pagrehistro ng runner
workflow.dispatch.input_required = Kumailangan ng value para sa input na "%s".
workflow.dispatch.warn_input_limit = Pinapakita lamang ang unang %d na mga input.
@ -3830,7 +3830,7 @@ deletion.success = Natanggal na ang lihim.
deletion.failed = Nabigong tanggalin ang lihim.
creation.failed = Nabigong idagdag ang lihim.
deletion = Tanggalin ang lihim
creation = Idagdag ang Lihim
creation = Idagdag ang lihim
description = Ang mga sikreto ay ipapasa sa ilang mga aksyon at hindi mababasa kung hindi.
none = Wala pang mga sikreto sa ngayon.
creation.name_placeholder = case-insensitive, alphanumeric character o underscore lamang, hindi dapat magsimula sa GITEA_ o GITHUB_
@ -3844,7 +3844,7 @@ filepreview.truncated = Na-truncate ang preview
filepreview.lines = Mga linya %[1]d hanggang %[2]d sa %[3]s
[projects]
deleted.display_name = Binurang Proyekto
deleted.display_name = Binurang proyekto
type-2.display_name = Proyekto ng repositoryo
type-1.display_name = Indibidwal na proyekto
type-3.display_name = Proyekto ng organisasyon

View file

@ -2044,7 +2044,7 @@ ext_wiki=Wiki externe
ext_wiki.desc=Lier un wiki externe.
wiki=Wiki
wiki.welcome=Bienvenue sur le Wiki.
wiki.welcome=Bienvenue sur le wiki.
wiki.welcome_desc=Le wiki vous permet d'écrire ou de partager de la documentation avec vos collaborateurs.
wiki.desc=Écrire et partager de la documentation avec vos collaborateurs.
wiki.create_first_page=Créer la première page
@ -2913,6 +2913,13 @@ pulls.editable_explanation = Cette pull request peut être éditée par les main
sync_fork.branch_behind_one = Cette branche a %[1]d commits de retard sur %[2]s
sync_fork.branch_behind_few = Cettte branche a %[1]d commits de retard sur %[2]s
sync_fork.button = Sync
settings.event_action_failure = Échec
settings.event_action_recover = Récupérer
settings.event_action_success = Réussite
settings.event_header_action = Événements d'exécution d'action
settings.event_action_success_desc = L'exécution de l'action a réussi.
settings.event_action_failure_desc = L'exécution de l'action a échoué.
settings.event_action_recover_desc = L'exécution de l'action a réussi après l'échec de la dernière exécution de l'action dans le même workflow.
[graphs]
component_loading = Chargement %s…
@ -2921,7 +2928,7 @@ component_loading_failed = Échec de chargement de %s
component_loading_info = Cela peut prendre du temps…
component_failed_to_load = Une erreur inattendue s'est produite.
contributors.what = contributions
code_frequency.what = fŕequence de code
code_frequency.what = fquence de code
recent_commits.what = commits récents
@ -4004,7 +4011,7 @@ variables.not_found = La variable n'a pas été trouvée.
type-1.display_name=Projet personnel
type-2.display_name=Projet du dépôt
type-3.display_name=Projet de l'organisation
deleted.display_name = Projet Supprimé
deleted.display_name = Projet supprimé
[git.filemode]
changed_filemode=%[1]s → %[2]s

View file

@ -190,6 +190,7 @@ table_modal.placeholder.header = Cabeceira
link_modal.header = Engadir ligazón
link_modal.url = Url
link_modal.description = Descrición
link_modal.paste_reminder = Consello: Coa URL no portapapeis, podes pegala directamente no editor para crear unha ligazón.
[search]
@ -225,6 +226,8 @@ app_desc = Um servizo Git autoxestionado e fácil de usar
install = Fácil de instalar
install_desc = Simplemente <a target="_blank" rel="noopener noreferrer" href="%[1]s">executa o binario</a> para a túa plataforma, envíao con <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a> ou consígueo <a target="_blank" rel="noopener noreferrer" href="%[3]s">empaquetado</a>.
license = Código aberto
lightweight_desc = Forgejo precisa duns requerimentos mínimos e pode funcionar nunha Raspberry Pi barata. Aforra enerxía na túa máquina!
lightweight = Lixeiro
[error]
occurred = Ocorreu un erro
@ -291,6 +294,7 @@ app_slogan = Slogan da instancia
app_slogan_helper = Escribe o slogan da túa instancia aqui. Ou deixao baleiro para desabilitala.
domain = Dominio do servidor
ssh_port = Porto do servidor SSH
require_db_desc = Forgejo precisa MySQL, PostgreSQL, SQLite3 ou TiDB (protocolo MySQL).
[repo]
sync_fork.branch_behind_few = Esta rama ten %d achegas por detrás de %s

View file

@ -8,7 +8,7 @@ sign_in=Accedi
sign_in_or=o
sign_out=Esci
sign_up=Registrati
link_account=Collega Profilo
link_account=Collega profilo
register=Registrati
version=Versione
powered_by=Gestito da %s
@ -99,7 +99,7 @@ preview=Anteprima
loading=Caricamento…
error=Errore
error404=La pagina che stai cercando di raggiungere <strong>non esiste</strong> oppure <strong>non sei autorizzato</strong> a visualizzarla.
error404=La pagina che stai cercando di raggiungere <strong>non esiste</strong>, <strong>è stata rimossa</strong> oppure <strong>non sei autorizzato</strong> a visualizzarla.
never=Mai
@ -3869,7 +3869,7 @@ changed_filemode = %[1]s → %[2]s
[search]
type_tooltip = Tipo ricerca
search = Cerca...
search = Cerca
fuzzy = Approssimativa
match = Precisa
org_kind = Cerca organizzazioni...

View file

@ -0,0 +1,5 @@
[common]
home = zdani

View file

@ -312,7 +312,7 @@ default_allow_create_organization=조직 생성 허용을 기본값으로 설정
default_allow_create_organization.description=신규 사용자에게 기본적으로 조직 생성 권한을 부여합니다. 이 옵션이 꺼져있다면, 관리자가 신규 사용자에게 조직 생성 권한을 부여해야합니다.
default_enable_timetracking=시간 기록 기능을 기본적으로 사용
default_enable_timetracking.description=신규 저장소가 시간기록 기능을 기본적으로 사용할 수 있습니다.
no_reply_address=가려진 이메일 도메인
no_reply_address=숨겨진 이메일 도메인
no_reply_address_helper=이메일을 가린 사용자에게 적용될 이메일 도메인입니다. 예를 들어, 사용자명 'joe'가 도메인'noreply.example.org'로 이메일을 가리면 Git에 'joe@noreply.example.org'로 로그인 하게 됩니다.
db_schema_helper = 데이터베이스 기본값 ("공개")를 사용하려면 빈 칸으로 두세요.
require_db_desc = Forgejo를 사용하려면 MySQL, PostgreSQL, SQLite3 또는 TiDB (MySQL 프로토콜) 이 설치되어 있어야 합니다.
@ -330,6 +330,12 @@ app_slogan_helper = 인스턴스의 슬로건을 입력하세요. 비워두면
reinstall_confirm_check_1 = app.ini의 SECRET_KEY로 암호화 되어있는 데이터를 잃을 수 있습니다: 2FA/OTP를 통해 로그인 할 수 없으며 & 미러가 제대로 작동하지 않게됩니다. app.ini 파일에 정확한 SECRET_KEY가 있는것이 확실하다면 체크하세요.
run_user_helper = Forgejo를 구동하는 운영체제의 사용자명입니다. 이 사용자는 저장소 루트 경로에 접근권한이 있어야 합니다.
reinstall_confirm_check_2 = 저장소와 설정에 재동기화가 요구될 수 있습니다. 이 박스에 체크하면 저장소의 훅과 authorized_key 들을 수동으로 재동기화해야 한다는 것을 인지한다는 것을 의미합니다. 저장소와 미러의 설정이 올바른지 확인하세요.
password_algorithm = 암호 해시 알고리즘
enable_update_checker = 업데이트 확인 활성화
secret_key_failed = 비밀 키 생성 실패: %v
env_config_keys = 환경 설정
invalid_password_algorithm = 올바르지 않은 암호 해시 알고리즘
invalid_db_table = 데이터베이스 테이블 "%s"이(가) 올바르지 않습니다: %v
[home]
uname_holder=사용자명 또는 이메일 주소
@ -347,6 +353,8 @@ search_repos=저장소 찾기..
show_private=비공개
issues.in_your_repos=당신의 저장소에
feed_of = "%s"의 피드
filter = 다른 필터
[explore]
repos=저장소

View file

@ -162,7 +162,7 @@ filter.not_archived = Nav arhivētas
filter.is_fork = Atzarojumi
filter.not_fork = Nav atzarojumi
filter.is_mirror = Spoguļglabātavas
filter.public = Atklātas
filter.public = Publiskas
filter.private = Privātas
filter.clear = Notīrīt atlasi
confirm_delete_artifact = Vai tiešām izdzēst artefaktu '%s'?
@ -374,9 +374,9 @@ show_only_archived=Attēlot tikai arhivētos
show_only_unarchived=Attēlot tikai nearhivētos
show_private=Privāts
show_both_private_public=Rāda gan atklātās, gan privātās
show_both_private_public=Rāda gan publiskās, gan privātās
show_only_private=Attēlot tikai privātos
show_only_public=Attēlo tikai atklātās
show_only_public=Tiek rādītas tikai publiskās
issues.in_your_repos=Manās glabātavās
@ -690,7 +690,7 @@ email_domain_is_not_allowed = Lietotāja e-pasta adreses <b>%s</b> domēna vārd
change_avatar=Mainīt profila attēlu…
joined_on=Pievienojās %s
repositories=Glabātavas
activity=Atklāti notikumi
activity=Publiskas darbības
followers_few=%d sekotāji
starred=Izlasei pievienotās glabātavas
watched=Vērotās glabātavas
@ -701,7 +701,7 @@ following_few=%d seko
follow=Sekot
unfollow=Pārtraukt sekot
user_bio=Apraksts par sevi
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību visiem.
disabled_public_activity=Šis lietotājs ir atspējojis darbību redzamību citiem.
email_visibility.limited=E-pasta adrese ir redzama visiem autentificētajiem lietotājiem
email_visibility.private=E-pasta adrese ir redzama tikai administratoriem
show_on_map=Rādīt šo vietu kartē
@ -749,7 +749,7 @@ organization=Apvienības
uid=UID
webauthn=Divpakāpju pieteikšanās (drošības atslēgas)
public_profile=Visiem pieejamais profils
public_profile=Publiskais profils
biography_placeholder=Pastāsti citiem mazliet par sevi! (Tiek atbalstīts Markdown)
location_placeholder=Kopīgot savu aptuveno atrašanās vietu ar citiem
profile_desc=Par Tevi
@ -940,8 +940,8 @@ access_token_deletion_confirm_action=Dzēst
access_token_deletion_desc=Pilnvaras izdzēšana atsauks lietotņu, kas to izmanto, piekļuvi kontam. Šo darbību nevar atsaukt. Turpināt?
delete_token_success=Pilnvara tika izdzēsta. Lietotnēm, kas to izmanto, vairs nav piekļuves kontam.
repo_and_org_access=Glabātavas un apvienības piekļuve
permissions_public_only=Tikai atklātās
permissions_access_all=Visas (atklātās, privātās un ierobežotās)
permissions_public_only=Tikai publiskās
permissions_access_all=Visas (publiskās, privātās un ierobežotās)
select_permissions=Atlasīt atļaujas
permission_no_access=Nav piekļuves
permission_read=Lasīt
@ -1035,14 +1035,14 @@ email_notifications.submit=Iestatīt e-pasta iestatījumus
email_notifications.andyourown=Un manus paziņojumus
visibility=Lietotāja redzamība
visibility.public=Atklāta
visibility.public=Publiska
visibility.public_tooltip=Redzams ikvienam
visibility.limited=Ierobežota
visibility.limited_tooltip=Redzams tikai lietotājiem, kuri ir pieteikušies
visibility.private=Privāta
visibility.private_tooltip=Redzams tikai apvienību, kurās pievienojies, dalībniekiem
change_password = Mainīt paroli
keep_activity_private.description = Tavas <a href="%s">atklātās darbības</a> būs redzamas tikai Tev un servera pārvaldītājiem.
keep_activity_private.description = Tavas <a href="%s">publiskās darbības</a> būs redzamas tikai Tev un servera pārvaldītājiem.
update_hints = Atjaunināt norādes
update_hints_success = Norādes tika atjauninātas.
user_block_success = Lietotājs tika sekmīgi liegts.
@ -1083,7 +1083,7 @@ quota.applies_to_org = Uz apvienību attiecas zemāk esošās ierobežojuma kār
quota.rule.no_limit = Neierobežots
quota.sizes.all = Viss
quota.sizes.repos.all = Glabātavas
quota.sizes.repos.public = Atklātās glabātavas
quota.sizes.repos.public = Publiskās glabātavas
quota.sizes.repos.private = Privātās glabātavas
regenerate_token = Izveidot no jauna
access_token_regeneration = Izveidot piekļuves pilnvaru no jauna
@ -1195,7 +1195,7 @@ transfer.no_permission_to_accept=Nav atļaujas pieņemt šo nodošanu.
transfer.no_permission_to_reject=Nav atļaujas noraidīt šo nodošanu.
desc.private=Privāts
desc.public=Atklāts
desc.public=Publisks
desc.template=Sagatave
desc.internal=Iekšējs
desc.archived=Arhivēts
@ -1464,7 +1464,7 @@ commit.cherry-pick-content=Atlasīt zaru, uz kuru izlasīt:
commitstatus.error=Kļūda
commitstatus.failure=Atteice
commitstatus.pending=Nav iesūtīts
commitstatus.success=Pabeigts
commitstatus.success=Sekmīgs
ext_issues=Ārēji pieteikumi
ext_issues.desc=Saite uz ārējo problēmu sekotāju.
@ -1515,7 +1515,7 @@ issues.filter_assignees=Atlasīt pēc atbildīgajiem
issues.filter_milestones=Atlasīt pēc atskaites punkta
issues.filter_projects=Atlasīt pēc projekta
issues.filter_labels=Atlasīt pēc iezīmes
issues.filter_reviewers=Atlasīt izskatītājus
issues.filter_reviewers=Atlasīt pēc izskatītājiem
issues.new=Jauns pieteikums
issues.new.title_empty=Nosaukums nevar būt tukšs
issues.new.labels=Iezīmes
@ -2041,7 +2041,7 @@ ext_wiki=Ārēja vikivietne
ext_wiki.desc=Ārējā vikivietne norāda uz ārējo vikivietnes adresi.
wiki=Vikivietne
wiki.welcome=Laipni lūdzam vikivietnē.
wiki.welcome=Laipni lūdzam vikivietnē!
wiki.welcome_desc=Vikivietne ļauj rakstīt un kopīgot dokumentāciju ar līdzdalībniekiem.
wiki.desc=Dokumentācijas rakstīšana un kopīgošana ar līdzdalībniekiem.
wiki.create_first_page=Izveidot pirmo lapu
@ -2769,7 +2769,7 @@ no_eol.text = Nav EOL
size_format = %[1]s: %[2]s; %[3]s: %[4]s
mirror_public_key = Publiskā SSH atslēga
mirror_use_ssh.text = Izmantot SSH autentificēšanos
mirror_use_ssh.helper = Forgejo spoguļos glabātavu ar Git un SSH un izveidos atslēgu pāri, kad tiks atlasīta šī iespēja. Jānodrošina, ka izveidotais atslēgu pāris ir pilnvarots aizgādāt mērķa glabātavā. Nevarēs izmantot pilnvarošanu ar paroli, kad šis tiek atlasīts.
mirror_use_ssh.helper = Forgejo spoguļos glabātavu ar Git un SSH un izveidos atslēgu pāri, kad tiks atlasīta šī iespēja. Jānodrošina, ka izveidotā publiskāš atslēga ir pilnvarota aizgādāt mērķa glabātavā. Nevarēs izmantot pilnvarošanu ar paroli, kad šis tiek atlasīts.
mirror_use_ssh.not_available = SSH autentificēšanās nav pieejama.
mirror_denied_combination = Nevar izmantot autentificēšanos ar publiskās atslēgas un paroles apvienojumu.
migrate.forgejo.description = Pārcelt datus no codeberg.org vai citiem Fogejo serveriem.
@ -2959,7 +2959,7 @@ settings.location=Atrašanās vieta
settings.permission=Tiesības
settings.repoadminchangeteam=Glabātavas pārvaldītājs var pievienot un noņemt komandu piekļuvi
settings.visibility=Redzamība
settings.visibility.public=Atklāta
settings.visibility.public=Publiska
settings.visibility.limited=Ierobežota (redzama tikai lietotājiem, kuri ir pieteikušies)
settings.visibility.limited_shortname=Ierobežota
settings.visibility.private=Privāta (redzama tikai apvienības dalībniekiem)
@ -3594,7 +3594,7 @@ self_check.database_collation_mismatch = Sagaidīt, ka datubāzē tiek izmantota
self_check.database_fix_mysql = MySQL/MariaDB lietotāji var izmantot komandu "forgejo doctor convert", lai novērstu salīdzināšanas sarežģījumus, vai arī tos var pašrocīgi novērst ar "ALTER ... COLLATE ..." vaicājumiem.
config.app_slogan = Servera sauklis
config.allow_dots_in_usernames = Ļaut lietotājiem izmantot punktus savā lietotājvārdā. Neietekmē esošos kontus.
users.restricted.description = Ļaut mijiedarbību tikai ar glabātavām un apvienībām, kurās šis lietotājs ir pievienots kā līdzdalībnieks. Tas neļauj piekļūt šī servera atklātajām glabātavām.
users.restricted.description = Ļaut mijiedarbību tikai ar glabātavām un apvienībām, kurās šis lietotājs ir pievienots kā līdzdalībnieks. Tas neļauj piekļūt šī servera publiskajām glabātavām.
dashboard.sync_tag.started = Uzsākta birku sinhronizēšana
users.organization_creation.description = Ļaut jaunu apvienību izveidošanu.
users.block.description = Liegt šī lietotāja mijiedarbību ar šo serveri caur tā kontu un neļaut pieteikšanos.
@ -3925,7 +3925,7 @@ runners.task_list.run=Izpildījums
runners.task_list.status=Stāvoklis
runners.task_list.repository=Glabātava
runners.task_list.commit=Iesūtījums
runners.task_list.done_at=Beigu laiks
runners.task_list.done_at=Pabeigts
runners.edit_runner=Labot izpildītāju
runners.update_runner=Atjaunināt izmaiņas
runners.update_runner_success=Izpildītājs sekmīgi atjaunināts

View file

@ -1439,7 +1439,7 @@ issues.comment_manually_pull_merged_at = hett Kommitteren %[1]s in %[2]s %[3]s v
issues.reopen_issue = Weer opmaken
issues.closed_at = `hett deeses Gefall <a id="%[1]s" href="#%[1]s">%[2]s</a> dichtmaakt`
issues.commit_ref_at = `hett deeses Gefall <a id="%[1]s" href="#%[1]s">%[2]s</a> vun eenem Kommitteren benöömt`
issues.ref_closing_from = `<a href="%[3]s">hett deeses Gefall vun eenem Haalvörslag, wat t %[4]s dichtmaken word,</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s">benöömt</a>`
issues.ref_closing_from = `<a href="%[3]s">hett deeses Gefall</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s"> vun eenem Haalvörslag, wat t %[4]s dichtmaken word, benöömt</a>`
issues.ref_closed_from = `<a href="%[3]s">hett deeses Gefall %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s">dichtmaakt</a>`
issues.ref_reopened_from = `<a href="%[3]s">hett deeses Gefall %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> <a href="%[3]s">weer opmaakt</a>`
issues.ref_from = `vun %[1]s`
@ -2614,6 +2614,13 @@ archive.nocomment = Kommenteren gaht hier nich, denn dat Repositorium is archive
sync_fork.button = Vernejen
sync_fork.branch_behind_one = Deeser Twieg is %[1]d Kommitteren achter %[2]s
sync_fork.branch_behind_few = Deeser Twieg is %[1]d Kommitterens achter %[2]s
settings.event_action_failure = Fehlslagen
settings.event_action_success = Daankregen
settings.event_action_success_desc = Aktioons-Loop is all daankregen worden.
settings.event_action_recover = Verhaalt
settings.event_header_action = Aktioons-Loop-Vörfallen
settings.event_action_failure_desc = Aktioons-Loop is as fehlslagen ennt.
settings.event_action_recover_desc = Aktioons-Loop is daankregen worden, nadeem de leste Aktioons-Loop in de sülven Warkwies fehlslagen is.
[repo.permissions]
code.read = <b>Lesen:</b> De Quelltext vun deesem Repositorium ankieken un klonen.

View file

@ -8,7 +8,7 @@ sign_in=Aanmelden
sign_in_or=of
sign_out=Uitloggen
sign_up=Registreren
link_account=Account Koppelen
link_account=Account koppelen
register=Registreren
version=Versie
powered_by=Mogelijk gemaakt door %s
@ -2031,7 +2031,7 @@ settings.add_collaborator_success=De medewerker is toegevoegd.
settings.add_collaborator_inactive_user=Kan geen inactieve gebruiker toevoegen als medewerker.
settings.add_collaborator_duplicate=De collaborator is al toegevoegd aan deze repository.
settings.delete_collaborator=Verwijder
settings.collaborator_deletion=Verwijder medewerker
settings.collaborator_deletion=Verwijder samenwerker
settings.collaborator_deletion_desc=Het verwijderen van een collaborator zal hun toegang tot deze repository intrekken. Doorgaan?
settings.remove_collaborator_success=De medewerker is verwijderd.
settings.search_user_placeholder=Zoek gebruiker…
@ -3914,7 +3914,7 @@ runners.task_list.no_tasks = Er is nog geen taak.
runners.labels = Labels
runners.last_online = Laatste online tijd
runners.task_list.status = Status
runners.task_list.done_at = Gedaan Op
runners.task_list.done_at = Gedaan op
runners.id = ID
runs.actor = Acteur
actions = Actions

View file

@ -1503,11 +1503,11 @@ projects.card_type.images_and_text=Imagens e texto
projects.card_type.text_only=Somente texto
issues.desc=Organize relatórios de bugs, tarefas e marcos.
issues.filter_assignees=Filtrar Atribuição
issues.filter_milestones=Filtrar Marco
issues.filter_projects=Filtrar Projeto
issues.filter_labels=Filtrar Rótulo
issues.filter_reviewers=Filtrar Revisor
issues.filter_assignees=Filtrar atribuição
issues.filter_milestones=Filtrar marco
issues.filter_projects=Filtrar projeto
issues.filter_labels=Filtrar rótulo
issues.filter_reviewers=Filtrar revisor
issues.new=Novo issue
issues.new.title_empty=Título não pode ser em branco
issues.new.labels=Etiquetas
@ -2013,7 +2013,7 @@ ext_wiki=Wiki Externa
ext_wiki.desc=Link para uma wiki externa.
wiki=Wiki
wiki.welcome=Bem-vindo a wiki.
wiki.welcome=Bem-vindo à wiki.
wiki.welcome_desc=A wiki permite que você escreva e compartilhe a documentação com os colaboradores.
wiki.desc=Escrever e compartilhar a documentação com os colaboradores.
wiki.create_first_page=Criar a primeira página
@ -3808,8 +3808,8 @@ swift.install2=e execute o seguinte comando:
vagrant.install=Para adicionar uma Vagrant box, execute o seguinte comando:
settings.link=Vincular este pacote a um repositório
settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório.
settings.link.select=Selecionar Repositório
settings.link.button=Atualizar Link do Repositório
settings.link.select=Selecionar repositório
settings.link.button=Atualizar link do repositório
settings.link.success=Link do repositório foi atualizado com sucesso.
settings.link.error=Falha ao atualizar o link do repositório.
settings.delete=Excluir o pacote
@ -4004,7 +4004,7 @@ variables.not_found = Não foi possível encontrar a variável.
type-1.display_name=Projeto individual
type-2.display_name=Projeto do repositório
type-3.display_name=Projeto da organização
deleted.display_name = Projeto Apagado
deleted.display_name = Projeto apagado
[git.filemode]
symbolic_link=Ligação simbólica

View file

@ -9,7 +9,7 @@ sign_in_with_provider=Iniciar sessão com %s
sign_in_or=ou
sign_out=Terminar sessão
sign_up=Fazer inscrição
link_account=Vincular conta
link_account=Associar conta
register=Inscrição
version=Versão
powered_by=Implementado com %s
@ -20,12 +20,12 @@ notifications=Notificações
active_stopwatch=Cronómetro em andamento
tracked_time_summary=Resumo do tempo rastreado com base em filtros da lista de questões
create_new=Criar…
user_profile_and_more=Perfil e configurações…
user_profile_and_more=Perfil e definições…
signed_in_as=Sessão iniciada como
enable_javascript=Este sítio Web requer JavaScript.
toc=Índice
licenses=Licenças
return_to_forgejo=Retornar ao Forgejo
return_to_forgejo=Voltar ao Forgejo
username=Nome de utilizador
email=Endereço de email
@ -59,10 +59,10 @@ new_migrate=Nova migração
new_mirror=Nova réplica
new_fork=Nova derivação do repositório
new_org=Nova organização
new_project=Novo planeamento
new_project=Novo projeto
new_project_column=Nova coluna
manage_org=Gerir organizações
admin_panel=Administração do sítio
admin_panel=Administração do site
account_settings=Configurações da conta
settings=Configurações
your_profile=Perfil
@ -155,7 +155,7 @@ invalid_data = Dados inválidos: %v
filter.clear = Retirar filtros
filter.is_archived = Arquivado
filter.not_template = Não modelos
toggle_menu = Comutar menu
toggle_menu = Alternar menu
filter = Filtrar
copy_generic = Copiar para a área de transferência
test = Teste
@ -233,7 +233,7 @@ platform_desc=Está confirmado que Forgejo corre em sistemas operativos livres,
lightweight=Leve
lightweight_desc=Forgejo requer poucos recursos e pode correr num simples Raspberry Pi. Economize a energia da sua máquina!
license=Código aberto
license_desc=Vá buscá-lo em <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Junte-se a nós dando a <a target="_blank" rel="noopener noreferrer" href="%[2]s">sua contribuição</a> para tornar este programa ainda melhor. Não se acanhe e contribua!
license_desc=Todas as fontes estão disponíveis no <a target="_blank" rel="noopener noreferrer" href="%[1]s">Forgejo</a>! Junte-se a nós e <a target="_blank" rel="noopener noreferrer" href="%[2]s">contribua</a> para tornar este projeto ainda melhor. Não receie tornar-se colaborador!
[install]
install=Instalação
@ -291,7 +291,7 @@ smtp_port=Porto do SMTP
smtp_from=Email do remetente
smtp_from_helper=Endereço de email que o Forgejo vai usar. Insira um endereço de email simples ou use o formato "Nome" <email@exemplo.com>.
mailer_user=Nome de utilizador do SMTP
mailer_password=Senha do SMTP
mailer_password=Palavra-passe do SMTP
register_confirm=Exigir confirmação de email para se inscrever
mail_notify=Habilitar notificações por email
server_service_title=Configurações do servidor e de terceiros
@ -316,7 +316,7 @@ admin_setting.description=A criação de uma conta de administração é opciona
admin_title=Configurações da conta de administração
admin_name=Nome de utilizador do administrador
admin_password=Senha
confirm_password=Confirme a senha
confirm_password=Confirme a palavra-passe
admin_email=Endereço de email
install_btn_confirm=Instalar Forgejo
test_git_failed=Não foi possível testar o comando "git": %v
@ -339,7 +339,7 @@ default_enable_timetracking=Habilitar, por norma, a contagem do tempo
default_enable_timetracking.description=Habilitar, por norma, a contagem do tempo nos novos repositórios.
no_reply_address=Domínio dos emails ocultos
no_reply_address_helper=Nome de domínio para utilizadores com um endereço de email oculto. Por exemplo, o nome de utilizador "silva" será registado no Git como "silva@semresposta.exemplo.org" se o domínio de email oculto estiver definido como "semresposta.exemplo.org".
password_algorithm=Algoritmo de Hash da Senha
password_algorithm=Algoritmo de Hash da palavra-passe
invalid_password_algorithm=Algoritmo de hash da senha inválido
password_algorithm_helper=Definir o algoritmo de hash da senha. Os algoritmos têm requisitos e resistência distintos. `argon2` é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas pequenos.
enable_update_checker=Habilitar verificador de novidades
@ -415,7 +415,7 @@ disable_register_mail=A confirmação por email da inscrição está desabilitad
manual_activation_only=Contacte o administrador para completar a habilitação.
remember_me=Memorizar este dispositivo
remember_me.compromised=O identificador da sessão já não é válido, o que pode indicar uma conta comprometida. Verifique se a sua conta apresenta operações pouco habituais.
forgot_password_title=Esqueci-me da senha
forgot_password_title=Esqueci-me da palavra-passe
forgot_password=Esqueceu a sua senha?
sign_up_now=Precisa de uma conta? Inscreva-se agora.
sign_up_successful=A conta foi criada com sucesso. Bem-vindo/a!
@ -744,7 +744,7 @@ social=Contas sociais
applications=Aplicações
orgs=Organizações
repos=Repositórios
delete=Eliminar a conta
delete=Eliminar conta
twofa=Autenticação em dois passos (TOTP)
account_link=Contas vinculadas
organization=Organizações
@ -1060,7 +1060,7 @@ user_unblock_success = O utilizador foi desbloqueado com sucesso.
language.title = Idioma predefinido
keep_activity_private.description = O seu <a href="%s">trabalho público</a> apenas estará visível para si e para os administradores da instância.
language.description = Este idioma vai ser guardado na sua conta e ser usado como o predefinido depois de iniciar sessão.
language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! <a href="%s">Saiba mais</a>.
language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! <a href="%s">Ler mais</a>.
pronouns_custom_label = Pronomes personalizados
user_block_yourself = Não se pode bloquear a si próprio.
change_username_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera.
@ -1093,7 +1093,7 @@ regenerate_token = Regenerar
access_token_regeneration_desc = A regeneração de um código irá revogar o acesso à sua conta para as aplicações que o utilizam. Isto não pode ser anulado. Continuar?
[repo]
new_repo_helper=Um repositório contém todos os ficheiros do trabalho, incluindo o histórico das revisões. Já tem um hospedado noutro sítio? <a href="%s">Migre o repositório</a>.
new_repo_helper=Um repositório contém todos os ficheiros do projeto, incluindo o histórico das revisões. Já tem um hospedado noutro sítio? <a href="%s">Migre o repositório</a>.
owner=Proprietário(a)
owner_helper=Algumas organizações podem não aparecer na lista suspensa devido a um limite máximo de contagem de repositórios.
repo_name=Nome do repositório
@ -1133,7 +1133,7 @@ issue_labels=Rótulos
issue_labels_helper=Escolha um conjunto de rótulos
license=Licença
license_helper=Escolha um ficheiro de licença
license_helper_desc=Uma licença rege o que os outros podem, ou não, fazer com o seu código fonte. Não tem a certeza sobre qual a mais indicada para o seu trabalho? Veja: <a target="_blank" rel="noopener noreferrer" href="%s">Escolher uma licença</a>.
license_helper_desc=Uma licença rege o que os outros podem, ou não, fazer com o seu código fonte. Não tem a certeza sobre qual a mais indicada para o seu projeto? Veja: <a target="_blank" rel="noopener noreferrer" href="%s">Escolher uma licença</a>.
object_format=Formato dos elementos
object_format_helper=Formato dos elementos do repositório. Não poderá ser alterado mais tarde. SHA1 é o mais compatível.
readme=README
@ -1479,23 +1479,23 @@ projects=Planeamentos
projects.desc=Gerir questões e integrações nos quadros do planeamento.
projects.description=Descrição (opcional)
projects.description_placeholder=Descrição
projects.create=Criar planeamento
projects.create=Criar projeto
projects.title=Título
projects.new=Novo planeamento
projects.new=Novo projeto
projects.new_subheader=Coordene, acompanhe e modifique o seu trabalho num só lugar, para que os planeamentos se mantenham transparentes e cumpram o calendário.
projects.create_success=O planeamento "%s" foi criado.
projects.deletion=Eliminar planeamento
projects.deletion=Eliminar projeto
projects.deletion_desc=Eliminar um planeamento remove-o de todas as questões relacionadas. Continuar?
projects.deletion_success=O planeamento foi eliminado.
projects.edit=Editar planeamentos
projects.edit=Editar projeto
projects.edit_subheader=Planeamentos organizam questões e acompanham o progresso.
projects.modify=Editar planeamento
projects.modify=Editar projeto
projects.edit_success=O planeamento "%s" foi modificado.
projects.type.none=Nenhum
projects.type.basic_kanban=Kanban básico
projects.type.bug_triage=Triagem de erros
projects.template.desc=Modelo
projects.template.desc_helper=Escolha um modelo de planeamento para começar
projects.template.desc_helper=Escolha um modelo de projeto para começar
projects.type.uncategorized=Sem categoria
projects.column.edit=Editar coluna
projects.column.edit_title=Nome
@ -1507,7 +1507,7 @@ projects.column.set_default_desc=Definir esta coluna como a predefinida para que
projects.column.unset_default=Deixar de ser a predefinida
projects.column.unset_default_desc=Faz com que esta coluna deixe de ser a predefinida
projects.column.delete=Eliminar coluna
projects.column.deletion_desc=Eliminar uma coluna de um planeamento faz com que todas as questões que nela constam sejam movidas para a coluna padrão. Continuar?
projects.column.deletion_desc=Eliminar uma coluna de um projeto faz com que todas as questões que nela constam sejam movidas para a coluna padrão. Continuar?
projects.column.color=Colorido
projects.open=Abrir
projects.close=Fechar
@ -1519,7 +1519,7 @@ projects.card_type.text_only=Apenas texto
issues.desc=Organize relatórios de erros, tarefas e etapas.
issues.filter_assignees=Filtrar encarregado
issues.filter_milestones=Filtrar etapa
issues.filter_projects=Filtrar planeamento
issues.filter_projects=Filtrar projeto
issues.filter_labels=Filtrar rótulo
issues.filter_reviewers=Filtrar revisor
issues.new=Questão nova
@ -1530,8 +1530,8 @@ issues.new.clear_labels=Retirar rótulos
issues.new.projects=Planeamentos
issues.new.clear_projects=Limpar planeamentos
issues.new.no_projects=Nenhum planeamento
issues.new.open_projects=Planeamentos abertos
issues.new.closed_projects=Planeamentos fechados
issues.new.open_projects=Projetos abertos
issues.new.closed_projects=Projetos fechados
issues.new.no_items=Sem itens
issues.new.milestone=Etapa
issues.new.no_milestone=Sem etapa
@ -2049,7 +2049,7 @@ ext_wiki=Wiki externo
ext_wiki.desc=Ligação para um wiki externo.
wiki=Wiki
wiki.welcome=Bem-vindo(a) ao Wiki.
wiki.welcome=Bem-vindo(a) à wiki.
wiki.welcome_desc=O wiki permite escrever e partilhar documentação com os colaboradores.
wiki.desc=Escrever e partilhar documentação com os colaboradores.
wiki.create_first_page=Criar a primeira página
@ -2236,7 +2236,7 @@ settings.pulls.default_delete_branch_after_merge=Eliminar, por norma, o ramo do
settings.pulls.default_allow_edits_from_maintainers=Permitir, por norma, que os responsáveis editem
settings.releases_desc=Habilitar lançamentos no repositório
settings.packages_desc=Habilitar o registo de pacotes do repositório
settings.projects_desc=Habilitar planeamentos no repositório
settings.projects_desc=Habilitar projetos no repositório
settings.actions_desc=Habilitar sequências CI/CD integradas com Forgejo Actions
settings.admin_settings=Configurações do administrador
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
@ -2834,7 +2834,7 @@ form.string_too_long = O texto fornecido é mais comprido do que %d caracteres.
settings.federation_settings = Configurações da federação
settings.federation_apapiurl = URL de federação deste repositório. Copie e cole nas configurações de federação de outro repositório como um URL de um repositório que está a ser seguido.
issues.edit.already_changed = Não foi possível guardar as modificações desta questão. O conteúdo parece ter sido modificado por outro utilizador. Refresque a página e tente editar novamente para evitar sobrescrever as modificações que fizeram
project = Planeamentos
project = Projetos
pulls.edit.already_changed = Não foi possível guardar as modificações do pedido de integração. O conteúdo parece ter sido modificado por outro utilizador. Refresque a página e tente editar novamente para evitar sobrescrever as modificações que fizeram
subscribe.issue.guest.tooltip = Inicie sessão para subscrever esta questão.
subscribe.pull.guest.tooltip = Inicie sessão para subscrever este pedido de integração.
@ -3811,7 +3811,7 @@ swift.install2=e execute o seguinte comando:
vagrant.install=Para adicionar uma máquina virtual Vagrant, execute o seguinte comando:
settings.link=Vincular este pacote a um repositório
settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório.
settings.link.select=Escolha o repositório
settings.link.select=Escolher repositório
settings.link.button=Modificar vínculo ao repositório
settings.link.success=O vínculo ao repositório foi modificado com sucesso.
settings.link.error=Falhou a modificação do vínculo ao repositório.
@ -4002,10 +4002,10 @@ runs.no_workflows.help_write_access = Não sabe como começar com o Forgejo Acti
variables.not_found = Não foi possível encontrar a variável.
[projects]
type-1.display_name=Planeamento individual
type-2.display_name=Planeamento do repositório
type-3.display_name=Planeamento da organização
deleted.display_name = Planeamento eliminado
type-1.display_name=Projeto individual
type-2.display_name=Projeto do repositório
type-3.display_name=Projeto da organização
deleted.display_name = Projeto eliminado
[git.filemode]
changed_filemode=%[1]s → %[2]s
@ -4024,7 +4024,7 @@ code_search_by_git_grep = Os resultados da pesquisa no código-fonte neste momen
no_results = Não foram encontrados resultados correspondentes.
package_kind = Pesquisar pacotes…
runner_kind = Pesquisar executores…
project_kind = Pesquisar planeamentos…
project_kind = Pesquisar projetos…
branch_kind = Pesquisar ramos…
commit_kind = Pesquisar cometimentos…
search = Procurar…
@ -4068,8 +4068,8 @@ test = ok :)
[repo.permissions]
code.read = <b>Ler:</b> Aceder e clonar o código-fonte do repositório.
releases.read = <b>Ler:</b> Ver e descarregar lançamentos.
projects.read = <b>Ler:</b> Aceder aos quadros de planeamento do repositório.
projects.write = <b>Escrever:</b> Criar planeamentos e colunas e editá-las.
projects.read = <b>Ler:</b> Aceder aos quadros de projeto do repositório.
projects.write = <b>Escrever:</b> Criar projetos e colunas e editá-las.
packages.read = <b>Ler:</b> Ver e descarregar pacotes atribuídos ao repositório.
packages.write = <b>Escrever:</b> Publicar e eliminar pacotes atribuídos ao repositório.
actions.read = <b>Ler:</b> Ver sequências CI/CD integrados e os seus registos.

View file

@ -296,7 +296,7 @@ federated_avatar_lookup.description=Libravatar kullanarak federe profil resmi ar
disable_registration=Kendi Kendine Kaydolmayı Devre Dışı Bırak
disable_registration.description=Kullanıcının kendi kendine kaydolmasını devre dışı bırak. Yalnızca yöneticiler yeni hesaplar oluşturabilecek.
allow_only_external_registration.description=Sadece belirlenen dış hizmetler aracılığıyla kullanıcı kaydına izin ver.
openid_signin=OpenID Oturum Açmayı Etkinleştiriniz
openid_signin=OpenID Oturum Açmayı Etkinleştir
openid_signin.description=OpenID ile kullanıcı girişini etkinleştir.
openid_signup=OpenID ile Kendi Kendine Kaydı Etkinleştir
openid_signup.description=OpenID Tabanlı Kendi Kendi Kullanıcı Kaydını Etkinleştir.
@ -3061,13 +3061,13 @@ packages.repository=Depo
packages.size=Boyut
packages.published=Yayınlandı
defaulthooks=Varsayılan Web İstemcileri
defaulthooks.desc=Web İstemcileri, belirli Forgejo olayları tetiklendiğinde otomatik olarak HTTP POST isteklerini sunucuya yapar. Burada tanımlanan Web İstemcileri varsayılandır ve tüm yeni depolara kopyalanır. <a target="_blank" rel="noopener" href="%s">web istemcileri kılavuzunda</a> daha fazla bilgi edinin.
defaulthooks=Varsayılan web kancaları
defaulthooks.desc=Web Kancaları, belirli Forgejo olayları tetiklendiğinde otomatik olarak HTTP POST isteklerini sunucuya yapar. Burada tanımlanan Web kancaları varsayılandır ve tüm yeni depolara kopyalanır. <a target="_blank" rel="noopener" href="%s">web kancaları kılavuzunda</a> daha fazla bilgi edinin.
defaulthooks.add_webhook=Varsayılan Web İstemcisi Ekle
defaulthooks.update_webhook=Varsayılan Web İstemcisini Güncelle
systemhooks=Sistem Web İstemcileri
systemhooks.desc=Belirli Forgejo olayları tetiklendiğinde Web istemcileri otomatik olarak bir sunucuya HTTP POST istekleri yapar. Burada tanımlanan web istemcileri sistemdeki tüm depolar üzerinde çalışır, bu yüzden lütfen bunun olabilecek tüm performans sonuçlarını göz önünde bulundurun. <a target="_blank" rel="noopener" href="%s">web istemcileri kılavuzunda</a> daha fazla bilgi edinin.
systemhooks=Sistem web kancaları
systemhooks.desc=Belirli Forgejo olayları tetiklendiğinde Web kancaları otomatik olarak bir sunucuya HTTP POST istekleri yapar. Burada tanımlanan web kancaları sistemdeki tüm depolar üzerinde çalışır, bu yüzden lütfen bunun olabilecek tüm performans sonuçlarını göz önünde bulundurun. <a target="_blank" rel="noopener" href="%s">web kancaları kılavuzunda</a> daha fazla bilgi edinin.
systemhooks.add_webhook=Sistem Web İstemcisi Ekle
systemhooks.update_webhook=Sistem Web İstemcisi Güncelle
@ -3241,7 +3241,7 @@ config.disable_register=Kullanıcı Kaydını Devre Dışı Bırak
config.allow_only_internal_registration=Kayda Sadece Forgejo'nın Kendisi Üzerinden İzin Ver
config.allow_only_external_registration=Sadece Dış Hizmetler Aracılığıyla Kullanıcı Kaydına İzin Ver
config.enable_openid_signup=OpenID Kendinden Kaydı'nı Etkinleştir
config.enable_openid_signin=OpenID Oturum Açmayı Etkinleştiriniz
config.enable_openid_signin=OpenID Oturum Açmayı Etkinleştir
config.show_registration_button=Kaydolma Düğmesini Göster
config.require_sign_in_view=Sayfaları Görüntülemek için Giriş Yapmaya Zorla
config.mail_notify=E-Posta Bildirimlerini Etkinleştir

View file

@ -1780,7 +1780,7 @@ milestones.filter_sort.least_issues=Найменш задач
ext_wiki.desc=Посилання на зовнішню вікі.
wiki=Вікі
wiki.welcome=Ласкаво просимо до Вікі.
wiki.welcome=Ласкаво просимо до вікі.
wiki.welcome_desc=Wiki дозволяє писати та ділитися документацією з співавторами.
wiki.desc=Пишіть та обмінюйтеся документацією із співавторами.
wiki.create_first_page=Створити першу сторінку
@ -2663,6 +2663,11 @@ sync_fork.button = Синхронізувати
sync_fork.branch_behind_one = Ця гілка на %[1]d коміт позаду %[2]s
sync_fork.branch_behind_few = Ця гілка на %[1]d комітів позаду %[2]s
issues.role.first_time_contributor = Новий учасник
settings.event_action_failure = Помилка
settings.event_action_success = Успіх
settings.event_action_recover = Відновлено
commitstatus.success = Успіх
commitstatus.failure = Збій
[graphs]
contributors.what = внески

View file

@ -7,9 +7,9 @@ logo=徽标
sign_in=登录
sign_in_with_provider=使用 %s 登录
sign_in_or=
sign_out=退
sign_out=
sign_up=注册
link_account=链接账
link_account=链接账
register=注册
version=当前版本
powered_by=由 %s 提供支持
@ -743,7 +743,7 @@ social=社交帐号
applications=应用
orgs=组织
repos=仓库列表
delete=删除帐户
delete=删除账号
twofa=两步验证TOTP
account_link=已绑定的帐户
organization=组织
@ -1515,7 +1515,7 @@ projects.card_type.images_and_text=图标和文字
projects.card_type.text_only=仅文本
issues.desc=组织 bug 报告、任务和里程碑。
issues.filter_assignees=筛选指派
issues.filter_assignees=筛选指派成员
issues.filter_milestones=筛选里程碑
issues.filter_projects=筛选项目
issues.filter_labels=筛选标签
@ -1653,7 +1653,7 @@ issues.comment_pull_merged_at=已合并提交 %[1]s 到 %[2]s %[3]s
issues.comment_manually_pull_merged_at=手动合并提交 %[1]s 到 %[2]s %[3]s
issues.close_comment_issue=评论并关闭
issues.reopen_issue=重新开放
issues.reopen_comment_issue=重新打开评论
issues.reopen_comment_issue=重新打开评论
issues.create_comment=评论
issues.closed_at=`于<a id="%[1]s" href="#%[1]s">%[2]s</a>关闭此议题`
issues.reopened_at=`重新打开此问题 <a id="%[1]s" href="#%[1]s">%[2]s</a>`
@ -2304,7 +2304,7 @@ settings.add_collaborator_inactive_user=无法添加未激活的用户作为合
settings.add_collaborator_owner=不能将所有者添加为协作者。
settings.add_collaborator_duplicate=合作者已经被添加到本仓库。
settings.delete_collaborator=删除
settings.collaborator_deletion=除协作者
settings.collaborator_deletion=除协作者
settings.collaborator_deletion_desc=删除协作者后他将无法再对此仓库的访问。继续?
settings.remove_collaborator_success=已成功删除协作者。
settings.search_user_placeholder=搜索用户...

View file

@ -2570,8 +2570,8 @@ tree_path_not_found_tag = 路徑 %[1]s 不存在於標籤 %[2]s 中
tree_path_not_found_commit = 路徑 %[1]s 不存在於提交 %[2]s 中
tree_path_not_found_branch = 路徑 %[1]s 不存在於分支 %[2]s 中
transfer.no_permission_to_accept = 您沒有權限接受這項轉讓。
archive.title = 這個儲存庫被封存了。您可以檢視其中的檔案或是 Clone 它,但您無法推送提交,提出問題或合併請求
archive.title_date = 這個儲存庫在 %s 被封存了。您可以檢視其中的檔案或 clone 它,但您無法推送提交,提出問題或合併請求
archive.title = 這個儲存庫已被封存。您可以檢視其中的檔案或拓製儲存庫,但您無法提交推送和創建新議題、合併請求或評論
archive.title_date = 這個儲存庫在 %s 被封存了。您可以檢視其中的檔案或拓製儲存庫,但您無法提交推送和創建新議題、合併請求或評論
migrate.forgejo.description = 從 codeberg.org 或其他 Forgejo 站點遷移資料。
migrate.cancel_migrating_title = 取消遷移
executable_file = 可執行檔

View file

@ -98,5 +98,7 @@
"followers.incoming.list.none": "Tohoto uživatele nikdo nesleduje.",
"followers.outgoing.list.none": "%s nikoho nesleduje.",
"stars.list.none": "Tento repozitář si nikdo nepřidal do oblíbených.",
"followers.outgoing.list.self.none": "Nikoho nesledujete."
"followers.outgoing.list.self.none": "Nikoho nesledujete.",
"editor.textarea.tab_hint": "Řádek je již odsazen. Pro opuštění editoru stiskněte znovu <kbd>Tab</kbd> nebo <kbd>Escape</kbd>.",
"editor.textarea.shift_tab_hint": "Na tomto řádku není žádné odsazení. Pro opuštění editoru stiskněte znovu <kbd>Shift</kbd> + <kbd>Tab</kbd> nebo <kbd>Escape</kbd>."
}

View file

@ -84,5 +84,13 @@
"moderation.report_remarks.placeholder": "Angiv venligst nogle detaljer vedrørende det misbrug, du anmelder.",
"moderation.submit_report": "Indsend rapport",
"moderation.reporting_failed": "Den nye misbrugsrapport kunne ikke indsendes: %v",
"moderation.reported_thank_you": "Tak for din rapport. Administrationen er blevet gjort opmærksom på den."
"moderation.reported_thank_you": "Tak for din rapport. Administrationen er blevet gjort opmærksom på den.",
"stars.list.none": "Ingen har markeret dette depot med en stjerne.",
"watch.list.none": "Ingen ser dette depot.",
"followers.incoming.list.self.none": "Ingen følger din profil.",
"followers.incoming.list.none": "Ingen følger denne bruger.",
"followers.outgoing.list.self.none": "Du følger ikke nogen.",
"followers.outgoing.list.none": "%s følger ikke nogen.",
"editor.textarea.tab_hint": "Linjen er allerede indrykket. Tryk på <kbd>Tab</kbd> igen eller <kbd>Escape</kbd> for at forlade editoren.",
"editor.textarea.shift_tab_hint": "Ingen indrykning på denne linje. Tryk på <kbd>Shift</kbd> + <kbd>Tab</kbd> igen eller <kbd>Escape</kbd> for at forlade editoren."
}

View file

@ -90,5 +90,7 @@
"followers.outgoing.list.self.none": "Du folgst niemanden.",
"followers.outgoing.list.none": "%s folgt niemanden.",
"stars.list.none": "Niemand hat dieses Repo favorisiert.",
"followers.incoming.list.none": "Niemand folgt diesem Benutzer."
"followers.incoming.list.none": "Niemand folgt diesem Benutzer.",
"editor.textarea.tab_hint": "Zeile bereits eingerückt. Drücke nochmals <kbd>Tab</kbd> oder <kbd>Escape</kbd> um den Editor zu verlassen.",
"editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals <kbd>Shift</kbd> + <kbd>Tab</kbd> oder <kbd>Escape</kbd> um den Editor zu verlassen."
}

View file

@ -92,5 +92,6 @@
"discussion.locked": "This discussion has been locked. Commenting is limited to contributors.",
"editor.textarea.tab_hint": "Line already indented. Press <kbd>Tab</kbd> again or <kbd>Escape</kbd> to leave the editor.",
"editor.textarea.shift_tab_hint": "No indentation on this line. Press <kbd>Shift</kbd> + <kbd>Tab</kbd> again or <kbd>Escape</kbd> to leave the editor.",
"admin.dashboard.cleanup_offline_runners": "Cleanup offline runners",
"meta.last_line": "Thank you for translating Forgejo! This line isn't seen by the users but it serves other purposes in the translation management. You can place a fun fact in the translation instead of translating it."
}

View file

@ -83,5 +83,14 @@
"moderation.submit_report": "I-submit ang ulat",
"moderation.reporting_failed": "Hindi ma-submit ang bagong ulat sa pang aabuso: %v",
"moderation.reported_thank_you": "Salamat sa iyong ulat. Naipaalam na ito sa administrasyon.",
"repo.form.cannot_create": "Naabot na ng lahat ng mga espasyo kung saan ka makakagawa ng mga repositoryo ang limitasyon ng mga repositoryo."
"repo.form.cannot_create": "Naabot na ng lahat ng mga espasyo kung saan ka makakagawa ng mga repositoryo ang limitasyon ng mga repositoryo.",
"stars.list.none": "Wala pang nag-star ng repositoryong ito.",
"followers.incoming.list.self.none": "Walang sumusubaybay sa iyong profile.",
"repo.issue_indexer.title": "Indexer ng Isyu",
"watch.list.none": "Wala pang nanonood sa repositoryong ito.",
"followers.incoming.list.none": "Wala pang sumusunod sa user na ito.",
"followers.outgoing.list.self.none": "Hindi ka sumusunod ng anumang tao.",
"followers.outgoing.list.none": "Hindi sinusundan ni %s ang sinuman.",
"editor.textarea.tab_hint": "Naka-indent na ang linya. Pindutin ulit ang <kbd>Tab</kbd> o <kbd>Escape</kbd> para umalis sa editor.",
"editor.textarea.shift_tab_hint": "Walang indentation sa linyang ito. Pindutin ang <kbd>Shift</kbd> + <kbd>Tab</kbd> ulit o <kbd>Escape</kbd> para umalis sa editor."
}

View file

@ -89,5 +89,13 @@
"moderation.report_remarks": "Remarques",
"moderation.report_remarks.placeholder": "S'il vous plaît fournissez quelques détails en rapport avec l'abus que vous signalez.",
"moderation.submit_report": "Soumettre le signalement",
"moderation.reporting_failed": "Impossible de soumettre le nouveau signalement : %v"
"moderation.reporting_failed": "Impossible de soumettre le nouveau signalement : %v",
"followers.incoming.list.self.none": "Personne ne suit votre profile.",
"followers.incoming.list.none": "Personne ne suit cet utilisateur.",
"followers.outgoing.list.self.none": "Vous ne suivez personne.",
"followers.outgoing.list.none": "%s ne vous suit plus.",
"repo.issue_indexer.title": "Indexeur de problèmes",
"stars.list.none": "Personne n'a mis d'étoiles sur ce dépôt.",
"watch.list.none": "Personne ne consulte ce dépôt.",
"repo.form.cannot_create": "Tous les espaces dans lesquels vous pouvez créer des dépôts ont atteint la limite de dépôts."
}

View file

@ -98,5 +98,7 @@
"followers.outgoing.list.self.none": "Tu nevienam neseko.",
"followers.outgoing.list.none": "%s nevienam neseko.",
"stars.list.none": "Neviens šo glabātavu nav atzīmējis ar zvaigzni.",
"followers.incoming.list.self.none": "Neviens neseko Tavam profilam."
"followers.incoming.list.self.none": "Neviens neseko Tavam profilam.",
"editor.textarea.tab_hint": "Rinda jau ir ar atkāpi. Spied <kbd>Tab</kbd> vēlreiz vai <kbd>Escape</kbd>, lai izietu no redaktora!",
"editor.textarea.shift_tab_hint": "Šajā rindā nav atkāpes. Spied <kbd>Shift</kbd> + <kbd>Tab</kbd> vēlreiz vai <kbd>Escape</kbd>, lai izietu no redaktora!"
}

View file

@ -1,11 +1,11 @@
{
"repo.pulls.merged_title_desc": {
"one": "heeft %[1]d commit van <code>%[2]s</code> samengevoegd in <code>%[3]s</code> %[4]s",
"other": "heeft %[1]d commits samengevoegd van <code>%[2]s</code> naar <code>%[3]s</code> %[4]s"
"other": "heeft %[1]d commits van <code>%[2]s</code> samengevoegd in <code>%[3]s</code> %[4]s"
},
"repo.pulls.title_desc": {
"one": "wil %[1]d commit van <code>%[2]s</code> samenvoegen in <code id=\"%[4]s\">%[3]s</code>",
"other": "wil %[1]d commits van <code>%[2]s</code> samenvoegen met <code id=\"%[4]s\">%[3]s</code>"
"other": "wil %[1]d commits van <code>%[2]s</code> samenvoegen in <code id=\"%[4]s\">%[3]s</code>"
},
"search.milestone_kind": "Zoek mijlpalen…",
"home.welcome.no_activity": "Geen activiteit",
@ -13,27 +13,27 @@
"home.explore_repos": "Verken repositories",
"home.explore_users": "Verken gebruikers",
"home.explore_orgs": "Verken organisaties",
"incorrect_root_url": "Deze Forgejo-instantie is geconfigureerd om geserveerd te worden op \"%s\". U bekijkt Forgejo momenteel via een andere URL, waardoor onderdelen van de applicatie kunnen breken. De canonieke URL kan worden gewijzigd door Forgejo admins via de ROOT_URL instelling in de app.ini.",
"incorrect_root_url": "Deze Forgejo-instantie is geconfigureerd om bereikbaar te zijn op \"%s\". U bekijkt Forgejo momenteel via een andere URL, waardoor onderdelen van de applicatie kunnen breken. De canonieke URL kan worden gewijzigd door Forgejo admins via de ROOT_URL instelling in de app.ini.",
"themes.names.forgejo-auto": "Forgejo (volg het systeemthema)",
"themes.names.forgejo-light": "Forgejo licht",
"themes.names.forgejo-dark": "Forgejo donker",
"error.not_found.title": "Pagina niet gevonden",
"alert.asset_load_failed": "Het laden van asset-bestanden van {path} is mislukt. Controleer of de asset-bestanden toegankelijk zijn.",
"install.invalid_lfs_path": "Kan de LFS-root niet aanmaken op het opgegeven pad: %[1]s",
"alert.asset_load_failed": "Het laden van hulp-bestanden vanuit {path} is mislukt. Controleer of de hulp-bestanden toegankelijk zijn.",
"install.invalid_lfs_path": "Kan de LFS-root niet aanmaken op de opgegeven locatie: %[1]s",
"alert.range_error": " moet een getal zijn tussen %[1]s en %[2]s.",
"meta.last_line": "Wist je dat de paprika, behalve in de bekende kleuren rood, geel, oranje en groen, ook in de kleuren wit, paars, lila, muntgroen en bruin voorkomt.",
"mail.actions.successful_run_after_failure_subject": "Werkstroom %[1]s hersteld in repository %[2]s",
"mail.actions.not_successful_run_subject": "Werkstroom %[1]s mislukt in repository %[2]s",
"mail.actions.successful_run_after_failure": "Werkstroom %[1]s hersteld in repository %[2]s",
"mail.actions.not_successful_run": "Werkstroom %[1]s mislukt in repository %[2]s",
"mail.actions.successful_run_after_failure_subject": "Werkstroom %[1]s hersteld in repositorie %[2]s",
"mail.actions.not_successful_run_subject": "Werkstroom %[1]s mislukt in repositorie %[2]s",
"mail.actions.successful_run_after_failure": "Werkstroom %[1]s hersteld in repositorie %[2]s",
"mail.actions.not_successful_run": "Werkstroom %[1]s mislukt in repositorie %[2]s",
"mail.actions.run_info_cur_status": "De status van deze run: %[1]s (zojuist bijgewerkt van %[2]s)",
"mail.actions.run_info_previous_status": "Status vorige run: %[1]s",
"mail.actions.run_info_ref": "Branch: %[1]s (%[2]s)",
"mail.actions.run_info_trigger": "Getriggerd omdat: %[1]s door: %[2]s",
"discussion.locked": "Deze discussie is gesloten. Commentaar is beperkt tot bijdragers.",
"discussion.locked": "Deze discussie is afgesloten. Commentaar is alleen mogelijk voor bijdragers.",
"relativetime.now": "nu",
"relativetime.future": "in de toekomst",
"repo.form.cannot_create": "Alle spaces waarin u repositories kan maken hebben hun maximum aantal repositories bereikt.",
"repo.form.cannot_create": "Alle ruimtes waarin u repositories kan maken hebben hun maximum aantal repositories bereikt.",
"moderation.report_content": "Meldt content",
"moderation.report_abuse_form.header": "Meld misbruik bij de beheerder",
"moderation.report_abuse_form.invalid": "Ongeldige argumenten",
@ -86,5 +86,11 @@
"relativetime.hours": {
"one": "%d uur geleden",
"other": "%d uren geleden"
}
},
"repo.issue_indexer.title": "Issue indexer",
"stars.list.none": "Niemand heeft deze repo een ster gegeven.",
"watch.list.none": "Niemand houdt deze repo in de gaten.",
"followers.incoming.list.self.none": "Niemand volgt uw profiel.",
"followers.incoming.list.none": "Deze gebruiker wordt door niemand gevolgd.",
"followers.outgoing.list.self.none": "U volgt niemand."
}

View file

@ -98,5 +98,7 @@
"followers.incoming.list.none": "Ninguém está seguindo este perfil.",
"followers.outgoing.list.none": "%s não está seguindo ninguém.",
"stars.list.none": "Ninguém favoritou este repositório.",
"followers.outgoing.list.self.none": "Você não está seguindo ninguém."
"followers.outgoing.list.self.none": "Você não está seguindo ninguém.",
"editor.textarea.tab_hint": "Linha já indentada. Pressione <kbd>Tab</kbd> novamente ou <kbd>Esc</kbd> para sair do editor.",
"editor.textarea.shift_tab_hint": "Sem indentação nesta linha. Pressione <kbd>Shift</kbd> + <kbd>Tab</kbd> novamente ou <kbd>Esc</kbd> para sair do editor."
}

View file

@ -98,5 +98,7 @@
"moderation.reported_thank_you": "Спасибо за ваше сообщение. Администрация оповещена.",
"moderation.report_abuse_form.details": "Через эту форму можно жаловаться на пользователей, распространяющих спам или ведущих себя неадекватно.",
"moderation.report_abuse_form.invalid": "Невалидные аргументы",
"moderation.report_abuse_form.header": "Жалоба администрации"
"moderation.report_abuse_form.header": "Жалоба администрации",
"editor.textarea.tab_hint": "Отступ уже добавлен. Нажмите <kbd>Tab</kbd> снова или <kbd>Escape</kbd>, чтобы покинуть редактор.",
"editor.textarea.shift_tab_hint": "В строке нет отступов. Нажмите <kbd>Shift</kbd> + <kbd>Tab</kbd> снова или <kbd>Escape</kbd>, чтобы покинуть редактор."
}

View file

@ -66,5 +66,7 @@
"followers.outgoing.list.self.none": "你没有关注任何人。",
"followers.outgoing.list.none": "%s 没有关注任何人。",
"stars.list.none": "没有人点赞这个仓库。",
"followers.incoming.list.self.none": "没有人关注你的个人资料。"
"followers.incoming.list.self.none": "没有人关注你的个人资料。",
"editor.textarea.tab_hint": "此行已缩进。再次按 <kbd>Tab</kbd> 或按 <kbd>Escape</kbd> 退出编辑器。",
"editor.textarea.shift_tab_hint": "此行无缩进。再次按 <kbd>Shift</kbd> + <kbd>Tab</kbd> 或按 <kbd>Escape</kbd> 退出编辑器。"
}

View file

@ -1,5 +1,71 @@
{
"repo.pulls.merged_title_desc": "將 %[1]d 次提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "請求將 %[1]d 次程式碼提交從 <code>%[2]s</code> 合併至 <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "搜尋里程碑…"
"search.milestone_kind": "搜尋里程碑…",
"home.welcome.no_activity": "沒有活動",
"home.welcome.activity_hint": "您的動態摘要目前沒有任何內容。 您對關注的儲存庫所做的操作與活動將會顯示在這裡。",
"stars.list.none": "沒有人標星這個儲存庫。",
"watch.list.none": "沒有人關注這個儲存庫。",
"home.explore_repos": "探索儲存庫",
"home.explore_users": "探索使用者",
"home.explore_orgs": "探索組織",
"alert.range_error": " 必須是一個介於 %[1]s 和 %[2]s 之間的數字。",
"install.invalid_lfs_path": "無法在指定路徑建立 LFS 根目錄:%[1]s",
"relativetime.now": "現在",
"relativetime.future": "未來",
"repo.form.cannot_create": "您可以建立儲存庫的所有空間都已達到儲存庫上限。",
"repo.issue_indexer.title": "問題索引器",
"moderation.abuse_category": "分類",
"moderation.abuse_category.placeholder": "選擇分類",
"moderation.abuse_category.spam": "垃圾訊息",
"moderation.abuse_category.malware": "惡意軟體",
"moderation.abuse_category.illegal_content": "違法內容",
"moderation.report_remarks.placeholder": "請提供您所檢舉濫用行為的相關細節。",
"moderation.report_remarks": "備註",
"moderation.submit_report": "提交檢舉",
"moderation.reporting_failed": "無法提交新的濫用回報:%v",
"moderation.reported_thank_you": "感謝您的回報,管理團隊已收到相關通知。",
"mail.actions.successful_run_after_failure_subject": "儲存庫 %[2]s 中的工作流程 %[1]s 已恢復",
"error.not_found.title": "找不到頁面",
"incorrect_root_url": "這個 Forgejo 實例設定為在 \"%s\" 上提供服務。您目前是透過不同的 URL 存取 Forgejo這可能會導致部分功能無法正常運作。正式的 URL 是由 Forgejo 管理員透過 app.ini 中的 ROOT_URL 設定所控制。",
"themes.names.forgejo-auto": "Forgejo遵循系統主題",
"themes.names.forgejo-light": "Forgejo 淺色",
"themes.names.forgejo-dark": "Forgejo 深色",
"followers.incoming.list.self.none": "沒有人關注您的個人資料。",
"followers.incoming.list.none": "沒有人關注這位使用者。",
"followers.outgoing.list.none": "%s 沒有追蹤任何人。",
"followers.outgoing.list.self.none": "您沒有追蹤任何人。",
"relativetime.mins": "%d 分鐘前",
"relativetime.hours": "%d 小時前",
"relativetime.days": "%d 天前",
"relativetime.weeks": "%d 周前",
"relativetime.months": "%d 個月前",
"relativetime.years": "%d 年前",
"relativetime.1day": "昨天",
"relativetime.2days": "兩天前",
"relativetime.1week": "上週",
"relativetime.2weeks": "兩週前",
"relativetime.1month": "上個月",
"relativetime.2months": "兩個月前",
"relativetime.1year": "去年",
"relativetime.2years": "兩年前",
"moderation.abuse_category.other_violations": "其他違反平台規則的行為",
"mail.actions.not_successful_run_subject": "儲存庫 %[2]s 中的工作流程 %[1]s 已失敗",
"mail.actions.successful_run_after_failure": "儲存庫 %[2]s 中的工作流程 %[1]s 已恢復",
"mail.actions.not_successful_run": "儲存庫 %[2]s 中的工作流程 %[1]s 已失敗",
"mail.actions.run_info_cur_status": "本次執行狀態:%[1]s剛從 %[2]s 更新)",
"mail.actions.run_info_previous_status": "前一次執行狀態:%[1]s",
"mail.actions.run_info_ref": "分支:%[1]s (%[2]s)",
"mail.actions.run_info_trigger": "觸發原因:%[1]s由 %[2]s 執行",
"discussion.locked": "此討論已被鎖定。僅限貢獻者留言。",
"alert.asset_load_failed": "無法從 {path} 載入資源檔案。請確保這些資源檔案可以被存取。",
"editor.textarea.tab_hint": "此行已縮排。再次按下 <kbd>Tab</kbd> 鍵或按下 <kbd>Escape</kbd> 鍵以離開編輯器。",
"editor.textarea.shift_tab_hint": "此行未縮排。請再次按下 <kbd>Shift</kbd> + <kbd>Tab</kbd>,或按下 <kbd>Escape</kbd> 鍵以離開編輯器。",
"admin.config.moderation_config": "審核設定",
"moderation.report_abuse": "回報濫用行為",
"moderation.report_content": "檢舉內容",
"moderation.report_abuse_form.header": "向管理員回報濫用",
"moderation.report_abuse_form.details": "這個表單是用來檢舉用戶建立垃圾帳號、儲存庫、問題、留言,或其他不當行為。",
"moderation.report_abuse_form.invalid": "無效參數",
"moderation.report_abuse_form.already_reported": "您已檢舉此內容"
}

1726
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@
"monaco-editor": "0.52.2",
"monaco-editor-webpack-plugin": "7.1.0",
"pdfobject": "2.3.0",
"postcss": "8.5.2",
"postcss": "8.5.4",
"postcss-loader": "8.1.1",
"postcss-nesting": "13.0.1",
"pretty-ms": "9.0.0",
@ -50,7 +50,7 @@
"tributejs": "5.1.3",
"uint8-to-base64": "0.2.0",
"vanilla-colorful": "0.7.2",
"vue": "3.5.14",
"vue": "3.5.16",
"vue-chartjs": "5.3.1",
"vue-loader": "17.4.2",
"vue3-calendar-heatmap": "2.0.5",
@ -59,47 +59,46 @@
"wrap-ansi": "9.0.0"
},
"devDependencies": {
"@axe-core/playwright": "4.10.1",
"@axe-core/playwright": "4.10.2",
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
"@playwright/test": "1.52.0",
"@stoplight/spectral-cli": "6.15.0",
"@stylistic/eslint-plugin-js": "4.2.0",
"@stylistic/eslint-plugin-js": "4.4.1",
"@stylistic/stylelint-plugin": "3.1.2",
"@typescript-eslint/parser": "8.31.1",
"@vitejs/plugin-vue": "5.2.3",
"@vitest/coverage-v8": "3.1.2",
"@vitest/eslint-plugin": "1.1.43",
"@vitejs/plugin-vue": "5.2.4",
"@vitest/coverage-v8": "3.2.3",
"@vitest/eslint-plugin": "1.2.1",
"@vue/test-utils": "2.4.6",
"eslint": "9.25.1",
"eslint-import-resolver-typescript": "4.3.4",
"eslint": "9.28.0",
"eslint-import-resolver-typescript": "4.4.3",
"eslint-plugin-array-func": "5.0.2",
"eslint-plugin-import-x": "4.11.0",
"eslint-plugin-import-x": "4.15.1",
"eslint-plugin-no-jquery": "3.1.1",
"eslint-plugin-no-use-extend-native": "0.7.2",
"eslint-plugin-playwright": "2.2.0",
"eslint-plugin-regexp": "2.7.0",
"eslint-plugin-regexp": "2.9.0",
"eslint-plugin-sonarjs": "3.0.2",
"eslint-plugin-unicorn": "59.0.0",
"eslint-plugin-unicorn": "59.0.1",
"eslint-plugin-toml": "0.12.0",
"eslint-plugin-vitest-globals": "1.5.0",
"eslint-plugin-vue": "10.1.0",
"eslint-plugin-vue-scoped-css": "2.9.0",
"eslint-plugin-vue": "10.2.0",
"eslint-plugin-vue-scoped-css": "2.10.0",
"eslint-plugin-wc": "2.2.1",
"globals": "16.1.0",
"happy-dom": "17.4.6",
"happy-dom": "17.6.3",
"license-checker-rseidelsohn": "4.4.2",
"markdownlint-cli": "0.44.0",
"markdownlint-cli": "0.45.0",
"postcss-html": "1.8.0",
"sharp": "0.34.2",
"stylelint": "16.19.1",
"stylelint": "16.20.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.11",
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "3.2.0",
"typescript": "5.8.3",
"typescript-eslint": "8.31.1",
"typescript-eslint": "8.33.1",
"vite-string-plugin": "1.3.4",
"vitest": "3.1.2"
"vitest": "3.2.3"
},
"browserslist": [
"defaults"

Some files were not shown because too many files have changed in this diff Show more