ReleaseNote -> ChangeLog
This commit is contained in:
parent
c993b77b5d
commit
9a2d88b93b
23 changed files with 258 additions and 258 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -4,7 +4,7 @@ configs/**/data/**
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
logs/
|
logs/
|
||||||
|
|
||||||
# Deploy sırasında git tag'lerinden üretilir (configs/release-notes/generate-release-notes.sh)
|
# Deploy sırasında git tag'lerinden üretilir (configs/change-logs/generate-change-logs.sh)
|
||||||
# ve API konteynerine mount edilir. Takip edilirse deploy'daki `git pull` yerel
|
# ve API konteynerine mount edilir. Takip edilirse deploy'daki `git pull` yerel
|
||||||
# değişiklikle çakışır ve dosya eskir.
|
# değişiklikle çakışır ve dosya eskir.
|
||||||
configs/release-notes/release-notes.json
|
configs/change-logs/change-logs.json
|
||||||
14
README.md
14
README.md
|
|
@ -710,23 +710,23 @@ konfigürasyonu ile üretilir.
|
||||||
(`views/version/swRegistration.ts`, `sw.ts`, `AppUpdateDialog.tsx`).
|
(`views/version/swRegistration.ts`, `sw.ts`, `AppUpdateDialog.tsx`).
|
||||||
- Isıtma yalnızca kuruluma bağlı değildir: uygulama açılışta `ENSURE_WARMUP` mesajı yollar,
|
- Isıtma yalnızca kuruluma bağlı değildir: uygulama açılışta `ENSURE_WARMUP` mesajı yollar,
|
||||||
service worker eksik kalan bileşenleri kaldığı yerden tamamlar.
|
service worker eksik kalan bileşenleri kaldığı yerden tamamlar.
|
||||||
- **Sürüm bilgisi backend'dedir.** `Sas_H_ReleaseNote` tablosu tek kaynaktır; istemci sürüm
|
- **Sürüm bilgisi backend'dedir.** `Sas_H_ChangeLog` tablosu tek kaynaktır; istemci sürüm
|
||||||
numarasını ve son sürümün notlarını `application-configuration` yanıtındaki
|
numarasını ve son sürümün notlarını `application-configuration` yanıtındaki
|
||||||
`extraProperties.changeLogs` alanından okur (`PlatformApplicationConfigurationContributor`),
|
`extraProperties.changeLogs` alanından okur (`PlatformApplicationConfigurationContributor`),
|
||||||
tam listeyi ise `/api/app/release-note` endpoint'inden alır. Ayrı bir `version.json` isteği
|
tam listeyi ise `/api/app/change-log` endpoint'inden alır. Ayrı bir `version.json` isteği
|
||||||
yoktur. Changelog `/admin/changeLog` ekranında gösterilir; sürüm numarası son görülenden
|
yoktur. Changelog `/admin/changeLog` ekranında gösterilir; sürüm numarası son görülenden
|
||||||
farklıysa kullanıcı giriş sonrası oraya yönlendirilir (tetikleyici bundle değil, sürümdür —
|
farklıysa kullanıcı giriş sonrası oraya yönlendirilir (tetikleyici bundle değil, sürümdür —
|
||||||
yalnızca yeni bir git tag'i eklenmiş olsa da çalışır).
|
yalnızca yeni bir git tag'i eklenmiş olsa da çalışır).
|
||||||
- **Sürüm notu akışı — DbMigrator gerektirmez:** `configs/release-notes/generate-release-notes.sh`
|
- **Sürüm notu akışı — DbMigrator gerektirmez:** `configs/change-logs/generate-change-logs.sh`
|
||||||
deploy sırasında (`deploy/app.sh`) git tag'lerinden `configs/release-notes/release-notes.json`
|
deploy sırasında (`deploy/app.sh`) git tag'lerinden `configs/change-logs/change-logs.json`
|
||||||
üretir, dosya API konteynerine `/etc/api/release-notes` altına salt okunur mount edilir ve
|
üretir, dosya API konteynerine `/etc/api/change-logs` altına salt okunur mount edilir ve
|
||||||
`ReleaseNoteStartupService` uygulama açılışında tabloyu bu dosyayla eşitler. Dosya imaja
|
`ChangeLogStartupService` uygulama açılışında tabloyu bu dosyayla eşitler. Dosya imaja
|
||||||
**gömülmez**: api build context'i içindeyken her yeni tag Dockerfile'daki `COPY . .`
|
**gömülmez**: api build context'i içindeyken her yeni tag Dockerfile'daki `COPY . .`
|
||||||
katmanını geçersiz kılıp imajı gereksiz yere yeniden derletiyordu; artık kod değişmediyse
|
katmanını geçersiz kılıp imajı gereksiz yere yeniden derletiyordu; artık kod değişmediyse
|
||||||
imaj cache'ten gelir. Yeni sürüm için tag atıp deploy etmek yeterlidir. Notlar
|
imaj cache'ten gelir. Yeni sürüm için tag atıp deploy etmek yeterlidir. Notlar
|
||||||
**annotated** tag mesajından okunur (`git tag -a 1.2.0 -m "..."`), her satır bir madde.
|
**annotated** tag mesajından okunur (`git tag -a 1.2.0 -m "..."`), her satır bir madde.
|
||||||
- **Tablo git tag listesinin aynasıdır:** yeni tag eklenir, mesajı düzeltilen tag güncellenir,
|
- **Tablo git tag listesinin aynasıdır:** yeni tag eklenir, mesajı düzeltilen tag güncellenir,
|
||||||
git'ten silinen tag tablodan da (hard delete ile) kaldırılır. Bu yüzden `Sas_H_ReleaseNote`
|
git'ten silinen tag tablodan da (hard delete ile) kaldırılır. Bu yüzden `Sas_H_ChangeLog`
|
||||||
elle düzenlenmemelidir — ilk deploy'da geri alınır. Dosya okunamaz veya boşsa senkronizasyon
|
elle düzenlenmemelidir — ilk deploy'da geri alınır. Dosya okunamaz veya boşsa senkronizasyon
|
||||||
hiçbir şey yapmaz, tablo boşaltılmaz.
|
hiçbir şey yapmaz, tablo boşaltılmaz.
|
||||||
- Deploy algılaması service worker'ın kendi `registration.update()` kontrolüne dayanır:
|
- Deploy algılaması service worker'ın kendi `registration.update()` kontrolüne dayanır:
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using Volo.Abp.Application.Dtos;
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
namespace Sozsoft.Platform.ReleaseNotes;
|
namespace Sozsoft.Platform.ChangeLogs;
|
||||||
|
|
||||||
public class ReleaseNoteDto : EntityDto<Guid>
|
public class ChangeLogDto : EntityDto<Guid>
|
||||||
{
|
{
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
public DateTime ReleaseDate { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
|
|
@ -6,34 +6,34 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
using Sozsoft.Platform.Entities;
|
using Sozsoft.Platform.Entities;
|
||||||
using Volo.Abp.Domain.Repositories;
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
|
||||||
namespace Sozsoft.Platform.ReleaseNotes;
|
namespace Sozsoft.Platform.ChangeLogs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sürüm notları (ChangeLog ekranının kaynağı).
|
/// Sürüm notları (ChangeLog ekranının kaynağı).
|
||||||
///
|
///
|
||||||
/// Kayıtlar git tag'lerinden üretilip <c>Sas_H_ReleaseNote</c> tablosuna
|
/// Kayıtlar git tag'lerinden üretilip <c>Sas_H_ChangeLog</c> tablosuna
|
||||||
/// tohumlanır. Uygulamanın çalışan sürüm numarası ise application-configuration
|
/// tohumlanır. Uygulamanın çalışan sürüm numarası ise application-configuration
|
||||||
/// yanıtındaki <c>extraProperties.changeLogs</c> ile gelir; bu servis yalnızca
|
/// yanıtındaki <c>extraProperties.changeLogs</c> ile gelir; bu servis yalnızca
|
||||||
/// tam listeyi döner, böylece her config isteğinde tüm changelog taşınmaz.
|
/// tam listeyi döner, böylece her config isteğinde tüm changelog taşınmaz.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class ReleaseNoteAppService : PlatformAppService
|
public class ChangeLogAppService : PlatformAppService
|
||||||
{
|
{
|
||||||
private readonly IRepository<ReleaseNote, Guid> _releaseNoteRepository;
|
private readonly IRepository<ChangeLog, Guid> _changeLogRepository;
|
||||||
|
|
||||||
public ReleaseNoteAppService(IRepository<ReleaseNote, Guid> releaseNoteRepository)
|
public ChangeLogAppService(IRepository<ChangeLog, Guid> changeLogRepository)
|
||||||
{
|
{
|
||||||
_releaseNoteRepository = releaseNoteRepository;
|
_changeLogRepository = changeLogRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<ReleaseNoteDto>> GetListAsync()
|
public async Task<List<ChangeLogDto>> GetListAsync()
|
||||||
{
|
{
|
||||||
var items = await _releaseNoteRepository.GetListAsync(x => x.IsPublished);
|
var items = await _changeLogRepository.GetListAsync(x => x.IsPublished);
|
||||||
|
|
||||||
return items
|
return items
|
||||||
.OrderByDescending(note => note.ReleaseDate)
|
.OrderByDescending(note => note.ReleaseDate)
|
||||||
.ThenByDescending(note => note.Version)
|
.ThenByDescending(note => note.Version)
|
||||||
.Select(note => new ReleaseNoteDto
|
.Select(note => new ChangeLogDto
|
||||||
{
|
{
|
||||||
Id = note.Id,
|
Id = note.Id,
|
||||||
Version = note.Version,
|
Version = note.Version,
|
||||||
|
|
@ -98,5 +98,5 @@ public enum TableNameEnum
|
||||||
DbTableColumn,
|
DbTableColumn,
|
||||||
DevRequest,
|
DevRequest,
|
||||||
Agenda,
|
Agenda,
|
||||||
ReleaseNote
|
ChangeLog
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ public static class TableNameResolver
|
||||||
{ nameof(TableNameEnum.DbTableColumn), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.DbTableColumn), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.LogEntry), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.LogEntry), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.AiBot), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.AiBot), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.ReleaseNote), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.ChangeLog), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.GlobalSearch), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.GlobalSearch), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.ContactTitle), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.ContactTitle), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.Currency), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.Currency), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ namespace Sozsoft.Platform.Entities;
|
||||||
/// changelog'u application-configuration yanıtındaki
|
/// changelog'u application-configuration yanıtındaki
|
||||||
/// <c>extraProperties.changeLogs</c> alanından okur, ayrı bir sürüm dosyası yoktur.
|
/// <c>extraProperties.changeLogs</c> alanından okur, ayrı bir sürüm dosyası yoktur.
|
||||||
///
|
///
|
||||||
/// Kayıtlar git tag'lerinden türer ve açılışta <c>ReleaseNoteStartupService</c>
|
/// Kayıtlar git tag'lerinden türer ve açılışta <c>ChangeLogStartupService</c>
|
||||||
/// tarafından tag listesiyle birebir eşitlenir.
|
/// tarafından tag listesiyle birebir eşitlenir.
|
||||||
///
|
///
|
||||||
/// Host seviyesindedir (tenant'a göre değişmez).
|
/// Host seviyesindedir (tenant'a göre değişmez).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ReleaseNote : FullAuditedEntity<Guid>
|
public class ChangeLog : FullAuditedEntity<Guid>
|
||||||
{
|
{
|
||||||
/// <summary>Kullanıcıya gösterilen sürüm numarası (ör. "1.2.1").</summary>
|
/// <summary>Kullanıcıya gösterilen sürüm numarası (ör. "1.2.1").</summary>
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
|
@ -46,11 +46,11 @@ public class ReleaseNote : FullAuditedEntity<Guid>
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ReleaseNote()
|
protected ChangeLog()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReleaseNote(string version, DateTime releaseDate, string notes, string commit = null, bool isPublished = true)
|
public ChangeLog(string version, DateTime releaseDate, string notes, string commit = null, bool isPublished = true)
|
||||||
{
|
{
|
||||||
Version = version;
|
Version = version;
|
||||||
ReleaseDate = releaseDate;
|
ReleaseDate = releaseDate;
|
||||||
|
|
@ -46,7 +46,7 @@ public class PlatformDbContext :
|
||||||
public DbSet<Tenant> Tenants { get; set; }
|
public DbSet<Tenant> Tenants { get; set; }
|
||||||
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
|
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
|
||||||
public DbSet<AiBot> AiBots { get; set; }
|
public DbSet<AiBot> AiBots { get; set; }
|
||||||
public DbSet<ReleaseNote> ReleaseNotes { get; set; }
|
public DbSet<ChangeLog> ChangeLogs { get; set; }
|
||||||
public DbSet<Branch> Branches { get; set; }
|
public DbSet<Branch> Branches { get; set; }
|
||||||
public DbSet<BranchUsers> BranchUsers { get; set; }
|
public DbSet<BranchUsers> BranchUsers { get; set; }
|
||||||
public DbSet<GlobalSearch> GlobalSearchs { get; set; }
|
public DbSet<GlobalSearch> GlobalSearchs { get; set; }
|
||||||
|
|
@ -203,9 +203,9 @@ public class PlatformDbContext :
|
||||||
b.HasIndex(x => new { x.Name }).IsUnique().HasFilter(null);
|
b.HasIndex(x => new { x.Name }).IsUnique().HasFilter(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Entity<ReleaseNote>(b =>
|
builder.Entity<ChangeLog>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ReleaseNote)), Prefix.DbSchema);
|
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ChangeLog)), Prefix.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(a => a.Version).IsRequired().HasMaxLength(32);
|
b.Property(a => a.Version).IsRequired().HasMaxLength(32);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Sozsoft.Platform.Migrations
|
namespace Sozsoft.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20260812194642_Initial")]
|
[Migration("20260817083025_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -1381,6 +1381,68 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Sas_T_BranchUsers", (string)null);
|
b.ToTable("Sas_T_BranchUsers", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sozsoft.Platform.Entities.ChangeLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Commit")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPublished")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Notes")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Version")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(32)
|
||||||
|
.HasColumnType("nvarchar(32)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Version")
|
||||||
|
.IsUnique()
|
||||||
|
.HasFilter("[IsDeleted] = 0");
|
||||||
|
|
||||||
|
b.ToTable("Sas_H_ChangeLog", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.City", b =>
|
modelBuilder.Entity("Sozsoft.Platform.Entities.City", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -4662,68 +4724,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Sas_H_Product", (string)null);
|
b.ToTable("Sas_H_Product", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.ReleaseNote", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Commit")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsPublished")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Notes")
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ReleaseDate")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<string>("Version")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("nvarchar(32)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("Version")
|
|
||||||
.IsUnique()
|
|
||||||
.HasFilter("[IsDeleted] = 0");
|
|
||||||
|
|
||||||
b.ToTable("Sas_H_ReleaseNote", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.ReportCategory", b =>
|
modelBuilder.Entity("Sozsoft.Platform.Entities.ReportCategory", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -1035,6 +1035,29 @@ namespace Sozsoft.Platform.Migrations
|
||||||
table.PrimaryKey("PK_Sas_H_BlogCategory", x => x.Id);
|
table.PrimaryKey("PK_Sas_H_BlogCategory", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Sas_H_ChangeLog",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
Version = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
|
||||||
|
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
Commit = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||||
|
Notes = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
IsPublished = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Sas_H_ChangeLog", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Sas_H_Contact",
|
name: "Sas_H_Contact",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -1700,29 +1723,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
table.PrimaryKey("PK_Sas_H_Product", x => x.Id);
|
table.PrimaryKey("PK_Sas_H_Product", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Sas_H_ReleaseNote",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
Version = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
|
|
||||||
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
Commit = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
|
||||||
Notes = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
|
||||||
IsPublished = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Sas_H_ReleaseNote", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Sas_H_Route",
|
name: "Sas_H_Route",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -4057,6 +4057,13 @@ namespace Sozsoft.Platform.Migrations
|
||||||
unique: true,
|
unique: true,
|
||||||
filter: "[IsDeleted] = 0");
|
filter: "[IsDeleted] = 0");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Sas_H_ChangeLog_Version",
|
||||||
|
table: "Sas_H_ChangeLog",
|
||||||
|
column: "Version",
|
||||||
|
unique: true,
|
||||||
|
filter: "[IsDeleted] = 0");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Sas_H_City_Country_Name",
|
name: "IX_Sas_H_City_Country_Name",
|
||||||
table: "Sas_H_City",
|
table: "Sas_H_City",
|
||||||
|
|
@ -4257,13 +4264,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
unique: true,
|
unique: true,
|
||||||
filter: "[IsDeleted] = 0");
|
filter: "[IsDeleted] = 0");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Sas_H_ReleaseNote_Version",
|
|
||||||
table: "Sas_H_ReleaseNote",
|
|
||||||
column: "Version",
|
|
||||||
unique: true,
|
|
||||||
filter: "[IsDeleted] = 0");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Sas_H_Route_Key",
|
name: "IX_Sas_H_Route_Key",
|
||||||
table: "Sas_H_Route",
|
table: "Sas_H_Route",
|
||||||
|
|
@ -4526,6 +4526,9 @@ namespace Sozsoft.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Sas_H_BlogPost");
|
name: "Sas_H_BlogPost");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Sas_H_ChangeLog");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Sas_H_Contact");
|
name: "Sas_H_Contact");
|
||||||
|
|
||||||
|
|
@ -4604,9 +4607,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Sas_H_Product");
|
name: "Sas_H_Product");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Sas_H_ReleaseNote");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Sas_H_Route");
|
name: "Sas_H_Route");
|
||||||
|
|
||||||
|
|
@ -1378,6 +1378,68 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Sas_T_BranchUsers", (string)null);
|
b.ToTable("Sas_T_BranchUsers", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sozsoft.Platform.Entities.ChangeLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Commit")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("IsPublished")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Notes")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Version")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(32)
|
||||||
|
.HasColumnType("nvarchar(32)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Version")
|
||||||
|
.IsUnique()
|
||||||
|
.HasFilter("[IsDeleted] = 0");
|
||||||
|
|
||||||
|
b.ToTable("Sas_H_ChangeLog", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.City", b =>
|
modelBuilder.Entity("Sozsoft.Platform.Entities.City", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -4659,68 +4721,6 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Sas_H_Product", (string)null);
|
b.ToTable("Sas_H_Product", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.ReleaseNote", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("Commit")
|
|
||||||
.HasMaxLength(64)
|
|
||||||
.HasColumnType("nvarchar(64)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsPublished")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Notes")
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("ReleaseDate")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<string>("Version")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(32)
|
|
||||||
.HasColumnType("nvarchar(32)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("Version")
|
|
||||||
.IsUnique()
|
|
||||||
.HasFilter("[IsDeleted] = 0");
|
|
||||||
|
|
||||||
b.ToTable("Sas_H_ReleaseNote", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.ReportCategory", b =>
|
modelBuilder.Entity("Sozsoft.Platform.Entities.ReportCategory", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ using Volo.Abp.Uow;
|
||||||
|
|
||||||
namespace Sozsoft.Platform.Extensions;
|
namespace Sozsoft.Platform.Extensions;
|
||||||
|
|
||||||
public class ReleaseNoteSeedDto
|
public class ChangeLogSeedDto
|
||||||
{
|
{
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
public string ReleaseDate { get; set; }
|
public string ReleaseDate { get; set; }
|
||||||
|
|
@ -25,16 +25,16 @@ public class ReleaseNoteSeedDto
|
||||||
public List<string> Notes { get; set; }
|
public List<string> Notes { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReleaseNoteSeedFileDto
|
public class ChangeLogSeedFileDto
|
||||||
{
|
{
|
||||||
public List<ReleaseNoteSeedDto> ReleaseNotes { get; set; }
|
public List<ChangeLogSeedDto> ChangeLogs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sürüm notlarını uygulama açılışında veritabanına senkronize eder.
|
/// Sürüm notlarını uygulama açılışında veritabanına senkronize eder.
|
||||||
///
|
///
|
||||||
/// Kaynak, konteynere mount edilen <c>release-notes.json</c> dosyasıdır; bu dosya
|
/// Kaynak, konteynere mount edilen <c>change-logs.json</c> dosyasıdır; bu dosya
|
||||||
/// deploy sırasında <c>configs/release-notes/generate-release-notes.sh</c> tarafından
|
/// deploy sırasında <c>configs/change-logs/generate-change-logs.sh</c> tarafından
|
||||||
/// git tag'lerinden üretilir. Böylece yeni bir sürüm tag'i eklemek için DbMigrator
|
/// git tag'lerinden üretilir. Böylece yeni bir sürüm tag'i eklemek için DbMigrator
|
||||||
/// çalıştırmak GEREKMEZ — API'yi deploy etmek yeterlidir.
|
/// çalıştırmak GEREKMEZ — API'yi deploy etmek yeterlidir.
|
||||||
///
|
///
|
||||||
|
|
@ -45,25 +45,25 @@ public class ReleaseNoteSeedFileDto
|
||||||
/// tag güncellenir, silinen tag veritabanından da kaldırılır. Dosya okunamaz veya
|
/// tag güncellenir, silinen tag veritabanından da kaldırılır. Dosya okunamaz veya
|
||||||
/// boşsa hiçbir şey yapılmaz (yanlışlıkla tablo boşaltılmasın diye).
|
/// boşsa hiçbir şey yapılmaz (yanlışlıkla tablo boşaltılmasın diye).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ReleaseNoteStartupService : IHostedService
|
public class ChangeLogStartupService : IHostedService
|
||||||
{
|
{
|
||||||
private const string FileName = "release-notes.json";
|
private const string FileName = "change-logs.json";
|
||||||
|
|
||||||
// Konteynerde docker-compose-app.yml ile mount edilen yol.
|
// Konteynerde docker-compose-app.yml ile mount edilen yol.
|
||||||
private const string MountedDirectory = "/etc/api/release-notes";
|
private const string MountedDirectory = "/etc/api/change-logs";
|
||||||
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly IHostApplicationLifetime _applicationLifetime;
|
private readonly IHostApplicationLifetime _applicationLifetime;
|
||||||
private readonly IHostEnvironment _environment;
|
private readonly IHostEnvironment _environment;
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
private readonly ILogger<ReleaseNoteStartupService> _logger;
|
private readonly ILogger<ChangeLogStartupService> _logger;
|
||||||
|
|
||||||
public ReleaseNoteStartupService(
|
public ChangeLogStartupService(
|
||||||
IServiceProvider serviceProvider,
|
IServiceProvider serviceProvider,
|
||||||
IHostApplicationLifetime applicationLifetime,
|
IHostApplicationLifetime applicationLifetime,
|
||||||
IHostEnvironment environment,
|
IHostEnvironment environment,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
ILogger<ReleaseNoteStartupService> logger)
|
ILogger<ChangeLogStartupService> logger)
|
||||||
{
|
{
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
_applicationLifetime = applicationLifetime;
|
_applicationLifetime = applicationLifetime;
|
||||||
|
|
@ -105,11 +105,11 @@ public class ReleaseNoteStartupService : IHostedService
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await using var stream = File.OpenRead(path);
|
await using var stream = File.OpenRead(path);
|
||||||
var data = await JsonSerializer.DeserializeAsync<ReleaseNoteSeedFileDto>(
|
var data = await JsonSerializer.DeserializeAsync<ChangeLogSeedFileDto>(
|
||||||
stream,
|
stream,
|
||||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||||
|
|
||||||
var items = data?.ReleaseNotes ?? [];
|
var items = data?.ChangeLogs ?? [];
|
||||||
if (items.Count == 0)
|
if (items.Count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -145,13 +145,13 @@ public class ReleaseNoteStartupService : IHostedService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dosya yolunu sırayla dener: açık ayar (<c>App:ReleaseNotesPath</c>), konteynerdeki
|
/// Dosya yolunu sırayla dener: açık ayar (<c>App:ChangeLogsPath</c>), konteynerdeki
|
||||||
/// mount noktası, son olarak yerel geliştirmede depodaki <c>configs/release-notes</c>
|
/// mount noktası, son olarak yerel geliştirmede depodaki <c>configs/change-logs</c>
|
||||||
/// klasörü. Hiçbiri yoksa null döner.
|
/// klasörü. Hiçbiri yoksa null döner.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private string ResolvePath()
|
private string ResolvePath()
|
||||||
{
|
{
|
||||||
var configured = _configuration["App:ReleaseNotesPath"];
|
var configured = _configuration["App:ChangeLogsPath"];
|
||||||
if (!string.IsNullOrWhiteSpace(configured))
|
if (!string.IsNullOrWhiteSpace(configured))
|
||||||
{
|
{
|
||||||
// Klasör verildiyse dosya adı eklenir.
|
// Klasör verildiyse dosya adı eklenir.
|
||||||
|
|
@ -166,11 +166,11 @@ public class ReleaseNoteStartupService : IHostedService
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yerel geliştirme: ContentRootPath api/src/Sozsoft.Platform.HttpApi.Host,
|
// Yerel geliştirme: ContentRootPath api/src/Sozsoft.Platform.HttpApi.Host,
|
||||||
// aranan yol depo kökündeki configs/release-notes.
|
// aranan yol depo kökündeki configs/change-logs.
|
||||||
var directory = new DirectoryInfo(_environment.ContentRootPath);
|
var directory = new DirectoryInfo(_environment.ContentRootPath);
|
||||||
while (directory != null)
|
while (directory != null)
|
||||||
{
|
{
|
||||||
var candidate = Path.Combine(directory.FullName, "configs", "release-notes", FileName);
|
var candidate = Path.Combine(directory.FullName, "configs", "change-logs", FileName);
|
||||||
if (File.Exists(candidate))
|
if (File.Exists(candidate))
|
||||||
{
|
{
|
||||||
return candidate;
|
return candidate;
|
||||||
|
|
@ -184,9 +184,9 @@ public class ReleaseNoteStartupService : IHostedService
|
||||||
|
|
||||||
private static async Task<(int Inserted, int Updated, int Deleted)> SyncItemsAsync(
|
private static async Task<(int Inserted, int Updated, int Deleted)> SyncItemsAsync(
|
||||||
IServiceProvider services,
|
IServiceProvider services,
|
||||||
List<ReleaseNoteSeedDto> items)
|
List<ChangeLogSeedDto> items)
|
||||||
{
|
{
|
||||||
var repository = services.GetRequiredService<IRepository<ReleaseNote, Guid>>();
|
var repository = services.GetRequiredService<IRepository<ChangeLog, Guid>>();
|
||||||
var unitOfWorkManager = services.GetRequiredService<IUnitOfWorkManager>();
|
var unitOfWorkManager = services.GetRequiredService<IUnitOfWorkManager>();
|
||||||
var currentTenant = services.GetRequiredService<ICurrentTenant>();
|
var currentTenant = services.GetRequiredService<ICurrentTenant>();
|
||||||
|
|
||||||
|
|
@ -209,7 +209,7 @@ public class ReleaseNoteStartupService : IHostedService
|
||||||
|
|
||||||
if (!existing.TryGetValue(item.Version, out var current))
|
if (!existing.TryGetValue(item.Version, out var current))
|
||||||
{
|
{
|
||||||
await repository.InsertAsync(new ReleaseNote(item.Version, releaseDate, notes, item.Commit));
|
await repository.InsertAsync(new ChangeLog(item.Version, releaseDate, notes, item.Commit));
|
||||||
inserted++;
|
inserted++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -27,12 +27,12 @@ public class PlatformApplicationConfigurationContributor : IApplicationConfigura
|
||||||
|
|
||||||
// Uygulamanın çalışan sürümü: istemcinin tek sürüm kaynağı (ayrı bir
|
// Uygulamanın çalışan sürümü: istemcinin tek sürüm kaynağı (ayrı bir
|
||||||
// version.json isteği yoktur). Yalnızca EN SON sürüm taşınır; tam liste
|
// version.json isteği yoktur). Yalnızca EN SON sürüm taşınır; tam liste
|
||||||
// ChangeLog ekranının kendi endpoint'inden (/api/app/release-note) gelir,
|
// ChangeLog ekranının kendi endpoint'inden (/api/app/change-log) gelir,
|
||||||
// aksi halde her config isteğinde bütün changelog gönderilirdi.
|
// aksi halde her config isteğinde bütün changelog gönderilirdi.
|
||||||
var releaseNoteRepository = context.ServiceProvider.GetRequiredService<IRepository<ReleaseNote, Guid>>();
|
var changeLogRepository = context.ServiceProvider.GetRequiredService<IRepository<ChangeLog, Guid>>();
|
||||||
var releaseNotes = await releaseNoteRepository.GetListAsync(x => x.IsPublished);
|
var changeLogs = await changeLogRepository.GetListAsync(x => x.IsPublished);
|
||||||
|
|
||||||
var latest = releaseNotes
|
var latest = changeLogs
|
||||||
.OrderByDescending(note => note.ReleaseDate)
|
.OrderByDescending(note => note.ReleaseDate)
|
||||||
.ThenByDescending(note => note.Version)
|
.ThenByDescending(note => note.Version)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
|
||||||
|
|
@ -140,9 +140,9 @@ public class PlatformHttpApiHostModule : AbpModule
|
||||||
ConfigureCache();
|
ConfigureCache();
|
||||||
ConfigureHangfire(context, configuration);
|
ConfigureHangfire(context, configuration);
|
||||||
context.Services.AddHostedService<BackgroundWorkerStartupService>();
|
context.Services.AddHostedService<BackgroundWorkerStartupService>();
|
||||||
// Sürüm notları imaja gömülü release-notes.json'dan senkronize edilir;
|
// Sürüm notları imaja gömülü change-logs.json'dan senkronize edilir;
|
||||||
// yeni bir sürüm tag'i için DbMigrator çalıştırmak gerekmez.
|
// yeni bir sürüm tag'i için DbMigrator çalıştırmak gerekmez.
|
||||||
context.Services.AddHostedService<Extensions.ReleaseNoteStartupService>();
|
context.Services.AddHostedService<Extensions.ChangeLogStartupService>();
|
||||||
ConfigureBlobStoring(configuration);
|
ConfigureBlobStoring(configuration);
|
||||||
ConfigureAuditing();
|
ConfigureAuditing();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@
|
||||||
<None Remove="Logs\**" />
|
<None Remove="Logs\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Sürüm notları (release-notes.json) artık bu projeye kopyalanmaz: dosya
|
<!-- Sürüm notları (change-logs.json) artık bu projeye kopyalanmaz: dosya
|
||||||
configs/release-notes altında üretilir ve konteynere mount edilir. api build
|
configs/change-logs altında üretilir ve konteynere mount edilir. api build
|
||||||
context'i içindeyken her yeni tag imajı gereksiz yere yeniden derletiyordu. -->
|
context'i içindeyken her yeni tag imajı gereksiz yere yeniden derletiyordu. -->
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
18
configs/change-logs/README.md
Normal file
18
configs/change-logs/README.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# change-logs
|
||||||
|
|
||||||
|
`change-logs.json` git tag'lerinden üretilir ve API konteynerine salt okunur
|
||||||
|
mount edilir (`/etc/api/change-logs`). İmaja gömülmez.
|
||||||
|
|
||||||
|
- Üretim: `bash configs/change-logs/generate-change-logs.sh`
|
||||||
|
- Deploy akışında otomatik çağrılır: `configs/deployment/scripts/deploy/app.sh`
|
||||||
|
- Okuyan taraf: `ChangeLogStartupService` (uygulama açılışında `Sas_H_ChangeLog`
|
||||||
|
tablosunu bu dosyayla eşitler)
|
||||||
|
|
||||||
|
Bu klasör API build context'inin dışındadır; böylece yeni bir tag atmak API imajını
|
||||||
|
yeniden derletmez, docker cache'i bozulmaz.
|
||||||
|
|
||||||
|
Farklı bir yol kullanılacaksa `App:ChangeLogsPath` (env: `App__ChangeLogsPath`)
|
||||||
|
ayarı ile ezilebilir.
|
||||||
|
|
||||||
|
`change-logs.json` `.gitignore`'dadır; deploy'daki `git pull` ile çakışmaması için
|
||||||
|
takip edilmez.
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Sürüm notlarını git tag'lerinden üretir:
|
# Sürüm notlarını git tag'lerinden üretir:
|
||||||
# configs/release-notes/release-notes.json
|
# configs/change-logs/change-logs.json
|
||||||
#
|
#
|
||||||
# Dosya İMAJA GÖMÜLMEZ. Konteynere docker-compose-app.yml üzerinden
|
# Dosya İMAJA GÖMÜLMEZ. Konteynere docker-compose-app.yml üzerinden
|
||||||
# `/etc/api/release-notes` altına salt okunur mount edilir; ReleaseNoteStartupService
|
# `/etc/api/change-logs` altına salt okunur mount edilir; ChangeLogStartupService
|
||||||
# açılışta bu yolu okuyup `Sas_H_ReleaseNote` tablosuyla eşitler, DbMigrator gerekmez.
|
# açılışta bu yolu okuyup `Sas_H_ChangeLog` tablosuyla eşitler, DbMigrator gerekmez.
|
||||||
#
|
#
|
||||||
# Neden api/ altında değil: dosya api build context'i içindeyken her yeni tag
|
# Neden api/ altında değil: dosya api build context'i içindeyken her yeni tag
|
||||||
# Dockerfile'daki `COPY . .` katmanını geçersiz kılıyor ve kodda hiçbir değişiklik
|
# Dockerfile'daki `COPY . .` katmanını geçersiz kılıyor ve kodda hiçbir değişiklik
|
||||||
|
|
@ -21,14 +21,14 @@ set -e
|
||||||
# Dış bağımlılığı yoktur (jq/node gerekmez): JSON kaçışları sed ile yapılır.
|
# Dış bağımlılığı yoktur (jq/node gerekmez): JSON kaçışları sed ile yapılır.
|
||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
OUTPUT="release-notes.json"
|
OUTPUT="change-logs.json"
|
||||||
|
|
||||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
echo "> git deposu yok, ${OUTPUT} güncellenmedi." >&2
|
echo "> git deposu yok, ${OUTPUT} güncellenmedi." >&2
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "> release-notes.json oluşturuluyor..."
|
echo "> change-logs.json oluşturuluyor..."
|
||||||
|
|
||||||
# origin'de olmayan yerel tag'ler sürüm sırasını bozar; temizle. `--force` şart:
|
# origin'de olmayan yerel tag'ler sürüm sırasını bozar; temizle. `--force` şart:
|
||||||
# yerel bir tag origin'dekinden farklı commit'e bakıyorsa git onu "would clobber
|
# yerel bir tag origin'dekinden farklı commit'e bakıyorsa git onu "would clobber
|
||||||
|
|
@ -49,7 +49,7 @@ escape_json() {
|
||||||
}
|
}
|
||||||
|
|
||||||
TMP=$(mktemp)
|
TMP=$(mktemp)
|
||||||
printf '{\n "ReleaseNotes": [\n' > "$TMP"
|
printf '{\n "ChangeLogs": [\n' > "$TMP"
|
||||||
|
|
||||||
FIRST_TAG=true
|
FIRST_TAG=true
|
||||||
for TAG in $TAGS; do
|
for TAG in $TAGS; do
|
||||||
|
|
@ -45,9 +45,9 @@ services:
|
||||||
- ../seeds:/etc/api/seeds
|
- ../seeds:/etc/api/seeds
|
||||||
- api-keys:/root/.aspnet/DataProtection-Keys
|
- api-keys:/root/.aspnet/DataProtection-Keys
|
||||||
# Surum notlari imaja gomulmez; deploy sirasinda git tag'lerinden uretilip
|
# Surum notlari imaja gomulmez; deploy sirasinda git tag'lerinden uretilip
|
||||||
# buradan okunur (ReleaseNoteStartupService). Boylece yeni tag API imajini
|
# buradan okunur (ChangeLogStartupService). Boylece yeni tag API imajini
|
||||||
# yeniden derletmez.
|
# yeniden derletmez.
|
||||||
- ../release-notes:/etc/api/release-notes:ro
|
- ../change-logs:/etc/api/change-logs:ro
|
||||||
networks:
|
networks:
|
||||||
- db
|
- db
|
||||||
- default
|
- default
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ cd ~/sozsoft-platform/api
|
||||||
|
|
||||||
# Sürüm notları burada ÜRETİLMEZ. Dosya api build context'i içindeyken her yeni
|
# Sürüm notları burada ÜRETİLMEZ. Dosya api build context'i içindeyken her yeni
|
||||||
# tag Dockerfile'daki `COPY . .` katmanını geçersiz kılıyor ve kodda hiçbir
|
# tag Dockerfile'daki `COPY . .` katmanını geçersiz kılıyor ve kodda hiçbir
|
||||||
# değişiklik olmasa bile imaj baştan derleniyordu. Artık configs/release-notes
|
# değişiklik olmasa bile imaj baştan derleniyordu. Artık configs/change-logs
|
||||||
# altında deploy sırasında üretilip konteynere mount ediliyor
|
# altında deploy sırasında üretilip konteynere mount ediliyor
|
||||||
# (configs/deployment/scripts/deploy/app.sh).
|
# (configs/deployment/scripts/deploy/app.sh).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,14 @@ git checkout main
|
||||||
# farklı commit'e bakıyorsa --force olmadan reddedilir ve yeni tag'ler gelmez.
|
# farklı commit'e bakıyorsa --force olmadan reddedilir ve yeni tag'ler gelmez.
|
||||||
git fetch --prune --prune-tags --tags --force && git pull
|
git fetch --prune --prune-tags --tags --force && git pull
|
||||||
|
|
||||||
# Sürüm notları imaja gömülü değil; konteynere configs/release-notes klasöründen
|
# Sürüm notları imaja gömülü değil; konteynere configs/change-logs klasöründen
|
||||||
# mount ediliyor ve API açılışta veritabanına senkronize ediyor (DbMigrator
|
# mount ediliyor ve API açılışta veritabanına senkronize ediyor (DbMigrator
|
||||||
# gerekmez). `bash ...` ile çağrılır: depo Windows'tan yönetildiği için
|
# gerekmez). `bash ...` ile çağrılır: depo Windows'tan yönetildiği için
|
||||||
# çalıştırma biti kaybolunca "Permission denied" verip notları sessizce düşürüyordu.
|
# çalıştırma biti kaybolunca "Permission denied" verip notları sessizce düşürüyordu.
|
||||||
RELEASE_NOTES=~/sozsoft-platform/configs/release-notes/release-notes.json
|
RELEASE_NOTES=~/sozsoft-platform/configs/change-logs/change-logs.json
|
||||||
bash ~/sozsoft-platform/configs/release-notes/generate-release-notes.sh
|
bash ~/sozsoft-platform/configs/change-logs/generate-change-logs.sh
|
||||||
|
|
||||||
# Dosya yoksa API açılışta "release-notes.json bulunamadı" uyarısı verir ve
|
# Dosya yoksa API açılışta "change-logs.json bulunamadı" uyarısı verir ve
|
||||||
# changelog eskir; sessizce devam etmek yerine burada dur.
|
# changelog eskir; sessizce devam etmek yerine burada dur.
|
||||||
if [ ! -s "$RELEASE_NOTES" ]; then
|
if [ ! -s "$RELEASE_NOTES" ]; then
|
||||||
echo "HATA: ${RELEASE_NOTES} üretilemedi, deploy durduruldu." >&2
|
echo "HATA: ${RELEASE_NOTES} üretilemedi, deploy durduruldu." >&2
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
# release-notes
|
|
||||||
|
|
||||||
`release-notes.json` git tag'lerinden üretilir ve API konteynerine salt okunur
|
|
||||||
mount edilir (`/etc/api/release-notes`). İmaja gömülmez.
|
|
||||||
|
|
||||||
- Üretim: `bash configs/release-notes/generate-release-notes.sh`
|
|
||||||
- Deploy akışında otomatik çağrılır: `configs/deployment/scripts/deploy/app.sh`
|
|
||||||
- Okuyan taraf: `ReleaseNoteStartupService` (uygulama açılışında `Sas_H_ReleaseNote`
|
|
||||||
tablosunu bu dosyayla eşitler)
|
|
||||||
|
|
||||||
Bu klasör API build context'inin dışındadır; böylece yeni bir tag atmak API imajını
|
|
||||||
yeniden derletmez, docker cache'i bozulmaz.
|
|
||||||
|
|
||||||
Farklı bir yol kullanılacaksa `App:ReleaseNotesPath` (env: `App__ReleaseNotesPath`)
|
|
||||||
ayarı ile ezilebilir.
|
|
||||||
|
|
||||||
`release-notes.json` `.gitignore`'dadır; deploy'daki `git pull` ile çakışmaması için
|
|
||||||
takip edilmez.
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
import apiService from '@/services/api.service'
|
import apiService from '@/services/api.service'
|
||||||
|
|
||||||
/** `Sas_H_ReleaseNote` kaydı; git tag'lerinden tohumlanır. */
|
/** `Sas_H_ChangeLog` kaydı; git tag'lerinden tohumlanır. */
|
||||||
export interface ReleaseNoteDto {
|
export interface ChangeLogDto {
|
||||||
id: string
|
id: string
|
||||||
version: string
|
version: string
|
||||||
releaseDate: string
|
releaseDate: string
|
||||||
changeLog: string[]
|
changeLog: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReleaseNoteService {
|
class ChangeLogService {
|
||||||
/**
|
/**
|
||||||
* ChangeLog ekranının kaynağı. Uygulamanın çalışan sürüm numarası
|
* ChangeLog ekranının kaynağı. Uygulamanın çalışan sürüm numarası
|
||||||
* application-configuration ile geldiği için burada yalnızca tam liste alınır.
|
* application-configuration ile geldiği için burada yalnızca tam liste alınır.
|
||||||
*/
|
*/
|
||||||
async getList(): Promise<ReleaseNoteDto[]> {
|
async getList(): Promise<ChangeLogDto[]> {
|
||||||
const response = await apiService.fetchData<ReleaseNoteDto[]>({
|
const response = await apiService.fetchData<ChangeLogDto[]>({
|
||||||
url: '/api/app/release-note',
|
url: '/api/app/change-log',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
})
|
})
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const releaseNoteService = new ReleaseNoteService()
|
export const changeLogService = new ChangeLogService()
|
||||||
|
|
@ -5,7 +5,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import PageTitle from '@/components/shared/PageTitle'
|
import PageTitle from '@/components/shared/PageTitle'
|
||||||
import { FaRegCheckCircle, FaSyncAlt, FaTag } from 'react-icons/fa'
|
import { FaRegCheckCircle, FaSyncAlt, FaTag } from 'react-icons/fa'
|
||||||
import { releaseNoteService, type ReleaseNoteDto } from '@/services/releaseNote.service'
|
import { changeLogService, type ChangeLogDto } from '@/services/changeLog.service'
|
||||||
import { checkForAppUpdate } from './swRegistration'
|
import { checkForAppUpdate } from './swRegistration'
|
||||||
import { useStoreActions } from '@/store'
|
import { useStoreActions } from '@/store'
|
||||||
|
|
||||||
|
|
@ -96,16 +96,16 @@ const Changelog = () => {
|
||||||
const { isCheckingUpdate, checkForUpdate } = useManualUpdateCheck()
|
const { isCheckingUpdate, checkForUpdate } = useManualUpdateCheck()
|
||||||
const clearPendingChangelog = useStoreActions((actions) => actions.locale.clearPendingChangelog)
|
const clearPendingChangelog = useStoreActions((actions) => actions.locale.clearPendingChangelog)
|
||||||
|
|
||||||
// Kaynak `ReleaseNote` entity'sidir; liste yalnızca bu ekran açıldığında
|
// Kaynak `ChangeLog` entity'sidir; liste yalnızca bu ekran açıldığında
|
||||||
// istenir (application-configuration sadece çalışan sürümü taşır).
|
// istenir (application-configuration sadece çalışan sürümü taşır).
|
||||||
const [releases, setReleases] = useState<ReleaseNoteDto[]>([])
|
const [releases, setReleases] = useState<ChangeLogDto[]>([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Bekleyen changelog bayrağı burada tüketilir; kullanıcı değişiklikleri
|
// Bekleyen changelog bayrağı burada tüketilir; kullanıcı değişiklikleri
|
||||||
// gördüğü için sonraki girişlerde tekrar yönlendirilmez.
|
// gördüğü için sonraki girişlerde tekrar yönlendirilmez.
|
||||||
clearPendingChangelog()
|
clearPendingChangelog()
|
||||||
|
|
||||||
void releaseNoteService
|
void changeLogService
|
||||||
.getList()
|
.getList()
|
||||||
.then(setReleases)
|
.then(setReleases)
|
||||||
.catch((error: unknown) => console.warn('Sürüm notları alınamadı.', error))
|
.catch((error: unknown) => console.warn('Sürüm notları alınamadı.', error))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue