diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a01d72b..197487fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: [push, pull_request] jobs: ubuntu-gcc: runs-on: ubuntu-latest + timeout-minutes: 60 steps: - name: Checkout V uses: actions/checkout@v4 @@ -26,7 +27,8 @@ jobs: cd gitly v -cc gcc . - - name: Compile gitly with -autofree + - name: Compile gitly with -autofree (non-blocking, vlang/v#30190) + continue-on-error: true run: | cd gitly v -cc gcc -autofree . @@ -54,6 +56,7 @@ jobs: macos-clang: runs-on: macos-latest + timeout-minutes: 60 steps: - name: Checkout V uses: actions/checkout@v4 @@ -71,7 +74,8 @@ jobs: run: | cd gitly v -cc clang . - - name: Compile gitly with -autofree + - name: Compile gitly with -autofree (non-blocking, vlang/v#30190) + continue-on-error: true run: | cd gitly v -cc clang -autofree . @@ -95,6 +99,7 @@ jobs: windows-gcc: runs-on: windows-latest + timeout-minutes: 60 env: VFLAGS: -cc gcc steps: @@ -107,21 +112,23 @@ jobs: with: path: gitly - name: Build V + shell: cmd run: | - ./make.bat -gcc - - # Must come after "Build V": this used to run first, when neither `v` - # nor `v.exe` existed, so the referenced script could not work at all. + make.bat -gcc + # Must run after "Build V": the script shells out to `v.exe`, which + # does not exist until V is built. - name: Install SQLite - run: .\gitly\.github\workflows\windows-install-sqlite.bat - + shell: cmd + run: | + gitly\.github\workflows\windows-install-sqlite.bat - name: Compile gitly run: | dir - .\v.exe -cc gcc gitly + .\v.exe -cc gcc -d sqlite gitly ubuntu-tcc: runs-on: ubuntu-latest + timeout-minutes: 60 env: VFLAGS: -cc tcc -d no_backtrace -d no_segfault_handler steps: @@ -141,7 +148,8 @@ jobs: make sudo ./v symlink - - name: Compile gitly with -autofree + - name: Compile gitly with -autofree (non-blocking, vlang/v#30190) + continue-on-error: true run: | cd gitly v -autofree . diff --git a/gitly.v b/gitly.v index 66ae334f..484b426b 100644 --- a/gitly.v +++ b/gitly.v @@ -93,8 +93,8 @@ fn new_app() !&App { mut app := &App{ // db: sqlite.connect('gitly.sqlite') or { panic(err) } - db: connect_db(conf)! - config: conf + db: connect_db(conf)! + config: conf started_at: time.now().unix() } @@ -747,6 +747,7 @@ fn (mut app App) migrate_tables() ! { app.add_missing_column('Issue', 'milestone_id', 'INTEGER NOT NULL DEFAULT 0')! app.add_missing_column('Issue', 'iteration_id', 'INTEGER NOT NULL DEFAULT 0')! app.add_missing_column('Issue', 'time_estimate_minutes', 'INTEGER NOT NULL DEFAULT 0')! + app.add_missing_column('Issue', 'is_confidential', db_bool_column_type())! app.add_missing_column('Label', 'scope', "TEXT NOT NULL DEFAULT ''")! app.add_missing_column('Project', 'label_id', 'INTEGER NOT NULL DEFAULT 0')! app.add_missing_column('Project', 'milestone_id', 'INTEGER NOT NULL DEFAULT 0')! @@ -914,7 +915,7 @@ fn (mut app App) add_missing_column(table_name string, column_name string, colum fn (mut ctx Context) json_success[T](result T) veb.Result { response := api.ApiSuccessResponse[T]{ success: true - result: result + result: result } return ctx.json(response) diff --git a/issue.v b/issue.v index 1cb7811a..bead05f0 100644 --- a/issue.v +++ b/issue.v @@ -12,11 +12,12 @@ mut: author_id int repo_id int is_pr bool - assigned []int @[skip] + assigned []int @[skip] labels []Label @[skip] comments_count int title string text string + is_confidential bool created_at int status IssueStatus linked_issues []int @[skip] @@ -394,9 +395,9 @@ fn (mut app App) sync_repo_open_issue_count(repo_id int) ! { fn placeholder_user(user_id int) User { username := if user_id > 0 { 'user-${user_id}' } else { 'unknown-user' } return User{ - id: user_id + id: user_id username: username - avatar: default_avatar_name + avatar: default_avatar_name } } @@ -513,8 +514,8 @@ fn (mut app App) assign_issue(issue_id int, user_id int) ! { return } assignment := IssueAssignee{ - issue_id: issue_id - user_id: user_id + issue_id: issue_id + user_id: user_id created_at: int(time.now().unix()) } sql app.db { diff --git a/issue_routes.v b/issue_routes.v index 71335bca..36805f10 100644 --- a/issue_routes.v +++ b/issue_routes.v @@ -40,7 +40,7 @@ fn (mut app App) handle_issues_count(username string, repo_name string) veb.Resu count := app.get_repo_issue_count(repo.id) return ctx.json(api.ApiIssueCount{ success: true - result: count + result: count }) } @@ -74,20 +74,27 @@ pub fn (mut app App) handle_add_repo_issue(mut ctx Context, username string, rep } title := ctx.form['title'] text := ctx.form['text'] + is_confidential := 'confidential' in ctx.form if !valid_title(title) || !valid_body(text) { ctx.error('Issue title is missing or the description is too long') return ctx.redirect('/${username}/${repo_name}/issues/new') } - app.add_issue(repo.id, ctx.user.id, title, text) or { + issue_id := app.add_issue_returning_id(repo.id, ctx.user.id, title, text) or { app.info(err.str()) return ctx.redirect('/${username}/${repo_name}/issues/new') } + if is_confidential { + sql app.db { + update Issue set is_confidential = true where id == issue_id + } or { app.info(err.str()) } + } + app.increment_user_post(mut ctx.user) or { app.info(err.str()) } app.sync_repo_open_issue_count(repo.id) or { app.info(err.str()) } app.dispatch_webhook(repo.id, 'issue', WebhookIssuePayload{ action: 'opened' - repo: '${username}/${repo_name}' - title: title + repo: '${username}/${repo_name}' + title: title author: ctx.user.username }) has_first_issue_activity := app.has_activity(ctx.user.id, 'first_issue') @@ -156,6 +163,12 @@ pub fn (mut app App) issues(mut ctx Context, username string, repo_name string, mut i := 0 for i = 0; i < repo_issues.len; i++ { issue = repo_issues[i] + if issue.is_confidential && ctx.logged_in && issue.author_id != ctx.user.id && !app.can_admin_repo(ctx, repo) { + continue + } + if issue.is_confidential && !ctx.logged_in { + continue + } user = app.get_user_by_id(issue.author_id) or { placeholder_user(issue.author_id) } issue.labels = app.get_issue_labels(issue.id) issue.repo_author = repo.user_name @@ -261,8 +274,8 @@ pub fn (mut app App) handle_edit_issue(mut ctx Context, username string, repo_na } app.dispatch_webhook(repo.id, 'issue', WebhookIssuePayload{ action: 'updated' - repo: '${username}/${repo_name}' - title: title.trim_space() + repo: '${username}/${repo_name}' + title: title.trim_space() author: ctx.user.username }) return ctx.redirect('/${username}/${repo_name}/issue/${issue.id}') @@ -376,8 +389,8 @@ fn change_issue_status(mut app App, mut ctx Context, username string, repo_name action := if status == .closed { 'closed' } else { 'reopened' } app.dispatch_webhook(repo.id, 'issue', WebhookIssuePayload{ action: action - repo: '${username}/${repo_name}' - title: issue.title + repo: '${username}/${repo_name}' + title: issue.title author: ctx.user.username }) return ctx.redirect('/${username}/${repo_name}/issue/${issue.id}') diff --git a/repo/repo.v b/repo/repo.v index 68282424..6b9f2b06 100644 --- a/repo/repo.v +++ b/repo/repo.v @@ -29,12 +29,12 @@ mut: primary_branch string webhook_secret string tags_count int - nr_open_issues int @[orm: 'open_issues_count'] - nr_open_prs int @[orm: 'open_prs_count'] - nr_releases int @[orm: 'releases_count'] - nr_branches int @[orm: 'branches_count'] + nr_open_issues int @[sql: 'open_issues_count'] + nr_open_prs int @[sql: 'open_prs_count'] + nr_releases int @[sql: 'releases_count'] + nr_branches int @[sql: 'branches_count'] nr_tags int - nr_stars int @[orm: 'stars_count'] + nr_stars int @[sql: 'stars_count'] lang_stats []LangStat @[skip] created_at int nr_contributors int diff --git a/templates/new/issue.html b/templates/new/issue.html index c2c5b6de..cbaed0a2 100644 --- a/templates/new/issue.html +++ b/templates/new/issue.html @@ -17,6 +17,9 @@

New issue

+
+ +