Skip to content

feat(org): support archiving organizations - #39538

Open
ilijamt wants to merge 7 commits into
go-gitea:mainfrom
ilijamt:feat/archive-org
Open

ilijamt wants to merge 7 commits into
go-gitea:mainfrom
ilijamt:feat/archive-org

Conversation

@ilijamt

@ilijamt ilijamt commented Oct 1, 2026 •

Copy link
Copy Markdown

I have a lot of organizations with only archived repositories, and they clutter my dashboard. Moving them all into one archive organization would lose where they came from, and I'd have to track that with topics.

Archiving an organization now archives all its repositories and blocks new ones. Repositories transferred in are archived too. Unarchiving only unarchives the organization.

Archived organizations are hidden on the dashboard by default, with a toggle to show them.

image image image

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Oct 1, 2026
@github-actions github-actions Bot added the type/feature Completely new functionality. Can only be merged if feature freeze is not active. label Oct 1, 2026
@ilijamt

ilijamt commented Oct 1, 2026 •

Copy link
Copy Markdown
Author

I've added a search box in the org panel so it's consistent with the repositories panel.

image

Comment thread modelmigration/v29/v357.go
@silverwind

silverwind commented Oct 2, 2026 •

Copy link
Copy Markdown
Member
  1. Does GitHub have a similar org archival feature?
  2. What happens to repos on an archived or, will the archival cascade?

@ilijamt

ilijamt commented Oct 2, 2026

Copy link
Copy Markdown
Author
  1. Does GitHub have a similar org archival feature?

Yes it does, and makes the org read only, so you can't create new repos in there. The new button is disabled. https://docs.github.com/en/organizations/managing-organization-settings/archiving-an-organization

  1. What happens to repos on an archived or, will the archival cascade?

Yes, it cascades. Archiving an organization archives all its repositories (except mirrors) and blocks new ones. Repositories transferred in are archived too. While the organization is archived you can't unarchive its repositories one by one. Unarchiving only unarchives the organization, and the repositories stay archived. Same as GitHub

While clicking through the UI I noticed you can still create projects in an archived organization. Should that be disabled too? It's a simple change. I'd leave members and teams as they are, archived or not.

image image

@silverwind

silverwind commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

you can still create projects in an archived organization. Should that be disabled too?

Yes I'd say an archived org should, like a archived project, act read-only.

But do check how projects and other things behave in archived repos first, there might be more such pre-existing bugs.

If you can, have your AI validate that our behaviour of archived orgs matches github's.

@ilijamt

ilijamt commented Oct 2, 2026

Copy link
Copy Markdown
Author

you can still create projects in an archived organization. Should that be disabled too?

Yes I'd say an archived org should, like a archived project, act read-only.

But do check how projects and other things behave in archived repos first, there might be more such pre-existing bugs.

If you can, have your AI validate that our behaviour of archived orgs matches github's.

Will do. just a question how should we handle if org has a mirror? As you have to convert it to a regular repo so you can archive it. So we have two choices leave it as it is and the mirror will be the exception, or decline to convert to archived org while we have active mirror?

@silverwind

silverwind commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Check how GitHub does it and align to that if possible. Maybe we could just allow mirror repos be archived? Why was it forbidden?

@ilijamt

ilijamt commented Oct 2, 2026

Copy link
Copy Markdown
Author

Check how GitHub does it. Maybe we could just allow mirror repos be archived? Why was it forbidden?

@silverwind

Currently mirror repositories in Gitea do not have the concept or archiving the mirror repos. Github will make them read only, but it works differently from how mirrors are in Gitea. If I add this it would be a bigger change, so if we want to handle this maybe better in a follow up PR later?

This is how it looks like now for a mirror repo The current functionality doesn't allow to archive a mirror repo. If we convert it to regular repo then we can archive it.

image

@silverwind

silverwind commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

To keep the changeset small, I think we can deny archiving an org when it contains mirror repos, e.g. show an error in that case and tell the user they have to manually convert those mirrors to regular repos first.

@ilijamt

ilijamt commented Oct 2, 2026

Copy link
Copy Markdown
Author

To keep the changeset small, I think we can deny archiving an org when it contains mirror repos

Done. If the org has mirrors, archiving is refused and the settings page lists them, so they can be converted first.

An archived org is now read-only: projects, labels, webhooks, Actions settings, packages and the profile. I checked it against GitHub and it behaves the same.

The branch is squashed into 5 commits.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical archive-transition races and unresolved archived-state enforcement gaps block safe approval.

Review effort: Lite
Findings: 3 High severity

Open (3)
What changed in this PR

Adds organization archiving, repository propagation, read-only enforcement, dashboard filtering, API support, migrations, and tests.

Changes:

  • Adds archived organization state, archive/unarchive flows, audit events, and migration support.
  • Archives existing and transferred repositories while blocking mutations in archived organizations.
  • Updates dashboard UI, templates, localization, API schemas, and integration coverage.

Open findings include archive-transition races in repository creation and transfer, incomplete enforcement paths, API unarchive behavior, stale issue indexing, and a dashboard keyboard interaction issue.

File Summary
web_src/​js/​components/​DashboardRepoList.vue Archived organization filtering and search UI
web_src/​css/​modules/​dropdown.css Disabled dropdown styling
tests/​integration/​org_archived_test.go Organization archive integration tests
tests/​integration/​api_repo_edit_test.go Archived repository behavior tests
templates/​webhook/​new.tmpl Disables archived organization webhook forms
templates/​user/​settings/​applications_oauth2_list.tmpl Hides OAuth mutations
templates/​user/​settings/​applications_oauth2_edit_form.tmpl Disables OAuth editing
templates/​user/​dashboard/​repolist.tmpl Adds archive metadata to the dashboard
templates/​user/​dashboard/​navbar.tmpl Adds archived organization navigation
templates/​swagger/​v1-swagger.generated.json Updated Swagger documentation
templates/​swagger/​v1-openapi3.generated.json Updated OpenAPI documentation
templates/​shared/​variables/​variable_list.tmpl Read-only variables UI
templates/​shared/​secrets/​add_list.tmpl Read-only secrets UI
templates/​shared/​actions/​scoped_workflows.tmpl Read-only workflow settings
templates/​shared/​actions/​runner_list.tmpl Read-only runner controls
templates/​shared/​actions/​runner_edit.tmpl Read-only runner editing
templates/​shared/​actions/​owner_general_settings.tmpl Read-only Actions settings
templates/​repo/​settings/​webhook/​settings.tmpl Disables webhook mutations
templates/​repo/​settings/​webhook/​history.tmpl Hides webhook replay
templates/​repo/​settings/​webhook/​base_list.tmpl Hides webhook controls
templates/​repo/​settings/​options.tmpl Blocks repository unarchiving
templates/​repo/​issue/​labels/​label_list.tmpl Blocks organization label editing
templates/​projects/​new.tmpl Disables project creation
templates/​package/​shared/​cleanup_rules/​list.tmpl Hides cleanup rule editing
templates/​package/​shared/​cleanup_rules/​edit.tmpl Disables cleanup rule mutations
templates/​package/​shared/​cargo.tmpl Hides Cargo mutations
templates/​org/​settings/​options.tmpl Makes archived settings read-only
templates/​org/​settings/​options_dangerzone.tmpl Adds archive controls
templates/​org/​settings/​layout_head.tmpl Adds an archived warning
templates/​org/​settings/​labels.tmpl Hides label creation
templates/​org/​home.tmpl Hides repository creation
templates/​org/​header.tmpl Displays archived status
services/​repository/​transfer.go Archives transferred repositories
services/​repository/​transfer_test.go Tests transfer restrictions
services/​repository/​create.go Blocks creation in archived organizations
services/​org/​org.go Implements organization archival
services/​org/​org_test.go Tests archival behavior
services/​convert/​convert.go Exposes archive state in API data
services/​context/​package.go Restricts archived package owners
services/​context/​org.go Adds archived organization context guards
services/​context/​api.go Adds archived organization API errors
routers/​web/​web.go Applies archived organization route guards
routers/​web/​user/​home.go Adds archived organization dashboard state
routers/​web/​repo/​setting/​setting.go Handles archived transfer and unarchive errors
routers/​web/​repo/​repo.go Handles archived creation errors
routers/​web/​repo/​migrate.go Handles archived migration errors
routers/​web/​repo/​fork.go Handles archived fork errors
routers/​web/​org/​setting.go Adds the organization archive endpoint
routers/​web/​org/​projects.go Blocks archived project writes
routers/​api/​v1/​shared/​project.go Documents archived project responses
routers/​api/​v1/​repo/​transfer.go Handles archived transfer errors
routers/​api/​v1/​repo/​repo.go Handles archived repository changes
routers/​api/​v1/​repo/​migrate.go Handles archived migration errors
routers/​api/​v1/​repo/​fork.go Handles archived fork errors
routers/​api/​v1/​org/​org.go Adds archive API support
routers/​api/​v1/​org/​label.go Guards organization labels
routers/​api/​v1/​org/​hook.go Guards organization hooks
routers/​api/​v1/​org/​avatar.go Guards organization avatars
routers/​api/​v1/​org/​action.go Guards organization Actions
routers/​api/​v1/​api.go Registers archived organization guards
options/​locale/​locale_en-US.json Adds archive-related translations
modules/​structs/​org.go Adds archive API fields
models/​user/​user.go Adds archive persistence fields
models/​organization/​org.go Adds archive state persistence
models/​organization/​org_list.go Excludes archived creation targets
models/​organization/​org_list_test.go Tests archived organization filtering
models/​audit/​action.go Adds archive audit events
modelmigration/​v29/​v356.go Adds archive database columns
modelmigration/​migrations.go Registers the migration

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread services/org/org.go
Comment on lines +231 to +244
if err := org_model.SetArchiveOrgState(ctx, org, archived); err != nil {
return err
}
if !archived {
return nil
}
if err := db.GetEngine(ctx).Where(builder.Eq{"owner_id": org.ID, "is_archived": false}).Find(&repos); err != nil {
return err
}
for _, repo := range repos {
if err := repo_model.SetArchiveRepoState(ctx, repo, true); err != nil {
return err
}
}
Comment on lines +342 to +344
if u.IsOrganization() && u.IsArchived {
return util.NewPermissionDeniedErrorf("organization %s is archived", u.Name)
}
Comment on lines +158 to +160
if err := checkTransferIntoArchivedOrg(newOwner, repo); err != nil {
return err
}
@ilijamt

ilijamt commented Oct 3, 2026 •

Copy link
Copy Markdown
Author

@silverwind I checked the Copilot comments. The race is real but unlikely, and harmless: worst case one repo in an archived org stays writable. I see 3 options:

  1. Leave it, since the repo can be archived by hand.
  2. Re-read the archived state inside the create transaction, like transfer does. This narrows the window.
  3. Lock the org during archive, create and transfer. This closes it fully, but Gitea doesn't use row locks anywhere.

Any preference?

There was a merge conflict in the migrations so I had to rebase

@silverwind

silverwind commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Recent changes on include some race-prevention code during database transactions, so it might be unnecessary, but I have not checked in detail if those preventions really apply here. Code should primarily be written to be race-free.

Always be sceptical about AI reviews. I will do a more complete review using Claude later.

@ilijamt

ilijamt commented Oct 5, 2026

Copy link
Copy Markdown
Author

I added one QoL, if you open an archived org it will show you the archived repos immediatly instead of having to go to the ui and select to show the arcvhied repos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. type/feature Completely new functionality. Can only be merged if feature freeze is not active.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants