Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit a70bb04

Browse files
committed
Merge master into fixes/disable-selected-asset-history-view
2 parents 580c6ad + 1a23457 commit a70bb04

35 files changed

+1720
-1601
lines changed

docs/process/release-process.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Release process
2+
3+
## Release information
4+
5+
### Tag name format
6+
7+
***Alpha releases***: `v[major].[minor]-alpha`
8+
9+
***Beta releases***: `v[major].[minor]-beta`
10+
11+
***Releases***: `v[major].[minor]`
12+
13+
## The process
14+
15+
#### TL;DR
16+
17+
1. Dev branches to a release branch every week, create draft release with release notes
18+
2. QA tests release branch for up to a week
19+
3. Dev continues work on master
20+
4. Dev fixes shipblockers on release branch and updates build on draft release page, and makes sure fixes are also sent to master
21+
5. QA publishes release by tagging the release branch and hitting "Publish"
22+
6. Goto 1
23+
24+
#### The long explanation
25+
26+
Every week:
27+
28+
1. Create a release branch from master with the name `release/[Major].[Minor]`, where `[Major].[Minor]` are the current major and minor parts of the version set on master.
29+
1. Bump the version on master
30+
1. Create a draft release with the release notes, following the format below
31+
1. Upload a build created from the release branch
32+
1. QA tests the release and logs any issues found in it. Issues are fixed on the next release unless they are related to the issues that are reported as fixed in the current release, and they are shipblockers.
33+
1. If the release requires fixes:
34+
1. If the fix is reverting a PR, that doesn't have to be done on master, only on the release branch. Otherwise:
35+
1. Create a branch from the release branch fork point (the commit that the release branch is based on)
36+
1. Push the fix to this branch and create a PR targetting the release branch
37+
1. Upload a new build from the release branch
38+
1. Create another branch from master, merge the fix branch into it and create a PR targetting master
39+
1. QA approves release by:
40+
1. Filling out the tag name, in the format shown above
41+
1. Selecting the release branch corresponding to the build
42+
1. Clicking `Publish release`
43+
44+
45+
## Template for release notes
46+
47+
The https://github.com/github-for-unity/unity-release-notes node project generates draft release notes by outputting all issues labeled `Feature`, `Enhancement` and `Bug` closed since the last release in the correct format for release notes, and also outputs all PRs closed since the last release, in case some issues might not have been correctly labeled and/or created.
48+
49+
The markdown format for release notes is below. This is what the project above generates (more or less).
50+
51+
```
52+
# Release notes
53+
54+
[any special notes and/or funny/relevant image for the release here, if needed]
55+
56+
## Features
57+
58+
- #XXX - Title of issue (adjust for user consumption if needed)
59+
60+
## Enhancements
61+
62+
- #XXX - Title of issue (adjust for user consumption if needed)
63+
64+
## Fixes
65+
66+
- #XXX - Title of issue (adjust for user consumption if needed)
67+
68+
```

docs/readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ Details about how the team is organizing and shipping GitHub for Unity:
2424

2525
- **[Issue Triage](process/issue-triage.md)** - how we address issues reported
2626
by users
27-
- **[Review Process](process/reviews.md)** - how we review contributions
27+
- **[Review](process/reviews.md)** - how we review contributions
2828
- **[Roadmap](process/roadmap.md)** - how we plan for the future
29+
- **[Release](process/release-process.md)** - how we review contributions
2930

3031
## Technical
3132

src/GitHub.Api/Events/RepositoryWatcher.cs

