Skip to content

Commit b9e4a44

Browse files
committed
Merge remote-tracking branch 'upstream/main'
* upstream/main: Replace some `gt-` classes with `tw-` (go-gitea#29570) Enable/disable owner and repo projects independently (go-gitea#28805) Add an trailing slash to dashboard links (go-gitea#29555) Extend issue template yaml engine (go-gitea#29274) [skip ci] Updated licenses and gitignores Fix workflow trigger event IssueChangeXXX bug (go-gitea#29559) Fix 500 when pushing release to an empty repo (go-gitea#29554) Update js and py dependencies, bump python (go-gitea#29561) Filter Repositories by type (go-gitea#29231)
2 parents b476683 + a2e9001 commit b9e4a44

File tree

93 files changed

+1380
-784
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+1380
-784
lines changed

.github/workflows/pull-compliance.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ jobs:
3232
runs-on: ubuntu-latest
3333
steps:
3434
- uses: actions/checkout@v4
35-
- uses: actions/setup-python@v4
35+
- uses: actions/setup-python@v5
3636
with:
37-
python-version: "3.11"
37+
python-version: "3.12"
3838
- run: pip install poetry
3939
- run: make deps-py
4040
- run: make lint-templates
@@ -45,9 +45,9 @@ jobs:
4545
runs-on: ubuntu-latest
4646
steps:
4747
- uses: actions/checkout@v4
48-
- uses: actions/setup-python@v4
48+
- uses: actions/setup-python@v5
4949
with:
50-
python-version: "3.11"
50+
python-version: "3.12"
5151
- run: pip install poetry
5252
- run: make deps-py
5353
- run: make lint-yaml

.stylelintrc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ rules:
6464
"@stylistic/media-query-list-comma-newline-before": null
6565
"@stylistic/media-query-list-comma-space-after": null
6666
"@stylistic/media-query-list-comma-space-before": null
67+
"@stylistic/named-grid-areas-alignment": null
6768
"@stylistic/no-empty-first-line": null
6869
"@stylistic/no-eol-whitespace": true
6970
"@stylistic/no-extra-semicolons": true

docs/content/usage/issue-pull-request-templates.en-us.md

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ body:
136136
attributes:
137137
value: |
138138
Thanks for taking the time to fill out this bug report!
139+
# some markdown that will only be visible once the issue has been created
140+
- type: markdown
141+
attributes:
142+
value: |
143+
This issue was created by an issue **template** :)
144+
visible: [content]
139145
- type: input
140146
id: contact
141147
attributes:
@@ -187,18 +193,25 @@ body:
187193
options:
188194
- label: I agree to follow this project's Code of Conduct
189195
required: true
196+
- label: I have also read the CONTRIBUTION.MD
197+
required: true
198+
visible: [form]
199+
- label: This is a TODO only visible after issue creation
200+
visible: [content]
190201
```
191202
192203
### Markdown
193204
194-
You can use a `markdown` element to display Markdown in your form that provides extra context to the user, but is not submitted.
205+
You can use a `markdown` element to display Markdown in your form that provides extra context to the user, but is not submitted by default.
195206

196207
Attributes:
197208

198209
| Key | Description | Required | Type | Default | Valid values |
199210
|-------|--------------------------------------------------------------|----------|--------|---------|--------------|
200211
| value | The text that is rendered. Markdown formatting is supported. | Required | String | - | - |
201212

213+
visible: Default is **[form]**
214+
202215
### Textarea
203216

204217
You can use a `textarea` element to add a multi-line text field to your form. Contributors can also attach files in `textarea` fields.
@@ -219,6 +232,8 @@ Validations:
219232
|----------|------------------------------------------------------|----------|---------|---------|--------------|
220233
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
221234

235+
visible: Default is **[form, content]**
236+
222237
### Input
223238

224239
You can use an `input` element to add a single-line text field to your form.
@@ -240,6 +255,8 @@ Validations:
240255
| is_number | Prevents form submission until element is filled with a number. | Optional | Boolean | false | - |
241256
| regex | Prevents form submission until element is filled with a value that match the regular expression. | Optional | String | - | a [regular expression](https://en.wikipedia.org/wiki/Regular_expression) |
242257

258+
visible: Default is **[form, content]**
259+
243260
### Dropdown
244261

245262
You can use a `dropdown` element to add a dropdown menu in your form.
@@ -259,24 +276,29 @@ Validations:
259276
|----------|------------------------------------------------------|----------|---------|---------|--------------|
260277
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
261278

279+
visible: Default is **[form, content]**
280+
262281
### Checkboxes
263282

264283
You can use the `checkboxes` element to add a set of checkboxes to your form.
265284

266285
Attributes:
267286

268287
| Key | Description | Required | Type | Default | Valid values |
269-
|-------------|-------------------------------------------------------------------------------------------------------|----------|--------|--------------|--------------|
288+
| ----------- | ----------------------------------------------------------------------------------------------------- | -------- | ------ | ------------ | ------------ |
270289
| label | A brief description of the expected user input, which is displayed in the form. | Required | String | - | - |
271290
| description | A description of the set of checkboxes, which is displayed in the form. Supports Markdown formatting. | Optional | String | Empty String | - |
272291
| options | An array of checkboxes that the user can select. For syntax, see below. | Required | Array | - | - |
273292

274293
For each value in the options array, you can set the following keys.
275294

276-
| Key | Description | Required | Type | Default | Options |
277-
|----------|------------------------------------------------------------------------------------------------------------------------------------------|----------|---------|---------|---------|
278-
| label | The identifier for the option, which is displayed in the form. Markdown is supported for bold or italic text formatting, and hyperlinks. | Required | String | - | - |
279-
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
295+
| Key | Description | Required | Type | Default | Options |
296+
|--------------|------------------------------------------------------------------------------------------------------------------------------------------|----------|--------------|---------|---------|
297+
| label | The identifier for the option, which is displayed in the form. Markdown is supported for bold or italic text formatting, and hyperlinks. | Required | String | - | - |
298+
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
299+
| visible | Whether a specific checkbox appears in the form only, in the created issue only, or both. Valid options are "form" and "content". | Optional | String array | false | - |
300+
301+
visible: Default is **[form, content]**
280302

281303
## Syntax for issue config
282304

@@ -292,15 +314,15 @@ contact_links:
292314

293315
### Possible Options
294316

295-
| Key | Description | Type | Default |
296-
|----------------------|-------------------------------------------------------------------------------------------------------|--------------------|----------------|
297-
| blank_issues_enabled | If set to false, the User is forced to use a Template | Boolean | true |
298-
| contact_links | Custom Links to show in the Choose Box | Contact Link Array | Empty Array |
317+
| Key | Description | Type | Default |
318+
|----------------------|-------------------------------------------------------|--------------------|-------------|
319+
| blank_issues_enabled | If set to false, the User is forced to use a Template | Boolean | true |
320+
| contact_links | Custom Links to show in the Choose Box | Contact Link Array | Empty Array |
299321

300322
### Contact Link
301323

302-
| Key | Description | Type | Required |
303-
|----------------------|-------------------------------------------------------------------------------------------------------|---------|----------|
304-
| name | the name of your link | String | true |
305-
| url | The URL of your Link | String | true |
306-
| about | A short description of your Link | String | true |
324+
| Key | Description | Type | Required |
325+
|-------|----------------------------------|--------|----------|
326+
| name | the name of your link | String | true |
327+
| url | The URL of your Link | String | true |
328+
| about | A short description of your Link | String | true |

models/fixtures/repo_unit.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@
520520
id: 75
521521
repo_id: 1
522522
type: 8
523+
config: "{\"ProjectsMode\":\"all\"}"
523524
created_unix: 946684810
524525

525526
-
@@ -650,12 +651,6 @@
650651
type: 2
651652
created_unix: 946684810
652653

653-
-
654-
id: 98
655-
repo_id: 1
656-
type: 8
657-
created_unix: 946684810
658-
659654
-
660655
id: 99
661656
repo_id: 1

models/repo/repo.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,11 @@ func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit
411411
Type: tp,
412412
Config: new(ActionsConfig),
413413
}
414+
} else if tp == unit.TypeProjects {
415+
return &RepoUnit{
416+
Type: tp,
417+
Config: new(ProjectsConfig),
418+
}
414419
}
415420

416421
return &RepoUnit{

models/repo/repo_unit.go

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,53 @@ func (cfg *ActionsConfig) ToDB() ([]byte, error) {
202202
return json.Marshal(cfg)
203203
}
204204

205+
// ProjectsMode represents the projects enabled for a repository
206+
type ProjectsMode string
207+
208+
const (
209+
// ProjectsModeRepo allows only repo-level projects
210+
ProjectsModeRepo ProjectsMode = "repo"
211+
// ProjectsModeOwner allows only owner-level projects
212+
ProjectsModeOwner ProjectsMode = "owner"
213+
// ProjectsModeAll allows both kinds of projects
214+
ProjectsModeAll ProjectsMode = "all"
215+
// ProjectsModeNone doesn't allow projects
216+
ProjectsModeNone ProjectsMode = "none"
217+
)
218+
219+
// ProjectsConfig describes projects config
220+
type ProjectsConfig struct {
221+
ProjectsMode ProjectsMode
222+
}
223+
224+
// FromDB fills up a ProjectsConfig from serialized format.
225+
func (cfg *ProjectsConfig) FromDB(bs []byte) error {
226+
return json.UnmarshalHandleDoubleEncode(bs, &cfg)
227+
}
228+
229+
// ToDB exports a ProjectsConfig to a serialized format.
230+
func (cfg *ProjectsConfig) ToDB() ([]byte, error) {
231+
return json.Marshal(cfg)
232+
}
233+
234+
func (cfg *ProjectsConfig) GetProjectsMode() ProjectsMode {
235+
if cfg.ProjectsMode != "" {
236+
return cfg.ProjectsMode
237+
}
238+
239+
return ProjectsModeNone
240+
}
241+
242+
func (cfg *ProjectsConfig) IsProjectsAllowed(m ProjectsMode) bool {
243+
projectsMode := cfg.GetProjectsMode()
244+
245+
if m == ProjectsModeNone {
246+
return true
247+
}
248+
249+
return projectsMode == m || projectsMode == ProjectsModeAll
250+
}
251+
205252
// BeforeSet is invoked from XORM before setting the value of a field of this object.
206253
func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
207254
switch colName {
@@ -217,7 +264,9 @@ func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
217264
r.Config = new(IssuesConfig)
218265
case unit.TypeActions:
219266
r.Config = new(ActionsConfig)
220-
case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects, unit.TypePackages:
267+
case unit.TypeProjects:
268+
r.Config = new(ProjectsConfig)
269+
case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypePackages:
221270
fallthrough
222271
default:
223272
r.Config = new(UnitConfig)
@@ -265,6 +314,11 @@ func (r *RepoUnit) ActionsConfig() *ActionsConfig {
265314
return r.Config.(*ActionsConfig)
266315
}
267316

317+
// ProjectsConfig returns config for unit.ProjectsConfig
318+
func (r *RepoUnit) ProjectsConfig() *ProjectsConfig {
319+
return r.Config.(*ProjectsConfig)
320+
}
321+
268322
func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) {
269323
var tmpUnits []*RepoUnit
270324
if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Find(&tmpUnits); err != nil {

modules/issue/template/template.go

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,13 @@ func validateRequired(field *api.IssueFormField, idx int) error {
122122
// The label is not required for a markdown or checkboxes field
123123
return nil
124124
}
125-
return validateBoolItem(newErrorPosition(idx, field.Type), field.Validations, "required")
125+
if err := validateBoolItem(newErrorPosition(idx, field.Type), field.Validations, "required"); err != nil {
126+
return err
127+
}
128+
if required, _ := field.Validations["required"].(bool); required && !field.VisibleOnForm() {
129+
return newErrorPosition(idx, field.Type).Errorf("can not require a hidden field")
130+
}
131+
return nil
126132
}
127133

128134
func validateID(field *api.IssueFormField, idx int, ids container.Set[string]) error {
@@ -172,10 +178,38 @@ func validateOptions(field *api.IssueFormField, idx int) error {
172178
return position.Errorf("'label' is required and should be a string")
173179
}
174180

181+
if visibility, ok := opt["visible"]; ok {
182+
visibilityList, ok := visibility.([]any)
183+
if !ok {
184+
return position.Errorf("'visible' should be list")
185+
}
186+
for _, visibleType := range visibilityList {
187+
visibleType, ok := visibleType.(string)
188+
if !ok || !(visibleType == "form" || visibleType == "content") {
189+
return position.Errorf("'visible' list can only contain strings of 'form' and 'content'")
190+
}
191+
}
192+
}
193+
175194
if required, ok := opt["required"]; ok {
176195
if _, ok := required.(bool); !ok {
177196
return position.Errorf("'required' should be a bool")
178197
}
198+
199+
// validate if hidden field is required
200+
if visibility, ok := opt["visible"]; ok {
201+
visibilityList, _ := visibility.([]any)
202+
isVisible := false
203+
for _, v := range visibilityList {
204+
if vv, _ := v.(string); vv == "form" {
205+
isVisible = true
206+
break
207+
}
208+
}
209+
if !isVisible {
210+
return position.Errorf("can not require a hidden checkbox")
211+
}
212+
}
179213
}
180214
}
181215
}
@@ -238,7 +272,7 @@ func RenderToMarkdown(template *api.IssueTemplate, values url.Values) string {
238272
IssueFormField: field,
239273
Values: values,
240274
}
241-
if f.ID == "" {
275+
if f.ID == "" || !f.VisibleInContent() {
242276
continue
243277
}
244278
f.WriteTo(builder)
@@ -253,11 +287,6 @@ type valuedField struct {
253287
}
254288

255289
func (f *valuedField) WriteTo(builder *strings.Builder) {
256-
if f.Type == api.IssueFormFieldTypeMarkdown {
257-
// markdown blocks do not appear in output
258-
return
259-
}
260-
261290
// write label
262291
if !f.HideLabel() {
263292
_, _ = fmt.Fprintf(builder, "### %s\n\n", f.Label())
@@ -269,6 +298,9 @@ func (f *valuedField) WriteTo(builder *strings.Builder) {
269298
switch f.Type {
270299
case api.IssueFormFieldTypeCheckboxes:
271300
for _, option := range f.Options() {
301+
if !option.VisibleInContent() {
302+
continue
303+
}
272304
checked := " "
273305
if option.IsChecked() {
274306
checked = "x"
@@ -302,6 +334,10 @@ func (f *valuedField) WriteTo(builder *strings.Builder) {
302334
} else {
303335
_, _ = fmt.Fprintf(builder, "%s\n", value)
304336
}
337+
case api.IssueFormFieldTypeMarkdown:
338+
if value, ok := f.Attributes["value"].(string); ok {
339+
_, _ = fmt.Fprintf(builder, "%s\n", value)
340+
}
305341
}
306342
_, _ = fmt.Fprintln(builder)
307343
}
@@ -314,6 +350,9 @@ func (f *valuedField) Label() string {
314350
}
315351

316352
func (f *valuedField) HideLabel() bool {
353+
if f.Type == api.IssueFormFieldTypeMarkdown {
354+
return true
355+
}
317356
if label, ok := f.Attributes["hide_label"].(bool); ok {
318357
return label
319358
}
@@ -385,6 +424,22 @@ func (o *valuedOption) IsChecked() bool {
385424
return false
386425
}
387426

427+
func (o *valuedOption) VisibleInContent() bool {
428+
if o.field.Type == api.IssueFormFieldTypeCheckboxes {
429+
if vs, ok := o.data.(map[string]any); ok {
430+
if vl, ok := vs["visible"].([]any); ok {
431+
for _, v := range vl {
432+
if vv, _ := v.(string); vv == "content" {
433+
return true
434+
}
435+
}
436+
return false
437+
}
438+
}
439+
}
440+
return true
441+
}
442+
388443
var minQuotesRegex = regexp.MustCompilePOSIX("^`{3,}")
389444

390445
// minQuotes return 3 or more back-quotes.

0 commit comments

Comments
 (0)