2014-02-15 04:46:54 +05:30
// Copyright 2014 The Gogs Authors. All rights reserved.
2017-08-26 19:27:41 +05:30
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-27 23:50:29 +05:30
// SPDX-License-Identifier: MIT
2014-02-15 04:46:54 +05:30
2014-02-14 19:50:57 +05:30
package models
import (
2019-12-15 15:21:28 +05:30
"context"
2014-03-11 06:18:58 +05:30
"fmt"
2019-04-23 02:10:51 +05:30
"strconv"
2014-02-14 19:50:57 +05:30
2021-11-17 18:04:35 +05:30
_ "image/jpeg" // Needed for jpeg support
Implement actions (#21937)
Close #13539.
Co-authored by: @lunny @appleboy @fuxiaohei and others.
Related projects:
- https://gitea.com/gitea/actions-proto-def
- https://gitea.com/gitea/actions-proto-go
- https://gitea.com/gitea/act
- https://gitea.com/gitea/act_runner
### Summary
The target of this PR is to bring a basic implementation of "Actions",
an internal CI/CD system of Gitea. That means even though it has been
merged, the state of the feature is **EXPERIMENTAL**, and please note
that:
- It is disabled by default;
- It shouldn't be used in a production environment currently;
- It shouldn't be used in a public Gitea instance currently;
- Breaking changes may be made before it's stable.
**Please comment on #13539 if you have any different product design
ideas**, all decisions reached there will be adopted here. But in this
PR, we don't talk about **naming, feature-creep or alternatives**.
### ⚠️ Breaking
`gitea-actions` will become a reserved user name. If a user with the
name already exists in the database, it is recommended to rename it.
### Some important reviews
- What is `DEFAULT_ACTIONS_URL` in `app.ini` for?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1055954954
- Why the api for runners is not under the normal `/api/v1` prefix?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061173592
- Why DBFS?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061301178
- Why ignore events triggered by `gitea-actions` bot?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1063254103
- Why there's no permission control for actions?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1090229868
### What it looks like
<details>
#### Manage runners
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205870657-c72f590e-2e08-4cd4-be7f-2e0abb299bbf.png">
#### List runs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872794-50fde990-2b45-48c1-a178-908e4ec5b627.png">
#### View logs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872501-9b7b9000-9542-4991-8f55-18ccdada77c3.png">
</details>
### How to try it
<details>
#### 1. Start Gitea
Clone this branch and [install from
source](https://docs.gitea.io/en-us/install-from-source).
Add additional configurations in `app.ini` to enable Actions:
```ini
[actions]
ENABLED = true
```
Start it.
If all is well, you'll see the management page of runners:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205877365-8e30a780-9b10-4154-b3e8-ee6c3cb35a59.png">
#### 2. Start runner
Clone the [act_runner](https://gitea.com/gitea/act_runner), and follow
the
[README](https://gitea.com/gitea/act_runner/src/branch/main/README.md)
to start it.
If all is well, you'll see a new runner has been added:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205878000-216f5937-e696-470d-b66c-8473987d91c3.png">
#### 3. Enable actions for a repo
Create a new repo or open an existing one, check the `Actions` checkbox
in settings and submit.
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879705-53e09208-73c0-4b3e-a123-2dcf9aba4b9c.png">
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879383-23f3d08f-1a85-41dd-a8b3-54e2ee6453e8.png">
If all is well, you'll see a new tab "Actions":
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205881648-a8072d8c-5803-4d76-b8a8-9b2fb49516c1.png">
#### 4. Upload workflow files
Upload some workflow files to `.gitea/workflows/xxx.yaml`, you can
follow the [quickstart](https://docs.github.com/en/actions/quickstart)
of GitHub Actions. Yes, Gitea Actions is compatible with GitHub Actions
in most cases, you can use the same demo:
```yaml
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
```
If all is well, you'll see a new run in `Actions` tab:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884473-79a874bc-171b-4aaf-acd5-0241a45c3b53.png">
#### 5. Check the logs of jobs
Click a run and you'll see the logs:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884800-994b0374-67f7-48ff-be9a-4c53f3141547.png">
#### 6. Go on
You can try more examples in [the
documents](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
of GitHub Actions, then you might find a lot of bugs.
Come on, PRs are welcome.
</details>
See also: [Feature Preview: Gitea
Actions](https://blog.gitea.io/2022/12/feature-preview-gitea-actions/)
---------
Co-authored-by: a1012112796 <1012112796@qq.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2023-01-31 07:15:19 +05:30
actions_model "code.gitea.io/gitea/models/actions"
2022-08-25 08:01:57 +05:30
activities_model "code.gitea.io/gitea/models/activities"
2021-11-18 11:28:42 +05:30
admin_model "code.gitea.io/gitea/models/admin"
2021-12-10 13:44:24 +05:30
asymkey_model "code.gitea.io/gitea/models/asymkey"
2021-09-19 17:19:59 +05:30
"code.gitea.io/gitea/models/db"
2022-06-12 21:21:54 +05:30
git_model "code.gitea.io/gitea/models/git"
2022-04-08 14:41:15 +05:30
issues_model "code.gitea.io/gitea/models/issues"
2022-03-29 11:59:02 +05:30
"code.gitea.io/gitea/models/organization"
2022-05-11 15:39:36 +05:30
access_model "code.gitea.io/gitea/models/perm/access"
2022-03-29 19:46:31 +05:30
project_model "code.gitea.io/gitea/models/project"
2021-11-19 19:09:57 +05:30
repo_model "code.gitea.io/gitea/models/repo"
2022-12-20 14:37:13 +05:30
secret_model "code.gitea.io/gitea/models/secret"
2022-10-17 04:59:26 +05:30
system_model "code.gitea.io/gitea/models/system"
2021-11-10 01:27:58 +05:30
"code.gitea.io/gitea/models/unit"
2021-11-24 15:19:20 +05:30
user_model "code.gitea.io/gitea/models/user"
2021-11-10 10:43:16 +05:30
"code.gitea.io/gitea/models/webhook"
Implement actions (#21937)
Close #13539.
Co-authored by: @lunny @appleboy @fuxiaohei and others.
Related projects:
- https://gitea.com/gitea/actions-proto-def
- https://gitea.com/gitea/actions-proto-go
- https://gitea.com/gitea/act
- https://gitea.com/gitea/act_runner
### Summary
The target of this PR is to bring a basic implementation of "Actions",
an internal CI/CD system of Gitea. That means even though it has been
merged, the state of the feature is **EXPERIMENTAL**, and please note
that:
- It is disabled by default;
- It shouldn't be used in a production environment currently;
- It shouldn't be used in a public Gitea instance currently;
- Breaking changes may be made before it's stable.
**Please comment on #13539 if you have any different product design
ideas**, all decisions reached there will be adopted here. But in this
PR, we don't talk about **naming, feature-creep or alternatives**.
### ⚠️ Breaking
`gitea-actions` will become a reserved user name. If a user with the
name already exists in the database, it is recommended to rename it.
### Some important reviews
- What is `DEFAULT_ACTIONS_URL` in `app.ini` for?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1055954954
- Why the api for runners is not under the normal `/api/v1` prefix?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061173592
- Why DBFS?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061301178
- Why ignore events triggered by `gitea-actions` bot?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1063254103
- Why there's no permission control for actions?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1090229868
### What it looks like
<details>
#### Manage runners
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205870657-c72f590e-2e08-4cd4-be7f-2e0abb299bbf.png">
#### List runs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872794-50fde990-2b45-48c1-a178-908e4ec5b627.png">
#### View logs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872501-9b7b9000-9542-4991-8f55-18ccdada77c3.png">
</details>
### How to try it
<details>
#### 1. Start Gitea
Clone this branch and [install from
source](https://docs.gitea.io/en-us/install-from-source).
Add additional configurations in `app.ini` to enable Actions:
```ini
[actions]
ENABLED = true
```
Start it.
If all is well, you'll see the management page of runners:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205877365-8e30a780-9b10-4154-b3e8-ee6c3cb35a59.png">
#### 2. Start runner
Clone the [act_runner](https://gitea.com/gitea/act_runner), and follow
the
[README](https://gitea.com/gitea/act_runner/src/branch/main/README.md)
to start it.
If all is well, you'll see a new runner has been added:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205878000-216f5937-e696-470d-b66c-8473987d91c3.png">
#### 3. Enable actions for a repo
Create a new repo or open an existing one, check the `Actions` checkbox
in settings and submit.
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879705-53e09208-73c0-4b3e-a123-2dcf9aba4b9c.png">
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879383-23f3d08f-1a85-41dd-a8b3-54e2ee6453e8.png">
If all is well, you'll see a new tab "Actions":
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205881648-a8072d8c-5803-4d76-b8a8-9b2fb49516c1.png">
#### 4. Upload workflow files
Upload some workflow files to `.gitea/workflows/xxx.yaml`, you can
follow the [quickstart](https://docs.github.com/en/actions/quickstart)
of GitHub Actions. Yes, Gitea Actions is compatible with GitHub Actions
in most cases, you can use the same demo:
```yaml
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
```
If all is well, you'll see a new run in `Actions` tab:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884473-79a874bc-171b-4aaf-acd5-0241a45c3b53.png">
#### 5. Check the logs of jobs
Click a run and you'll see the logs:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884800-994b0374-67f7-48ff-be9a-4c53f3141547.png">
#### 6. Go on
You can try more examples in [the
documents](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
of GitHub Actions, then you might find a lot of bugs.
Come on, PRs are welcome.
</details>
See also: [Feature Preview: Gitea
Actions](https://blog.gitea.io/2022/12/feature-preview-gitea-actions/)
---------
Co-authored-by: a1012112796 <1012112796@qq.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2023-01-31 07:15:19 +05:30
actions_module "code.gitea.io/gitea/modules/actions"
2021-04-09 03:55:57 +05:30
"code.gitea.io/gitea/modules/lfs"
2016-11-10 21:54:48 +05:30
"code.gitea.io/gitea/modules/log"
2020-08-18 09:53:45 +05:30
"code.gitea.io/gitea/modules/storage"
2017-01-01 23:45:09 +05:30
2020-06-13 17:05:59 +05:30
"xorm.io/builder"
2014-02-14 19:50:57 +05:30
)
2022-10-17 04:59:26 +05:30
// Init initialize model
2023-02-24 15:53:13 +05:30
func Init ( ctx context . Context ) error {
2023-05-06 15:09:06 +05:30
if err := unit . LoadUnitConfig ( ) ; err != nil {
return err
}
2023-02-24 15:53:13 +05:30
return system_model . Init ( ctx )
2014-03-11 11:02:36 +05:30
}
2014-12-07 06:52:48 +05:30
// DeleteRepository deletes a repository for a user or organization.
2021-01-19 01:30:50 +05:30
// make sure if you call this func to close open sessions (sqlite will otherwise get a deadlock)
2021-11-24 15:19:20 +05:30
func DeleteRepository ( doer * user_model . User , uid , repoID int64 ) error {
2022-11-13 01:48:50 +05:30
ctx , committer , err := db . TxContext ( db . DefaultContext )
2021-11-21 21:11:00 +05:30
if err != nil {
2021-01-19 01:30:50 +05:30
return err
}
2021-11-21 21:11:00 +05:30
defer committer . Close ( )
sess := db . GetEngine ( ctx )
2021-01-19 01:30:50 +05:30
Implement actions (#21937)
Close #13539.
Co-authored by: @lunny @appleboy @fuxiaohei and others.
Related projects:
- https://gitea.com/gitea/actions-proto-def
- https://gitea.com/gitea/actions-proto-go
- https://gitea.com/gitea/act
- https://gitea.com/gitea/act_runner
### Summary
The target of this PR is to bring a basic implementation of "Actions",
an internal CI/CD system of Gitea. That means even though it has been
merged, the state of the feature is **EXPERIMENTAL**, and please note
that:
- It is disabled by default;
- It shouldn't be used in a production environment currently;
- It shouldn't be used in a public Gitea instance currently;
- Breaking changes may be made before it's stable.
**Please comment on #13539 if you have any different product design
ideas**, all decisions reached there will be adopted here. But in this
PR, we don't talk about **naming, feature-creep or alternatives**.
### ⚠️ Breaking
`gitea-actions` will become a reserved user name. If a user with the
name already exists in the database, it is recommended to rename it.
### Some important reviews
- What is `DEFAULT_ACTIONS_URL` in `app.ini` for?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1055954954
- Why the api for runners is not under the normal `/api/v1` prefix?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061173592
- Why DBFS?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061301178
- Why ignore events triggered by `gitea-actions` bot?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1063254103
- Why there's no permission control for actions?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1090229868
### What it looks like
<details>
#### Manage runners
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205870657-c72f590e-2e08-4cd4-be7f-2e0abb299bbf.png">
#### List runs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872794-50fde990-2b45-48c1-a178-908e4ec5b627.png">
#### View logs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872501-9b7b9000-9542-4991-8f55-18ccdada77c3.png">
</details>
### How to try it
<details>
#### 1. Start Gitea
Clone this branch and [install from
source](https://docs.gitea.io/en-us/install-from-source).
Add additional configurations in `app.ini` to enable Actions:
```ini
[actions]
ENABLED = true
```
Start it.
If all is well, you'll see the management page of runners:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205877365-8e30a780-9b10-4154-b3e8-ee6c3cb35a59.png">
#### 2. Start runner
Clone the [act_runner](https://gitea.com/gitea/act_runner), and follow
the
[README](https://gitea.com/gitea/act_runner/src/branch/main/README.md)
to start it.
If all is well, you'll see a new runner has been added:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205878000-216f5937-e696-470d-b66c-8473987d91c3.png">
#### 3. Enable actions for a repo
Create a new repo or open an existing one, check the `Actions` checkbox
in settings and submit.
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879705-53e09208-73c0-4b3e-a123-2dcf9aba4b9c.png">
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879383-23f3d08f-1a85-41dd-a8b3-54e2ee6453e8.png">
If all is well, you'll see a new tab "Actions":
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205881648-a8072d8c-5803-4d76-b8a8-9b2fb49516c1.png">
#### 4. Upload workflow files
Upload some workflow files to `.gitea/workflows/xxx.yaml`, you can
follow the [quickstart](https://docs.github.com/en/actions/quickstart)
of GitHub Actions. Yes, Gitea Actions is compatible with GitHub Actions
in most cases, you can use the same demo:
```yaml
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
```
If all is well, you'll see a new run in `Actions` tab:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884473-79a874bc-171b-4aaf-acd5-0241a45c3b53.png">
#### 5. Check the logs of jobs
Click a run and you'll see the logs:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884800-994b0374-67f7-48ff-be9a-4c53f3141547.png">
#### 6. Go on
You can try more examples in [the
documents](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
of GitHub Actions, then you might find a lot of bugs.
Come on, PRs are welcome.
</details>
See also: [Feature Preview: Gitea
Actions](https://blog.gitea.io/2022/12/feature-preview-gitea-actions/)
---------
Co-authored-by: a1012112796 <1012112796@qq.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2023-01-31 07:15:19 +05:30
// Query the action tasks of this repo, they will be needed after they have been deleted to remove the logs
tasks , err := actions_model . FindTasks ( ctx , actions_model . FindTaskOptions { RepoID : repoID } )
if err != nil {
return fmt . Errorf ( "find actions tasks of repo %v: %w" , repoID , err )
}
2023-05-19 19:07:57 +05:30
// Query the artifacts of this repo, they will be needed after they have been deleted to remove artifacts files in ObjectStorage
artifacts , err := actions_model . ListArtifactsByRepoID ( ctx , repoID )
if err != nil {
return fmt . Errorf ( "list actions artifacts of repo %v: %w" , repoID , err )
}
2014-08-27 14:09:36 +05:30
// In case is a organization.
2022-12-03 08:18:26 +05:30
org , err := user_model . GetUserByID ( ctx , uid )
2014-08-27 14:09:36 +05:30
if err != nil {
return err
}
2021-12-10 06:57:50 +05:30
repo := & repo_model . Repository { OwnerID : uid }
2021-01-19 01:30:50 +05:30
has , err := sess . ID ( repoID ) . Get ( repo )
2017-03-01 09:35:45 +05:30
if err != nil {
return err
} else if ! has {
2021-12-10 06:57:50 +05:30
return repo_model . ErrRepoNotExist {
ID : repoID ,
UID : uid ,
OwnerName : "" ,
Name : "" ,
}
2017-03-01 09:35:45 +05:30
}
2019-02-04 05:26:53 +05:30
// Delete Deploy Keys
2021-12-10 13:44:24 +05:30
deployKeys , err := asymkey_model . ListDeployKeys ( ctx , & asymkey_model . ListDeployKeysOptions { RepoID : repoID } )
2019-02-04 05:26:53 +05:30
if err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "listDeployKeys: %w" , err )
2019-02-04 05:26:53 +05:30
}
2022-01-20 23:16:10 +05:30
needRewriteKeysFile := len ( deployKeys ) > 0
2019-02-04 05:26:53 +05:30
for _ , dKey := range deployKeys {
2021-12-10 13:44:24 +05:30
if err := DeleteDeployKey ( ctx , doer , dKey . ID ) ; err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "deleteDeployKeys: %w" , err )
2019-02-04 05:26:53 +05:30
}
}
2021-12-10 06:57:50 +05:30
if cnt , err := sess . ID ( repoID ) . Delete ( & repo_model . Repository { } ) ; err != nil {
2017-03-01 09:35:45 +05:30
return err
} else if cnt != 1 {
2021-12-10 06:57:50 +05:30
return repo_model . ErrRepoNotExist {
ID : repoID ,
UID : uid ,
OwnerName : "" ,
Name : "" ,
}
2017-03-01 09:35:45 +05:30
}
2014-08-27 14:09:36 +05:30
if org . IsOrganization ( ) {
2022-03-29 11:59:02 +05:30
teams , err := organization . FindOrgTeams ( ctx , org . ID )
2021-11-19 17:11:40 +05:30
if err != nil {
return err
}
for _ , t := range teams {
2022-05-11 15:39:36 +05:30
if ! organization . HasTeamRepo ( ctx , t . OrgID , t . ID , repoID ) {
2014-08-27 14:09:36 +05:30
continue
2022-03-29 11:59:02 +05:30
} else if err = removeRepository ( ctx , t , repo , false ) ; err != nil {
2014-08-27 14:09:36 +05:30
return err
}
}
}
2021-11-19 19:09:57 +05:30
attachments := make ( [ ] * repo_model . Attachment , 0 , 20 )
2019-12-12 11:01:05 +05:30
if err = sess . Join ( "INNER" , "`release`" , "`release`.id = `attachment`.release_id" ) .
Where ( "`release`.repo_id = ?" , repoID ) .
Find ( & attachments ) ; err != nil {
return err
}
releaseAttachments := make ( [ ] string , 0 , len ( attachments ) )
for i := 0 ; i < len ( attachments ) ; i ++ {
2020-08-18 09:53:45 +05:30
releaseAttachments = append ( releaseAttachments , attachments [ i ] . RelativePath ( ) )
2019-12-12 11:01:05 +05:30
}
2022-05-20 19:38:52 +05:30
if _ , err := db . Exec ( ctx , "UPDATE `user` SET num_stars=num_stars-1 WHERE id IN (SELECT `uid` FROM `star` WHERE repo_id = ?)" , repo . ID ) ; err != nil {
2020-07-08 00:46:34 +05:30
return err
}
2022-10-21 21:51:56 +05:30
if _ , err := db . GetEngine ( ctx ) . In ( "hook_id" , builder . Select ( "id" ) . From ( "webhook" ) . Where ( builder . Eq { "webhook.repo_id" : repo . ID } ) ) .
Delete ( & webhook . HookTask { } ) ; err != nil {
return err
}
2022-02-17 14:07:48 +05:30
if err := db . DeleteBeans ( ctx ,
2022-05-11 15:39:36 +05:30
& access_model . Access { RepoID : repo . ID } ,
2022-08-25 08:01:57 +05:30
& activities_model . Action { RepoID : repo . ID } ,
2022-05-11 15:39:36 +05:30
& repo_model . Collaboration { RepoID : repoID } ,
2022-06-13 15:07:59 +05:30
& issues_model . Comment { RefRepoID : repoID } ,
2022-06-12 21:21:54 +05:30
& git_model . CommitStatus { RepoID : repoID } ,
2023-06-29 15:33:20 +05:30
& git_model . Branch { RepoID : repoID } ,
2022-06-12 21:21:54 +05:30
& git_model . LFSLock { RepoID : repoID } ,
2021-12-10 06:57:50 +05:30
& repo_model . LanguageStat { RepoID : repoID } ,
2022-04-08 14:41:15 +05:30
& issues_model . Milestone { RepoID : repoID } ,
2021-12-10 06:57:50 +05:30
& repo_model . Mirror { RepoID : repoID } ,
2022-08-25 08:01:57 +05:30
& activities_model . Notification { RepoID : repoID } ,
2022-06-12 21:21:54 +05:30
& git_model . ProtectedBranch { RepoID : repoID } ,
& git_model . ProtectedTag { RepoID : repoID } ,
2021-12-10 06:57:50 +05:30
& repo_model . PushMirror { RepoID : repoID } ,
2022-08-25 08:01:57 +05:30
& repo_model . Release { RepoID : repoID } ,
2021-12-10 06:57:50 +05:30
& repo_model . RepoIndexerStatus { RepoID : repoID } ,
2021-12-12 21:18:20 +05:30
& repo_model . Redirect { RedirectRepoID : repoID } ,
2021-12-10 06:57:50 +05:30
& repo_model . RepoUnit { RepoID : repoID } ,
2021-12-12 21:18:20 +05:30
& repo_model . Star { RepoID : repoID } ,
2022-08-25 08:01:57 +05:30
& admin_model . Task { RepoID : repoID } ,
2021-12-12 21:18:20 +05:30
& repo_model . Watch { RepoID : repoID } ,
2021-11-10 10:43:16 +05:30
& webhook . Webhook { RepoID : repoID } ,
2022-12-20 14:37:13 +05:30
& secret_model . Secret { RepoID : repoID } ,
Implement actions (#21937)
Close #13539.
Co-authored by: @lunny @appleboy @fuxiaohei and others.
Related projects:
- https://gitea.com/gitea/actions-proto-def
- https://gitea.com/gitea/actions-proto-go
- https://gitea.com/gitea/act
- https://gitea.com/gitea/act_runner
### Summary
The target of this PR is to bring a basic implementation of "Actions",
an internal CI/CD system of Gitea. That means even though it has been
merged, the state of the feature is **EXPERIMENTAL**, and please note
that:
- It is disabled by default;
- It shouldn't be used in a production environment currently;
- It shouldn't be used in a public Gitea instance currently;
- Breaking changes may be made before it's stable.
**Please comment on #13539 if you have any different product design
ideas**, all decisions reached there will be adopted here. But in this
PR, we don't talk about **naming, feature-creep or alternatives**.
### ⚠️ Breaking
`gitea-actions` will become a reserved user name. If a user with the
name already exists in the database, it is recommended to rename it.
### Some important reviews
- What is `DEFAULT_ACTIONS_URL` in `app.ini` for?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1055954954
- Why the api for runners is not under the normal `/api/v1` prefix?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061173592
- Why DBFS?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061301178
- Why ignore events triggered by `gitea-actions` bot?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1063254103
- Why there's no permission control for actions?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1090229868
### What it looks like
<details>
#### Manage runners
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205870657-c72f590e-2e08-4cd4-be7f-2e0abb299bbf.png">
#### List runs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872794-50fde990-2b45-48c1-a178-908e4ec5b627.png">
#### View logs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872501-9b7b9000-9542-4991-8f55-18ccdada77c3.png">
</details>
### How to try it
<details>
#### 1. Start Gitea
Clone this branch and [install from
source](https://docs.gitea.io/en-us/install-from-source).
Add additional configurations in `app.ini` to enable Actions:
```ini
[actions]
ENABLED = true
```
Start it.
If all is well, you'll see the management page of runners:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205877365-8e30a780-9b10-4154-b3e8-ee6c3cb35a59.png">
#### 2. Start runner
Clone the [act_runner](https://gitea.com/gitea/act_runner), and follow
the
[README](https://gitea.com/gitea/act_runner/src/branch/main/README.md)
to start it.
If all is well, you'll see a new runner has been added:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205878000-216f5937-e696-470d-b66c-8473987d91c3.png">
#### 3. Enable actions for a repo
Create a new repo or open an existing one, check the `Actions` checkbox
in settings and submit.
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879705-53e09208-73c0-4b3e-a123-2dcf9aba4b9c.png">
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879383-23f3d08f-1a85-41dd-a8b3-54e2ee6453e8.png">
If all is well, you'll see a new tab "Actions":
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205881648-a8072d8c-5803-4d76-b8a8-9b2fb49516c1.png">
#### 4. Upload workflow files
Upload some workflow files to `.gitea/workflows/xxx.yaml`, you can
follow the [quickstart](https://docs.github.com/en/actions/quickstart)
of GitHub Actions. Yes, Gitea Actions is compatible with GitHub Actions
in most cases, you can use the same demo:
```yaml
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
```
If all is well, you'll see a new run in `Actions` tab:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884473-79a874bc-171b-4aaf-acd5-0241a45c3b53.png">
#### 5. Check the logs of jobs
Click a run and you'll see the logs:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884800-994b0374-67f7-48ff-be9a-4c53f3141547.png">
#### 6. Go on
You can try more examples in [the
documents](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
of GitHub Actions, then you might find a lot of bugs.
Come on, PRs are welcome.
</details>
See also: [Feature Preview: Gitea
Actions](https://blog.gitea.io/2022/12/feature-preview-gitea-actions/)
---------
Co-authored-by: a1012112796 <1012112796@qq.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2023-01-31 07:15:19 +05:30
& actions_model . ActionTaskStep { RepoID : repoID } ,
& actions_model . ActionTask { RepoID : repoID } ,
& actions_model . ActionRunJob { RepoID : repoID } ,
& actions_model . ActionRun { RepoID : repoID } ,
& actions_model . ActionRunner { RepoID : repoID } ,
2023-05-19 19:07:57 +05:30
& actions_model . ActionArtifact { RepoID : repoID } ,
2015-12-01 07:15:55 +05:30
) ; err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "deleteBeans: %w" , err )
2014-05-14 22:34:57 +05:30
}
2021-03-20 00:31:24 +05:30
// Delete Labels and related objects
2022-06-13 15:07:59 +05:30
if err := issues_model . DeleteLabelsByRepoID ( ctx , repoID ) ; err != nil {
2021-03-20 00:31:24 +05:30
return err
}
2022-05-08 19:16:34 +05:30
// Delete Pulls and related objects
2022-06-13 15:07:59 +05:30
if err := issues_model . DeletePullsByBaseRepoID ( ctx , repoID ) ; err != nil {
2022-05-08 19:16:34 +05:30
return err
}
2020-05-29 18:54:15 +05:30
// Delete Issues and related objects
var attachmentPaths [ ] string
2022-06-13 15:07:59 +05:30
if attachmentPaths , err = issues_model . DeleteIssuesByRepoID ( ctx , repoID ) ; err != nil {
2018-11-30 18:29:12 +05:30
return err
2014-05-14 18:53:33 +05:30
}
2014-10-19 11:05:24 +05:30
2021-06-14 07:52:55 +05:30
// Delete issue index
2022-10-16 16:14:16 +05:30
if err := db . DeleteResourceIndex ( ctx , "issue_index" , repoID ) ; err != nil {
2021-06-14 07:52:55 +05:30
return err
}
2014-10-14 00:53:30 +05:30
if repo . IsFork {
2022-05-20 19:38:52 +05:30
if _ , err := db . Exec ( ctx , "UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?" , repo . ForkID ) ; err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "decrease fork count: %w" , err )
2014-10-19 11:05:24 +05:30
}
2014-10-14 00:53:30 +05:30
}
2014-04-13 06:05:35 +05:30
2022-05-20 19:38:52 +05:30
if _ , err := db . Exec ( ctx , "UPDATE `user` SET num_repos=num_repos-1 WHERE id=?" , uid ) ; err != nil {
2014-04-13 06:05:35 +05:30
return err
}
2014-10-09 03:59:18 +05:30
2020-01-31 12:27:19 +05:30
if len ( repo . Topics ) > 0 {
2021-12-12 21:18:20 +05:30
if err := repo_model . RemoveTopicsFromRepo ( ctx , repo . ID ) ; err != nil {
2020-01-31 12:27:19 +05:30
return err
}
}
2022-12-03 08:18:26 +05:30
if err := project_model . DeleteProjectByRepoID ( ctx , repoID ) ; err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "unable to delete projects for repo[%d]: %w" , repoID , err )
2020-08-17 08:37:38 +05:30
}
2016-12-26 06:46:37 +05:30
// Remove LFS objects
2022-06-12 21:21:54 +05:30
var lfsObjects [ ] * git_model . LFSMetaObject
2016-12-26 06:46:37 +05:30
if err = sess . Where ( "repository_id=?" , repoID ) . Find ( & lfsObjects ) ; err != nil {
return err
}
2022-01-20 23:16:10 +05:30
lfsPaths := make ( [ ] string , 0 , len ( lfsObjects ) )
2016-12-26 06:46:37 +05:30
for _ , v := range lfsObjects {
2022-06-12 21:21:54 +05:30
count , err := db . CountByBean ( ctx , & git_model . LFSMetaObject { Pointer : lfs . Pointer { Oid : v . Oid } } )
2016-12-26 06:46:37 +05:30
if err != nil {
return err
}
if count > 1 {
continue
}
2021-09-08 20:49:30 +05:30
lfsPaths = append ( lfsPaths , v . RelativePath ( ) )
2016-12-26 06:46:37 +05:30
}
2022-06-12 21:21:54 +05:30
if _ , err := db . DeleteByBean ( ctx , & git_model . LFSMetaObject { RepositoryID : repoID } ) ; err != nil {
2016-12-26 06:46:37 +05:30
return err
}
2021-06-24 02:42:38 +05:30
// Remove archives
2021-12-06 12:49:28 +05:30
var archives [ ] * repo_model . RepoArchiver
2021-06-24 02:42:38 +05:30
if err = sess . Where ( "repo_id=?" , repoID ) . Find ( & archives ) ; err != nil {
return err
}
2022-01-20 23:16:10 +05:30
archivePaths := make ( [ ] string , 0 , len ( archives ) )
2021-06-24 02:42:38 +05:30
for _ , v := range archives {
2022-08-29 15:15:20 +05:30
archivePaths = append ( archivePaths , v . RelativePath ( ) )
2021-06-24 02:42:38 +05:30
}
2022-05-20 19:38:52 +05:30
if _ , err := db . DeleteByBean ( ctx , & repo_model . RepoArchiver { RepoID : repoID } ) ; err != nil {
2021-06-24 02:42:38 +05:30
return err
}
2015-09-01 21:13:53 +05:30
if repo . NumForks > 0 {
2017-01-27 21:41:41 +05:30
if _ , err = sess . Exec ( "UPDATE `repository` SET fork_id=0,is_fork=? WHERE fork_id=?" , false , repo . ID ) ; err != nil {
2019-04-02 13:18:31 +05:30
log . Error ( "reset 'fork_id' and 'is_fork': %v" , err )
2016-07-09 11:12:05 +05:30
}
2015-09-01 21:13:53 +05:30
}
2021-09-08 20:49:30 +05:30
// Get all attachments with both issue_id and release_id are zero
2021-11-19 19:09:57 +05:30
var newAttachments [ ] * repo_model . Attachment
2021-09-08 20:49:30 +05:30
if err := sess . Where ( builder . Eq {
"repo_id" : repo . ID ,
"issue_id" : 0 ,
"release_id" : 0 ,
} ) . Find ( & newAttachments ) ; err != nil {
return err
}
2022-01-20 23:16:10 +05:30
newAttachmentPaths := make ( [ ] string , 0 , len ( newAttachments ) )
2021-09-08 20:49:30 +05:30
for _ , attach := range newAttachments {
newAttachmentPaths = append ( newAttachmentPaths , attach . RelativePath ( ) )
}
2021-11-19 19:09:57 +05:30
if _ , err := sess . Where ( "repo_id=?" , repo . ID ) . Delete ( new ( repo_model . Attachment ) ) ; err != nil {
2021-09-08 20:49:30 +05:30
return err
}
2021-11-21 21:11:00 +05:30
if err = committer . Commit ( ) ; err != nil {
2021-01-19 01:30:50 +05:30
return err
2017-01-27 21:41:41 +05:30
}
2021-11-21 21:11:00 +05:30
committer . Close ( )
2019-12-12 11:01:05 +05:30
2021-12-10 13:44:24 +05:30
if needRewriteKeysFile {
if err := asymkey_model . RewriteAllPublicKeys ( ) ; err != nil {
log . Error ( "RewriteAllPublicKeys failed: %v" , err )
}
}
2019-12-12 11:01:05 +05:30
// We should always delete the files after the database transaction succeed. If
2021-07-08 17:08:13 +05:30
// we delete the file but the database rollback, the repository will be broken.
2019-12-12 11:01:05 +05:30
2021-09-08 20:49:30 +05:30
// Remove repository files.
repoPath := repo . RepoPath ( )
2022-10-17 04:59:26 +05:30
system_model . RemoveAllWithNotice ( db . DefaultContext , "Delete repository files" , repoPath )
2021-09-08 20:49:30 +05:30
// Remove wiki files
if repo . HasWiki ( ) {
2022-10-17 04:59:26 +05:30
system_model . RemoveAllWithNotice ( db . DefaultContext , "Delete repository wiki" , repo . WikiPath ( ) )
2021-09-08 20:49:30 +05:30
}
// Remove archives
2022-03-03 17:21:13 +05:30
for _ , archive := range archivePaths {
2022-10-17 04:59:26 +05:30
system_model . RemoveStorageWithNotice ( db . DefaultContext , storage . RepoArchives , "Delete repo archive file" , archive )
2021-09-08 20:49:30 +05:30
}
// Remove lfs objects
2022-03-03 17:21:13 +05:30
for _ , lfsObj := range lfsPaths {
2022-10-17 04:59:26 +05:30
system_model . RemoveStorageWithNotice ( db . DefaultContext , storage . LFS , "Delete orphaned LFS file" , lfsObj )
2021-09-08 20:49:30 +05:30
}
2019-12-12 11:01:05 +05:30
// Remove issue attachment files.
2022-03-03 17:21:13 +05:30
for _ , attachment := range attachmentPaths {
2022-10-17 04:59:26 +05:30
system_model . RemoveStorageWithNotice ( db . DefaultContext , storage . Attachments , "Delete issue attachment" , attachment )
2019-12-12 11:01:05 +05:30
}
// Remove release attachment files.
2022-03-03 17:21:13 +05:30
for _ , releaseAttachment := range releaseAttachments {
2022-10-17 04:59:26 +05:30
system_model . RemoveStorageWithNotice ( db . DefaultContext , storage . Attachments , "Delete release attachment" , releaseAttachment )
2019-12-12 11:01:05 +05:30
}
2021-09-08 20:49:30 +05:30
// Remove attachment with no issue_id and release_id.
2022-03-03 17:21:13 +05:30
for _ , newAttachment := range newAttachmentPaths {
2022-10-17 04:59:26 +05:30
system_model . RemoveStorageWithNotice ( db . DefaultContext , storage . Attachments , "Delete issue attachment" , newAttachment )
2021-09-08 20:49:30 +05:30
}
2019-05-30 07:52:26 +05:30
if len ( repo . Avatar ) > 0 {
2020-10-14 18:37:51 +05:30
if err := storage . RepoAvatars . Delete ( repo . CustomAvatarRelativePath ( ) ) ; err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "Failed to remove %s: %w" , repo . Avatar , err )
2019-05-30 07:52:26 +05:30
}
}
Implement actions (#21937)
Close #13539.
Co-authored by: @lunny @appleboy @fuxiaohei and others.
Related projects:
- https://gitea.com/gitea/actions-proto-def
- https://gitea.com/gitea/actions-proto-go
- https://gitea.com/gitea/act
- https://gitea.com/gitea/act_runner
### Summary
The target of this PR is to bring a basic implementation of "Actions",
an internal CI/CD system of Gitea. That means even though it has been
merged, the state of the feature is **EXPERIMENTAL**, and please note
that:
- It is disabled by default;
- It shouldn't be used in a production environment currently;
- It shouldn't be used in a public Gitea instance currently;
- Breaking changes may be made before it's stable.
**Please comment on #13539 if you have any different product design
ideas**, all decisions reached there will be adopted here. But in this
PR, we don't talk about **naming, feature-creep or alternatives**.
### ⚠️ Breaking
`gitea-actions` will become a reserved user name. If a user with the
name already exists in the database, it is recommended to rename it.
### Some important reviews
- What is `DEFAULT_ACTIONS_URL` in `app.ini` for?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1055954954
- Why the api for runners is not under the normal `/api/v1` prefix?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061173592
- Why DBFS?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1061301178
- Why ignore events triggered by `gitea-actions` bot?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1063254103
- Why there's no permission control for actions?
- https://github.com/go-gitea/gitea/pull/21937#discussion_r1090229868
### What it looks like
<details>
#### Manage runners
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205870657-c72f590e-2e08-4cd4-be7f-2e0abb299bbf.png">
#### List runs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872794-50fde990-2b45-48c1-a178-908e4ec5b627.png">
#### View logs
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205872501-9b7b9000-9542-4991-8f55-18ccdada77c3.png">
</details>
### How to try it
<details>
#### 1. Start Gitea
Clone this branch and [install from
source](https://docs.gitea.io/en-us/install-from-source).
Add additional configurations in `app.ini` to enable Actions:
```ini
[actions]
ENABLED = true
```
Start it.
If all is well, you'll see the management page of runners:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205877365-8e30a780-9b10-4154-b3e8-ee6c3cb35a59.png">
#### 2. Start runner
Clone the [act_runner](https://gitea.com/gitea/act_runner), and follow
the
[README](https://gitea.com/gitea/act_runner/src/branch/main/README.md)
to start it.
If all is well, you'll see a new runner has been added:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205878000-216f5937-e696-470d-b66c-8473987d91c3.png">
#### 3. Enable actions for a repo
Create a new repo or open an existing one, check the `Actions` checkbox
in settings and submit.
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879705-53e09208-73c0-4b3e-a123-2dcf9aba4b9c.png">
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205879383-23f3d08f-1a85-41dd-a8b3-54e2ee6453e8.png">
If all is well, you'll see a new tab "Actions":
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205881648-a8072d8c-5803-4d76-b8a8-9b2fb49516c1.png">
#### 4. Upload workflow files
Upload some workflow files to `.gitea/workflows/xxx.yaml`, you can
follow the [quickstart](https://docs.github.com/en/actions/quickstart)
of GitHub Actions. Yes, Gitea Actions is compatible with GitHub Actions
in most cases, you can use the same demo:
```yaml
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
```
If all is well, you'll see a new run in `Actions` tab:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884473-79a874bc-171b-4aaf-acd5-0241a45c3b53.png">
#### 5. Check the logs of jobs
Click a run and you'll see the logs:
<img width="1792" alt="image"
src="https://user-images.githubusercontent.com/9418365/205884800-994b0374-67f7-48ff-be9a-4c53f3141547.png">
#### 6. Go on
You can try more examples in [the
documents](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
of GitHub Actions, then you might find a lot of bugs.
Come on, PRs are welcome.
</details>
See also: [Feature Preview: Gitea
Actions](https://blog.gitea.io/2022/12/feature-preview-gitea-actions/)
---------
Co-authored-by: a1012112796 <1012112796@qq.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2023-01-31 07:15:19 +05:30
// Finally, delete action logs after the actions have already been deleted to avoid new log files
for _ , task := range tasks {
err := actions_module . RemoveLogs ( ctx , task . LogInStorage , task . LogFilename )
if err != nil {
log . Error ( "remove log file %q: %v" , task . LogFilename , err )
// go on
}
}
2023-05-19 19:07:57 +05:30
// delete actions artifacts in ObjectStorage after the repo have already been deleted
for _ , art := range artifacts {
if err := storage . ActionsArtifacts . Delete ( art . StoragePath ) ; err != nil {
log . Error ( "remove artifact file %q: %v" , art . StoragePath , err )
// go on
}
}
2015-09-01 21:13:53 +05:30
return nil
2014-03-21 01:34:56 +05:30
}
2015-09-01 21:13:53 +05:30
type repoChecker struct {
2022-01-18 00:01:58 +05:30
querySQL func ( ctx context . Context ) ( [ ] map [ string ] [ ] byte , error )
correctSQL func ( ctx context . Context , id int64 ) error
desc string
2015-09-01 21:13:53 +05:30
}
2015-08-18 01:33:11 +05:30
2019-12-15 15:21:28 +05:30
func repoStatsCheck ( ctx context . Context , checker * repoChecker ) {
2022-01-18 00:01:58 +05:30
results , err := checker . querySQL ( ctx )
2015-08-18 01:33:11 +05:30
if err != nil {
2019-04-02 13:18:31 +05:30
log . Error ( "Select %s: %v" , checker . desc , err )
2015-08-18 01:33:11 +05:30
return
}
2015-09-01 21:13:53 +05:30
for _ , result := range results {
2020-12-25 15:29:32 +05:30
id , _ := strconv . ParseInt ( string ( result [ "id" ] ) , 10 , 64 )
2019-12-15 15:21:28 +05:30
select {
case <- ctx . Done ( ) :
2022-01-18 00:01:58 +05:30
log . Warn ( "CheckRepoStats: Cancelled before checking %s for with id=%d" , checker . desc , id )
2019-12-15 15:21:28 +05:30
return
default :
}
2015-09-01 21:13:53 +05:30
log . Trace ( "Updating %s: %d" , checker . desc , id )
2022-01-18 00:01:58 +05:30
err = checker . correctSQL ( ctx , id )
2015-08-18 01:33:11 +05:30
if err != nil {
2019-04-02 13:18:31 +05:30
log . Error ( "Update %s[%d]: %v" , checker . desc , id , err )
2015-08-18 01:33:11 +05:30
}
}
2015-09-01 21:13:53 +05:30
}
2015-08-18 01:33:11 +05:30
2022-01-18 00:01:58 +05:30
func StatsCorrectSQL ( ctx context . Context , sql string , id int64 ) error {
_ , err := db . GetEngine ( ctx ) . Exec ( sql , id , id )
return err
}
func repoStatsCorrectNumWatches ( ctx context . Context , id int64 ) error {
return StatsCorrectSQL ( ctx , "UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=? AND mode<>2) WHERE id=?" , id )
}
func repoStatsCorrectNumStars ( ctx context . Context , id int64 ) error {
return StatsCorrectSQL ( ctx , "UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?" , id )
}
func labelStatsCorrectNumIssues ( ctx context . Context , id int64 ) error {
return StatsCorrectSQL ( ctx , "UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=?) WHERE id=?" , id )
}
func labelStatsCorrectNumIssuesRepo ( ctx context . Context , id int64 ) error {
_ , err := db . GetEngine ( ctx ) . Exec ( "UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=id) WHERE repo_id=?" , id )
return err
}
func labelStatsCorrectNumClosedIssues ( ctx context . Context , id int64 ) error {
_ , err := db . GetEngine ( ctx ) . Exec ( "UPDATE `label` SET num_closed_issues=(SELECT COUNT(*) FROM `issue_label`,`issue` WHERE `issue_label`.label_id=`label`.id AND `issue_label`.issue_id=`issue`.id AND `issue`.is_closed=?) WHERE `label`.id=?" , true , id )
return err
}
func labelStatsCorrectNumClosedIssuesRepo ( ctx context . Context , id int64 ) error {
_ , err := db . GetEngine ( ctx ) . Exec ( "UPDATE `label` SET num_closed_issues=(SELECT COUNT(*) FROM `issue_label`,`issue` WHERE `issue_label`.label_id=`label`.id AND `issue_label`.issue_id=`issue`.id AND `issue`.is_closed=?) WHERE `label`.repo_id=?" , true , id )
return err
}
var milestoneStatsQueryNumIssues = "SELECT `milestone`.id FROM `milestone` WHERE `milestone`.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE `issue`.milestone_id=`milestone`.id AND `issue`.is_closed=?) OR `milestone`.num_issues!=(SELECT COUNT(*) FROM `issue` WHERE `issue`.milestone_id=`milestone`.id)"
func milestoneStatsCorrectNumIssuesRepo ( ctx context . Context , id int64 ) error {
e := db . GetEngine ( ctx )
results , err := e . Query ( milestoneStatsQueryNumIssues + " AND `milestone`.repo_id = ?" , true , id )
if err != nil {
return err
}
for _ , result := range results {
id , _ := strconv . ParseInt ( string ( result [ "id" ] ) , 10 , 64 )
2022-04-08 14:41:15 +05:30
err = issues_model . UpdateMilestoneCounters ( ctx , id )
2022-01-18 00:01:58 +05:30
if err != nil {
return err
}
}
return nil
}
func userStatsCorrectNumRepos ( ctx context . Context , id int64 ) error {
return StatsCorrectSQL ( ctx , "UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?" , id )
}
func repoStatsCorrectIssueNumComments ( ctx context . Context , id int64 ) error {
return StatsCorrectSQL ( ctx , "UPDATE `issue` SET num_comments=(SELECT COUNT(*) FROM `comment` WHERE issue_id=? AND type=0) WHERE id=?" , id )
}
func repoStatsCorrectNumIssues ( ctx context . Context , id int64 ) error {
2022-10-25 18:17:46 +05:30
return repo_model . UpdateRepoIssueNumbers ( ctx , id , false , false )
2022-01-18 00:01:58 +05:30
}
func repoStatsCorrectNumPulls ( ctx context . Context , id int64 ) error {
2022-10-25 18:17:46 +05:30
return repo_model . UpdateRepoIssueNumbers ( ctx , id , true , false )
2022-01-18 00:01:58 +05:30
}
func repoStatsCorrectNumClosedIssues ( ctx context . Context , id int64 ) error {
2022-10-25 18:17:46 +05:30
return repo_model . UpdateRepoIssueNumbers ( ctx , id , false , true )
2022-01-18 00:01:58 +05:30
}
func repoStatsCorrectNumClosedPulls ( ctx context . Context , id int64 ) error {
2022-10-25 18:17:46 +05:30
return repo_model . UpdateRepoIssueNumbers ( ctx , id , true , true )
2022-01-18 00:01:58 +05:30
}
2023-07-05 00:06:08 +05:30
func statsQuery ( args ... any ) func ( context . Context ) ( [ ] map [ string ] [ ] byte , error ) {
2022-01-18 00:01:58 +05:30
return func ( ctx context . Context ) ( [ ] map [ string ] [ ] byte , error ) {
return db . GetEngine ( ctx ) . Query ( args ... )
}
}
2016-11-28 22:57:55 +05:30
// CheckRepoStats checks the repository stats
2020-05-17 05:01:38 +05:30
func CheckRepoStats ( ctx context . Context ) error {
2015-09-01 21:13:53 +05:30
log . Trace ( "Doing: CheckRepoStats" )
2015-08-29 22:43:24 +05:30
2015-09-01 21:13:53 +05:30
checkers := [ ] * repoChecker {
// Repository.NumWatches
{
2022-01-18 00:01:58 +05:30
statsQuery ( "SELECT repo.id FROM `repository` repo WHERE repo.num_watches!=(SELECT COUNT(*) FROM `watch` WHERE repo_id=repo.id AND mode<>2)" ) ,
repoStatsCorrectNumWatches ,
2015-09-01 21:13:53 +05:30
"repository count 'num_watches'" ,
} ,
// Repository.NumStars
{
2022-01-18 00:01:58 +05:30
statsQuery ( "SELECT repo.id FROM `repository` repo WHERE repo.num_stars!=(SELECT COUNT(*) FROM `star` WHERE repo_id=repo.id)" ) ,
repoStatsCorrectNumStars ,
2015-09-01 21:13:53 +05:30
"repository count 'num_stars'" ,
} ,
2022-10-11 12:11:39 +05:30
// Repository.NumIssues
{
2022-12-06 13:23:09 +05:30
statsQuery ( "SELECT repo.id FROM `repository` repo WHERE repo.num_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_pull=?)" , false ) ,
2022-10-11 12:11:39 +05:30
repoStatsCorrectNumIssues ,
"repository count 'num_issues'" ,
} ,
2022-01-18 00:01:58 +05:30
// Repository.NumClosedIssues
{
statsQuery ( "SELECT repo.id FROM `repository` repo WHERE repo.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)" , true , false ) ,
repoStatsCorrectNumClosedIssues ,
"repository count 'num_closed_issues'" ,
} ,
2022-10-11 12:11:39 +05:30
// Repository.NumPulls
{
2022-12-06 13:23:09 +05:30
statsQuery ( "SELECT repo.id FROM `repository` repo WHERE repo.num_pulls!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_pull=?)" , true ) ,
2022-10-11 12:11:39 +05:30
repoStatsCorrectNumPulls ,
"repository count 'num_pulls'" ,
} ,
2022-01-18 00:01:58 +05:30
// Repository.NumClosedPulls
{
2022-10-11 12:11:39 +05:30
statsQuery ( "SELECT repo.id FROM `repository` repo WHERE repo.num_closed_pulls!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)" , true , true ) ,
2022-01-18 00:01:58 +05:30
repoStatsCorrectNumClosedPulls ,
"repository count 'num_closed_pulls'" ,
} ,
2015-09-01 21:13:53 +05:30
// Label.NumIssues
{
2022-01-18 00:01:58 +05:30
statsQuery ( "SELECT label.id FROM `label` WHERE label.num_issues!=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=label.id)" ) ,
labelStatsCorrectNumIssues ,
2015-09-01 21:13:53 +05:30
"label count 'num_issues'" ,
} ,
2022-01-18 00:01:58 +05:30
// Label.NumClosedIssues
{
statsQuery ( "SELECT `label`.id FROM `label` WHERE `label`.num_closed_issues!=(SELECT COUNT(*) FROM `issue_label`,`issue` WHERE `issue_label`.label_id=`label`.id AND `issue_label`.issue_id=`issue`.id AND `issue`.is_closed=?)" , true ) ,
labelStatsCorrectNumClosedIssues ,
"label count 'num_closed_issues'" ,
} ,
// Milestone.Num{,Closed}Issues
{
statsQuery ( milestoneStatsQueryNumIssues , true ) ,
2022-04-08 14:41:15 +05:30
issues_model . UpdateMilestoneCounters ,
2022-01-18 00:01:58 +05:30
"milestone count 'num_closed_issues' and 'num_issues'" ,
} ,
2015-09-01 21:13:53 +05:30
// User.NumRepos
{
2022-01-18 00:01:58 +05:30
statsQuery ( "SELECT `user`.id FROM `user` WHERE `user`.num_repos!=(SELECT COUNT(*) FROM `repository` WHERE owner_id=`user`.id)" ) ,
userStatsCorrectNumRepos ,
2015-09-01 21:13:53 +05:30
"user count 'num_repos'" ,
} ,
2015-10-30 06:10:57 +05:30
// Issue.NumComments
{
2022-01-18 00:01:58 +05:30
statsQuery ( "SELECT `issue`.id FROM `issue` WHERE `issue`.num_comments!=(SELECT COUNT(*) FROM `comment` WHERE issue_id=`issue`.id AND type=0)" ) ,
repoStatsCorrectIssueNumComments ,
2015-10-30 06:10:57 +05:30
"issue count 'num_comments'" ,
} ,
2015-09-01 21:13:53 +05:30
}
2020-05-17 05:01:38 +05:30
for _ , checker := range checkers {
2019-12-15 15:21:28 +05:30
select {
case <- ctx . Done ( ) :
2020-05-17 05:01:38 +05:30
log . Warn ( "CheckRepoStats: Cancelled before %s" , checker . desc )
2021-11-10 10:43:16 +05:30
return db . ErrCancelledf ( "before checking %s" , checker . desc )
2019-12-15 15:21:28 +05:30
default :
2020-05-17 05:01:38 +05:30
repoStatsCheck ( ctx , checker )
2019-12-15 15:21:28 +05:30
}
2015-09-01 21:13:53 +05:30
}
2016-05-28 06:53:39 +05:30
// FIXME: use checker when stop supporting old fork repo format.
2015-09-01 21:13:53 +05:30
// ***** START: Repository.NumForks *****
2022-01-18 00:01:58 +05:30
e := db . GetEngine ( ctx )
results , err := e . Query ( "SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)" )
2015-08-29 22:43:24 +05:30
if err != nil {
2019-04-02 13:18:31 +05:30
log . Error ( "Select repository count 'num_forks': %v" , err )
2015-09-01 21:13:53 +05:30
} else {
for _ , result := range results {
2020-12-25 15:29:32 +05:30
id , _ := strconv . ParseInt ( string ( result [ "id" ] ) , 10 , 64 )
2019-12-15 15:21:28 +05:30
select {
case <- ctx . Done ( ) :
2020-05-17 05:01:38 +05:30
log . Warn ( "CheckRepoStats: Cancelled" )
2022-01-18 00:01:58 +05:30
return db . ErrCancelledf ( "during repository count 'num_fork' for repo ID %d" , id )
2019-12-15 15:21:28 +05:30
default :
}
2015-09-01 21:13:53 +05:30
log . Trace ( "Updating repository count 'num_forks': %d" , id )
2022-12-03 08:18:26 +05:30
repo , err := repo_model . GetRepositoryByID ( ctx , id )
2015-09-01 21:13:53 +05:30
if err != nil {
2021-12-10 06:57:50 +05:30
log . Error ( "repo_model.GetRepositoryByID[%d]: %v" , id , err )
2015-09-01 21:13:53 +05:30
continue
}
2022-06-13 15:07:59 +05:30
_ , err = e . SQL ( "SELECT COUNT(*) FROM `repository` WHERE fork_id=?" , repo . ID ) . Get ( & repo . NumForks )
2015-09-01 21:13:53 +05:30
if err != nil {
2019-04-02 13:18:31 +05:30
log . Error ( "Select count of forks[%d]: %v" , repo . ID , err )
2015-09-01 21:13:53 +05:30
continue
}
2022-06-06 13:31:49 +05:30
if _ , err = e . ID ( repo . ID ) . Cols ( "num_forks" ) . Update ( repo ) ; err != nil {
2019-04-02 13:18:31 +05:30
log . Error ( "UpdateRepository[%d]: %v" , id , err )
2015-09-01 21:13:53 +05:30
continue
}
2015-08-29 22:43:24 +05:30
}
}
2015-09-01 21:13:53 +05:30
// ***** END: Repository.NumForks *****
2020-05-17 05:01:38 +05:30
return nil
2015-03-21 18:25:00 +05:30
}
2022-01-18 00:01:58 +05:30
func UpdateRepoStats ( ctx context . Context , id int64 ) error {
var err error
for _ , f := range [ ] func ( ctx context . Context , id int64 ) error {
repoStatsCorrectNumWatches ,
repoStatsCorrectNumStars ,
repoStatsCorrectNumIssues ,
repoStatsCorrectNumPulls ,
repoStatsCorrectNumClosedIssues ,
repoStatsCorrectNumClosedPulls ,
labelStatsCorrectNumIssuesRepo ,
labelStatsCorrectNumClosedIssuesRepo ,
milestoneStatsCorrectNumIssuesRepo ,
} {
err = f ( ctx , id )
if err != nil {
return err
}
}
return nil
}
2021-11-24 15:19:20 +05:30
func updateUserStarNumbers ( users [ ] user_model . User ) error {
2022-11-13 01:48:50 +05:30
ctx , committer , err := db . TxContext ( db . DefaultContext )
2021-11-21 21:11:00 +05:30
if err != nil {
return err
}
defer committer . Close ( )
for _ , user := range users {
if _ , err = db . Exec ( ctx , "UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?" , user . ID , user . ID ) ; err != nil {
return err
}
}
return committer . Commit ( )
}
2020-07-08 00:46:34 +05:30
// DoctorUserStarNum recalculate Stars number for all user
func DoctorUserStarNum ( ) ( err error ) {
const batchSize = 100
for start := 0 ; ; start += batchSize {
2021-11-24 15:19:20 +05:30
users := make ( [ ] user_model . User , 0 , batchSize )
2021-11-21 21:11:00 +05:30
if err = db . GetEngine ( db . DefaultContext ) . Limit ( batchSize , start ) . Where ( "type = ?" , 0 ) . Cols ( "id" ) . Find ( & users ) ; err != nil {
2023-07-09 17:28:06 +05:30
return err
2020-07-08 00:46:34 +05:30
}
if len ( users ) == 0 {
break
}
2021-11-21 21:11:00 +05:30
if err = updateUserStarNumbers ( users ) ; err != nil {
2023-07-09 17:28:06 +05:30
return err
2020-07-08 00:46:34 +05:30
}
}
log . Debug ( "recalculate Stars number for all user finished" )
2022-06-20 15:32:49 +05:30
return err
2020-07-08 00:46:34 +05:30
}
2020-10-14 18:37:51 +05:30
2021-12-10 13:44:24 +05:30
// DeleteDeployKey delete deploy keys
func DeleteDeployKey ( ctx context . Context , doer * user_model . User , id int64 ) error {
key , err := asymkey_model . GetDeployKeyByID ( ctx , id )
if err != nil {
if asymkey_model . IsErrDeployKeyNotExist ( err ) {
return nil
}
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "GetDeployKeyByID: %w" , err )
2021-12-10 13:44:24 +05:30
}
// Check if user has access to delete this key.
if ! doer . IsAdmin {
2022-12-03 08:18:26 +05:30
repo , err := repo_model . GetRepositoryByID ( ctx , key . RepoID )
2021-12-10 13:44:24 +05:30
if err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "GetRepositoryByID: %w" , err )
2021-12-10 13:44:24 +05:30
}
2022-05-20 19:38:52 +05:30
has , err := access_model . IsUserRepoAdmin ( ctx , repo , doer )
2021-12-10 13:44:24 +05:30
if err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "GetUserRepoPermission: %w" , err )
2021-12-10 13:44:24 +05:30
} else if ! has {
return asymkey_model . ErrKeyAccessDenied {
UserID : doer . ID ,
KeyID : key . ID ,
Note : "deploy" ,
}
}
}
2022-06-06 13:31:49 +05:30
if _ , err := db . DeleteByBean ( ctx , & asymkey_model . DeployKey {
ID : key . ID ,
} ) ; err != nil {
2022-10-25 00:59:17 +05:30
return fmt . Errorf ( "delete deploy key [%d]: %w" , key . ID , err )
2021-12-10 13:44:24 +05:30
}
// Check if this is the last reference to same key content.
2022-06-06 13:31:49 +05:30
has , err := asymkey_model . IsDeployKeyExistByKeyID ( ctx , key . KeyID )
2021-12-10 13:44:24 +05:30
if err != nil {
return err
} else if ! has {
if err = asymkey_model . DeletePublicKeys ( ctx , key . KeyID ) ; err != nil {
return err
}
}
return nil
}