Support legacy run/job index-based URLs and refactor migration 326#37008
Support legacy run/job index-based URLs and refactor migration 326#37008lunny merged 23 commits intogo-gitea:mainfrom
Conversation
|
Would it be hard to add a "revert" migration? Migrations should be append-only, removing one in the middle defeats the migration concept. Alternatively keep it but make it a no-op. |
|
I don't think you should touch the doctor system anymore. Unless you can fully make it right and fix bugs like "gitea doctor check --all --fix deleted all my LFS files and attachments #36227" |
Revert migration will only make it worse it might be more slow. |
|
AI review, rubberstamp approval, bad design, then hurt end users. |
|
One problem I see is the following: |
This PR actually makes migration |
I agree. Running migration
I must admit that my design in #36842 was a mistake. We should have used a new URL format, such as |
|
What about "partially" migrating the jobs links? For example, choose a magic number N = 1000
This approach should have stable behavior, and doesn't need to keep guessing whether |
|
Or, only migrate the first 1000 (or 10000) runs: there should be more than 1000 jobs. also make sure next max run/job id > 1000
|
|
@wxiaoguang Thank you for your suggestion. I'd prefer the approach "migrate the first 1000 (or 10000) runs" and will implement it. |
|
Or even simpler: migrate runs with id < 1000, jobs with id < 1000, and make sure the new run/id have id > 1000 Then:
|
I didn't use this solution. This is because if we use this approach, the target URL for run(id=1100, index=5) would not be updated (since id > 1000), yet the I actually implemented the solution from #37008 (comment), which is based on |
There was a problem hiding this comment.
-
getCommitStatusCommitIDsilently skips unhandled event types —workflow_dispatchandscheduleare common triggers, but returning""produces no log output. Operators debugging missed rewrites have no trail. Suggestion: add alog.Debugin thedefaultbranch noting the skipped event type. -
legacyURLIDThreshold = 1000lacks rationale — This constant drives the entire partial-migration tradeoff but has no comment explaining why 1000. Suggestion: add a comment documenting the reasoning (e.g. "covers the range where run index and ID are most likely to collide; remaining legacy URLs are resolved at runtime"). -
resolveCurrentRunForViewcomplexity — Run-only pages use ID-first fallback, job pages use legacy-preferred fallback. The asymmetry is hard to follow in one function. Suggestion: split intoresolveRunSummaryandresolveRunJobhelpers.
This comment was written with the help of Claude Opus 4.6.
This is because runs triggered by other events do not create commit status. The logic of gitea/services/actions/commit_status.go Lines 83 to 138 in 0df3213
I have added more comments to it to clarify its purpose.
However, this partial migration combined with the web-layer compatibility logic still cannot accurately handle all legacy target URLs. In rare cases, a legacy target URL may remain ambiguous. For example:
In such cases, the only solution is to explicitly use index-based parsing by specifying the
I originally tried to make |
* main: Fix RPM Registry 404 when package name contains 'package' (go-gitea#37087) Improve actions notifier for `workflow_run` (go-gitea#37088) Refactor code render and render control chars (go-gitea#37078) Fix various problems (go-gitea#37077) [skip ci] Updated translations via Crowdin Support legacy run/job index-based URLs and refactor migration 326 (go-gitea#37008) Fix a bug when forking a repository in an organization (go-gitea#36950)
Follow up #36842
Migration
326can be prohibitively slow on large instances because it scans and rewrites all commit status target URLs generated by Gitea Actions in the database. This PR refactors migration326to perform a partial update instead of rewriting every legacy target URL. The reason for this partial rewrite is that smaller legacy run/job indexes are the most likely to be ambiguous with run/job ID-based URLs during runtime resolution, so this change prioritizes that subset while avoiding the cost of rewriting all legacy records.To preserve access to old links, this PR introduces
resolveCurrentRunForViewto handle both ID-based URLs and index-based URLs:/actions/runs/{run}/jobs/{job}), it first tries to confirm that the URL is ID-based. It does so by checking whether{job}can be treated as an existing job ID in the repository and whether that job belongs to{run}. If that match cannot be confirmed, it falls back to treating the URL as legacyrun index + job index, resolves the corresponding run and job, and redirects to the correct ID-based URL.run_id=3, run_index=2, job_id=4), and also another run-job pair (run_id=1100, run_index=3, job_id=1200, job_index=4), then/actions/runs/3/jobs/4is ambiguous. In that case, the resolver treats it as the ID-based URL by default and shows the page forrun_id=3, job_id=4. Users can still explicitly force the legacy index-based interpretation with?by_index=1, which would resolve the same URL to/actions/runs/1100/jobs/1200./actions/runs/{run}), it uses a best-effort strategy: by default it first treats{run}as a run ID, and if no such run exists in the repository, it falls back to treating{run}as a legacy run index and redirects to the ID-based URL. Users can also explicitly force the legacy interpretation with?by_index=1.id=7, index=3) and runB (id=99, index=7), then/actions/runs/7will resolve to runA by default, even though the old index-based URL originally referred to runB.The table below shows how valid legacy index-based target URLs are handled before and after migration
326. Lower-range legacy URLs are rewritten to ID-based URLs, while higher-range legacy URLs remain unchanged in the database but are still handled correctly byresolveCurrentRunForViewat runtime./user2/repo2/actions/runs/2/jobs/1/user2/repo2/actions/runs/3/jobs/4/user2/repo2/actions/runs/3/jobs/4/user2/repo2/actions/runs/4/jobs/8id=3))/user2/repo2/actions/runs/20/jobs/0/user2/repo2/actions/runs/80/jobs/170/user2/repo2/actions/runs/900/jobs/0/user2/repo2/actions/runs/900/jobs/0/user2/repo2/actions/runs/1500/jobs/0/user2/repo2/actions/runs/1500/jobs/0/user2/repo2/actions/runs/1500/jobs/1/user2/repo2/actions/runs/1500/jobs/1For users who already ran the old migration
326, this change has no functional impact. Their historical URLs are already stored in the ID-based form, and ID-based URLs continue to resolve correctly.For users who have not run the old migration
326, only a subset of legacy target URLs will now be rewritten during upgrade. This avoids the extreme runtime cost of the previous full migration, while all remaining legacy target URLs continue to work through the web-layer compatibility logic.Many thanks to @wxiaoguang for the suggestions.