Lines changed: 115 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface IRepositoryWatcher : IDisposable
1111
{
1212
void Start();
1313
void Stop();
14-
event Action<string> HeadChanged;
14+
event Action HeadChanged;
1515
event Action IndexChanged;
1616
event Action ConfigChanged;
1717
event Action<string> LocalBranchChanged;
@@ -38,7 +38,7 @@ class RepositoryWatcher : IRepositoryWatcher
3838
private bool processingEvents;
3939
private readonly ManualResetEventSlim signalProcessingEventsDone = new ManualResetEventSlim(false);
4040

41-
public event Action<string> HeadChanged;
41+
public event Action HeadChanged;
4242
public event Action IndexChanged;
4343
public event Action ConfigChanged;
4444
public event Action<string> LocalBranchChanged;
@@ -162,14 +162,7 @@ public int CheckAndProcessEvents()
162162

163163
private int ProcessEvents(Event[] fileEvents)
164164
{
165-
var eventsProcessed = 0;
166-
var configChanged = false;
167-
var headChanged = false;
168-
var repositoryChanged = false;
169-
var indexChanged = false;
170-
171-
string headContent = null;
172-
165+
Dictionary<EventType, List<EventData>> events = new Dictionary<EventType, List<EventData>>();
173166
foreach (var fileEvent in fileEvents)
174167
{
175168
if (!running)
@@ -197,22 +190,17 @@ private int ProcessEvents(Event[] fileEvents)
197190
// handling events in .git/*
198191
if (fileA.IsChildOf(paths.DotGitPath))
199192
{
200-
if (!configChanged && fileA.Equals(paths.DotGitConfig))
193+
if (!events.ContainsKey(EventType.ConfigChanged) && fileA.Equals(paths.DotGitConfig))
201194
{
202-
configChanged = true;
195+
events.Add(EventType.ConfigChanged, null);
203196
}
204-
else if (!headChanged && fileA.Equals(paths.DotGitHead))
197+
else if (!events.ContainsKey(EventType.HeadChanged) && fileA.Equals(paths.DotGitHead))
205198
{
206-
if (fileEvent.Type != EventType.DELETED)
207-
{
208-
headContent = paths.DotGitHead.ReadAllLines().FirstOrDefault();
209-
}
210-
211-
headChanged = true;
199+
events.Add(EventType.HeadChanged, null);
212200
}
213-
else if (!indexChanged && fileA.Equals(paths.DotGitIndex))
201+
else if (!events.ContainsKey(EventType.IndexChanged) && fileA.Equals(paths.DotGitIndex))
214202
{
215-
indexChanged = true;
203+
events.Add(EventType.IndexChanged, null);
216204
}
217205
else if (fileA.IsChildOf(paths.RemotesPath))
218206
{
@@ -226,20 +214,17 @@ private int ProcessEvents(Event[] fileEvents)
226214

227215
var origin = relativePathElements[0];
228216

229-
if (fileEvent.Type == EventType.DELETED)
217+
if (fileEvent.Type == sfw.net.EventType.DELETED)
230218
{
231219
if (fileA.ExtensionWithDot == ".lock")
232220
{
233221
continue;
234222
}
235223

236224
var branch = string.Join(@"/", relativePathElements.Skip(1).ToArray());
237-
238-
Logger.Trace("RemoteBranchDeleted: {0}/{1}", origin, branch);
239-
RemoteBranchDeleted?.Invoke(origin, branch);
240-
eventsProcessed++;
225+
AddOrUpdateEventData(events, EventType.RemoteBranchDeleted, new EventData { Origin = origin, Branch = branch });
241226
}
242-
else if (fileEvent.Type == EventType.RENAMED)
227+
else if (fileEvent.Type == sfw.net.EventType.RENAMED)
243228
{
244229
if (fileA.ExtensionWithDot != ".lock")
245230
{
@@ -255,17 +240,14 @@ private int ProcessEvents(Event[] fileEvents)
255240
.Union(new[] { fileA.FileNameWithoutExtension }).ToArray();
256241

257242
var branch = string.Join(@"/", branchPathElement);
258-
259-
Logger.Trace("RemoteBranchCreated: {0}/{1}", origin, branch);
260-
RemoteBranchCreated?.Invoke(origin, branch);
261-
eventsProcessed++;
243+
AddOrUpdateEventData(events, EventType.RemoteBranchCreated, new EventData { Origin = origin, Branch = branch });
262244
}
263245
}
264246
}
265247
}
266248
else if (fileA.IsChildOf(paths.BranchesPath))
267249
{
268-
if (fileEvent.Type == EventType.MODIFIED)
250+
if (fileEvent.Type == sfw.net.EventType.MODIFIED)
269251
{
270252
if (fileA.DirectoryExists())
271253
{
@@ -287,11 +269,10 @@ private int ProcessEvents(Event[] fileEvents)
287269

288270
var branch = string.Join(@"/", relativePathElements.ToArray());
289271

290-
Logger.Trace("LocalBranchChanged: {0}", branch);
291-
LocalBranchChanged?.Invoke(branch);
292-
eventsProcessed++;
272+
AddOrUpdateEventData(events, EventType.LocalBranchChanged, new EventData { Branch = branch });
273+
293274
}
294-
else if (fileEvent.Type == EventType.DELETED)
275+
else if (fileEvent.Type == sfw.net.EventType.DELETED)
295276
{
296277
if (fileA.ExtensionWithDot == ".lock")
297278
{
@@ -307,12 +288,9 @@ private int ProcessEvents(Event[] fileEvents)
307288
}
308289

309290
var branch = string.Join(@"/", relativePathElements.ToArray());
310-
311-
Logger.Trace("LocalBranchDeleted: {0}", branch);
312-
LocalBranchDeleted?.Invoke(branch);
313-
eventsProcessed++;
291+
AddOrUpdateEventData(events, EventType.LocalBranchDeleted, new EventData { Branch = branch });
314292
}
315-
else if (fileEvent.Type == EventType.RENAMED)
293+
else if (fileEvent.Type == sfw.net.EventType.RENAMED)
316294
{
317295
if (fileA.ExtensionWithDot != ".lock")
318296
{
@@ -332,54 +310,117 @@ private int ProcessEvents(Event[] fileEvents)
332310
}
333311

334312
var branch = string.Join(@"/", relativePathElements.ToArray());
335-
336-
Logger.Trace("LocalBranchCreated: {0}", branch);
337-
LocalBranchCreated?.Invoke(branch);
338-
eventsProcessed++;
313+
AddOrUpdateEventData(events, EventType.LocalBranchCreated, new EventData { Branch = branch });
339314
}
340315
}
341316
}
342317
}
343318
}
344319
else
345320
{
346-
if (repositoryChanged || ignoredPaths.Any(ignoredPath => fileA.IsChildOf(ignoredPath)))
321+
if (events.ContainsKey(EventType.RepositoryChanged) || ignoredPaths.Any(ignoredPath => fileA.IsChildOf(ignoredPath)))
347322
{
348323
continue;
349324
}
350-
351-
repositoryChanged = true;
325+
events.Add(EventType.RepositoryChanged, null);
352326
}
353327
}
354328

355-
if (configChanged)
329+
return FireEvents(events);
330+
}
331+
332+
private void AddOrUpdateEventData(Dictionary<EventType, List<EventData>> events, EventType type, EventData data)
333+
{
334+
if (!events.ContainsKey(type))
335+
events.Add(type, new List<EventData>());
336+
events[type].Add(data);
337+
}
338+
339+
private int FireEvents(Dictionary<EventType, List<EventData>> events)
340+
{
341+
int eventsProcessed = 0;
342+
if (events.ContainsKey(EventType.ConfigChanged))
356343
{
357344
Logger.Trace("ConfigChanged");
358345
ConfigChanged?.Invoke();
359346
eventsProcessed++;
360347
}
361348

362-
if (headChanged)
349+
if (events.ContainsKey(EventType.HeadChanged))
363350
{
364-
Logger.Trace("HeadChanged: {0}", headContent ?? "[null]");
365-
HeadChanged?.Invoke(headContent);
351+
Logger.Trace("HeadChanged");
352+
HeadChanged?.Invoke();
366353
eventsProcessed++;
367354
}
368355

369-
if (indexChanged)
356+
if (events.ContainsKey(EventType.IndexChanged))
370357
{
371358
Logger.Trace("IndexChanged");
372359
IndexChanged?.Invoke();
373360
eventsProcessed++;
374361
}
375362

376-
if (repositoryChanged)
363+
if (events.ContainsKey(EventType.RepositoryChanged))
377364
{
378365
Logger.Trace("RepositoryChanged");
379366
RepositoryChanged?.Invoke();
380367
eventsProcessed++;
381368
}
382369

370+
List<EventData> localBranchesCreated;
371+
if (events.TryGetValue(EventType.LocalBranchCreated, out localBranchesCreated))
372+
{
373+
foreach (var evt in localBranchesCreated)
374+
{
375+
Logger.Trace($"LocalBranchCreated: {evt.Branch}");
376+
LocalBranchCreated?.Invoke(evt.Branch);
377+
eventsProcessed++;
378+
}
379+
}
380+
381+
List<EventData> localBranchesChanged;
382+
if (events.TryGetValue(EventType.LocalBranchChanged, out localBranchesChanged))
383+
{
384+
foreach (var evt in localBranchesChanged)
385+
{
386+
Logger.Trace($"LocalBranchChanged: {evt.Branch}");
387+
LocalBranchChanged?.Invoke(evt.Branch);
388+
eventsProcessed++;
389+
}
390+
}
391+
392+
List<EventData> localBranchesDeleted;
393+
if (events.TryGetValue(EventType.LocalBranchDeleted, out localBranchesDeleted))
394+
{
395+
foreach (var evt in localBranchesDeleted)
396+
{
397+
Logger.Trace($"LocalBranchDeleted: {evt.Branch}");
398+
LocalBranchDeleted?.Invoke(evt.Branch);
399+
eventsProcessed++;
400+
}
401+
}
402+
403+
List<EventData> remoteBranchesCreated;
404+
if (events.TryGetValue(EventType.RemoteBranchCreated, out remoteBranchesCreated))
405+
{
406+
foreach (var evt in remoteBranchesCreated)
407+
{
408+
Logger.Trace($"RemoteBranchCreated: {evt.Origin}/{evt.Branch}");
409+
RemoteBranchCreated?.Invoke(evt.Origin, evt.Branch);
410+
eventsProcessed++;
411+
}
412+
}
413+
414+
List<EventData> remoteBranchesDeleted;
415+
if (events.TryGetValue(EventType.RemoteBranchDeleted, out remoteBranchesDeleted))
416+
{
417+
foreach (var evt in remoteBranchesDeleted)
418+
{
419+
Logger.Trace($"RemoteBranchDeleted: {evt.Origin}/{evt.Branch}");
420+
RemoteBranchDeleted?.Invoke(evt.Origin, evt.Branch);
421+
eventsProcessed++;
422+
}
423+
}
383424
return eventsProcessed;
384425
}
385426

@@ -407,5 +448,25 @@ public void Dispose()
407448
}
408449

409450
protected static ILogging Logger { get; } = Logging.GetLogger<RepositoryWatcher>();
451+
452+
private enum EventType
453+
{
454+
None,
455+
ConfigChanged,
456+
HeadChanged,
457+
RepositoryChanged,
458+
IndexChanged,
459+
RemoteBranchDeleted,
460+
RemoteBranchCreated,
461+
LocalBranchDeleted,
462+
LocalBranchCreated,
463+
LocalBranchChanged
464+
}
465+
466+
private class EventData
467+
{
468+
public string Origin;
469+
public string Branch;
470+
}
410471
}
411472
}

src/GitHub.Api/Git/GitRemote.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace GitHub.Unity
55
{
6-
enum GitRemoteFunction
6+
public enum GitRemoteFunction
77
{
88
Unknown,
99
Fetch,
@@ -12,7 +12,7 @@ enum GitRemoteFunction
1212
}
1313

1414
[Serializable]
15-
struct GitRemote
15+
public struct GitRemote
1616
{
1717
public string Name;
1818
public string Url;

0 commit comments

Comments
 (0)