chore(settings): show build commit in version info

pull/5866/head
boojack 4 weeks ago
parent e2c60845ea
commit 94ce1e5347

@ -37,6 +37,7 @@ var (
InstanceURL: viper.GetString("instance-url"), InstanceURL: viper.GetString("instance-url"),
} }
instanceProfile.Version = version.GetCurrentVersion() instanceProfile.Version = version.GetCurrentVersion()
instanceProfile.Commit = version.Commit
webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks") webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks")
if err := instanceProfile.Validate(); err != nil { if err := instanceProfile.Validate(); err != nil {

@ -30,6 +30,8 @@ type Profile struct {
Driver string Driver string
// Version is the current version of server // Version is the current version of server
Version string Version string
// Commit is the current build commit of server
Commit string
// InstanceURL is the url of your memos instance. // InstanceURL is the url of your memos instance.
InstanceURL string InstanceURL string
} }

@ -48,6 +48,9 @@ message InstanceProfile {
// The first administrator who set up this instance. // The first administrator who set up this instance.
// When null, instance requires initial setup (creating the first admin account). // When null, instance requires initial setup (creating the first admin account).
User admin = 7; User admin = 7;
// Commit is the current build commit of instance.
string commit = 8;
} }
// Request for instance profile. // Request for instance profile.

@ -209,7 +209,9 @@ type InstanceProfile struct {
InstanceUrl string `protobuf:"bytes,6,opt,name=instance_url,json=instanceUrl,proto3" json:"instance_url,omitempty"` InstanceUrl string `protobuf:"bytes,6,opt,name=instance_url,json=instanceUrl,proto3" json:"instance_url,omitempty"`
// The first administrator who set up this instance. // The first administrator who set up this instance.
// When null, instance requires initial setup (creating the first admin account). // When null, instance requires initial setup (creating the first admin account).
Admin *User `protobuf:"bytes,7,opt,name=admin,proto3" json:"admin,omitempty"` Admin *User `protobuf:"bytes,7,opt,name=admin,proto3" json:"admin,omitempty"`
// Commit is the current build commit of instance.
Commit string `protobuf:"bytes,8,opt,name=commit,proto3" json:"commit,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
@ -272,6 +274,13 @@ func (x *InstanceProfile) GetAdmin() *User {
return nil return nil
} }
func (x *InstanceProfile) GetCommit() string {
if x != nil {
return x.Commit
}
return ""
}
// Request for instance profile. // Request for instance profile.
type GetInstanceProfileRequest struct { type GetInstanceProfileRequest struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
@ -1377,12 +1386,13 @@ var File_api_v1_instance_service_proto protoreflect.FileDescriptor
const file_api_v1_instance_service_proto_rawDesc = "" + const file_api_v1_instance_service_proto_rawDesc = "" +
"\n" + "\n" +
"\x1dapi/v1/instance_service.proto\x12\fmemos.api.v1\x1a\x19api/v1/user_service.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a google/protobuf/field_mask.proto\x1a\x17google/type/color.proto\"\x8c\x01\n" + "\x1dapi/v1/instance_service.proto\x12\fmemos.api.v1\x1a\x19api/v1/user_service.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a google/protobuf/field_mask.proto\x1a\x17google/type/color.proto\"\xa4\x01\n" +
"\x0fInstanceProfile\x12\x18\n" + "\x0fInstanceProfile\x12\x18\n" +
"\aversion\x18\x02 \x01(\tR\aversion\x12\x12\n" + "\aversion\x18\x02 \x01(\tR\aversion\x12\x12\n" +
"\x04demo\x18\x03 \x01(\bR\x04demo\x12!\n" + "\x04demo\x18\x03 \x01(\bR\x04demo\x12!\n" +
"\finstance_url\x18\x06 \x01(\tR\vinstanceUrl\x12(\n" + "\finstance_url\x18\x06 \x01(\tR\vinstanceUrl\x12(\n" +
"\x05admin\x18\a \x01(\v2\x12.memos.api.v1.UserR\x05admin\"\x1b\n" + "\x05admin\x18\a \x01(\v2\x12.memos.api.v1.UserR\x05admin\x12\x16\n" +
"\x06commit\x18\b \x01(\tR\x06commit\"\x1b\n" +
"\x19GetInstanceProfileRequest\"\xe6\x19\n" + "\x19GetInstanceProfileRequest\"\xe6\x19\n" +
"\x0fInstanceSetting\x12\x17\n" + "\x0fInstanceSetting\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12W\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12W\n" +

@ -2530,6 +2530,9 @@ components:
description: |- description: |-
The first administrator who set up this instance. The first administrator who set up this instance.
When null, instance requires initial setup (creating the first admin account). When null, instance requires initial setup (creating the first admin account).
commit:
type: string
description: Commit is the current build commit of instance.
description: Instance profile message containing basic instance information. description: Instance profile message containing basic instance information.
InstanceSetting: InstanceSetting:
type: object type: object

@ -30,6 +30,7 @@ func (s *APIV1Service) GetInstanceProfile(ctx context.Context, _ *v1pb.GetInstan
Demo: s.Profile.Demo, Demo: s.Profile.Demo,
InstanceUrl: s.Profile.InstanceURL, InstanceUrl: s.Profile.InstanceURL,
Admin: admin, // nil when not initialized Admin: admin, // nil when not initialized
Commit: s.Profile.Commit,
} }
return instanceProfile, nil return instanceProfile, nil
} }

@ -29,6 +29,7 @@ func TestGetInstanceProfile(t *testing.T) {
// Verify the response contains expected data // Verify the response contains expected data
require.Equal(t, "test-1.0.0", resp.Version) require.Equal(t, "test-1.0.0", resp.Version)
require.Equal(t, "test-commit", resp.Commit)
require.True(t, resp.Demo) require.True(t, resp.Demo)
require.Equal(t, "http://localhost:8080", resp.InstanceUrl) require.Equal(t, "http://localhost:8080", resp.InstanceUrl)
@ -56,6 +57,7 @@ func TestGetInstanceProfile(t *testing.T) {
// Verify the response contains expected data with initialized flag // Verify the response contains expected data with initialized flag
require.Equal(t, "test-1.0.0", resp.Version) require.Equal(t, "test-1.0.0", resp.Version)
require.Equal(t, "test-commit", resp.Commit)
require.True(t, resp.Demo) require.True(t, resp.Demo)
require.Equal(t, "http://localhost:8080", resp.InstanceUrl) require.Equal(t, "http://localhost:8080", resp.InstanceUrl)
@ -102,6 +104,7 @@ func TestGetInstanceProfile_Concurrency(t *testing.T) {
case resp := <-results: case resp := <-results:
require.NotNil(t, resp) require.NotNil(t, resp)
require.Equal(t, "test-1.0.0", resp.Version) require.Equal(t, "test-1.0.0", resp.Version)
require.Equal(t, "test-commit", resp.Commit)
require.True(t, resp.Demo) require.True(t, resp.Demo)
require.Equal(t, "http://localhost:8080", resp.InstanceUrl) require.Equal(t, "http://localhost:8080", resp.InstanceUrl)
require.NotNil(t, resp.Admin) require.NotNil(t, resp.Admin)

@ -32,6 +32,7 @@ func NewTestService(t *testing.T) *TestService {
testProfile := &profile.Profile{ testProfile := &profile.Profile{
Demo: true, Demo: true,
Version: "test-1.0.0", Version: "test-1.0.0",
Commit: "test-commit",
InstanceURL: "http://localhost:8080", InstanceURL: "http://localhost:8080",
Driver: "sqlite", Driver: "sqlite",
DSN: ":memory:", DSN: ":memory:",

@ -37,6 +37,9 @@ type SettingSection = "my-account" | "preference" | "webhook" | "member" | "syst
const BASIC_SECTIONS: SettingSection[] = ["my-account", "preference", "webhook"]; const BASIC_SECTIONS: SettingSection[] = ["my-account", "preference", "webhook"];
const ADMIN_SECTIONS: SettingSection[] = ["member", "system", "memo", "tags", "storage", "sso", "ai"]; const ADMIN_SECTIONS: SettingSection[] = ["member", "system", "memo", "tags", "storage", "sso", "ai"];
const GITHUB_COMMIT_URL_PREFIX = "https://github.com/usememos/memos/commit/";
const isCommitSha = (commit: string) => /^[0-9a-f]{7,40}$/i.test(commit);
const SECTION_ICON_MAP: Record<SettingSection, LucideIcon> = { const SECTION_ICON_MAP: Record<SettingSection, LucideIcon> = {
"my-account": UserIcon, "my-account": UserIcon,
@ -72,6 +75,7 @@ const Setting = () => {
const { profile, fetchSetting } = useInstance(); const { profile, fetchSetting } = useInstance();
const [selectedSection, setSelectedSection] = useState<SettingSection>("my-account"); const [selectedSection, setSelectedSection] = useState<SettingSection>("my-account");
const isHost = user?.role === User_Role.ADMIN; const isHost = user?.role === User_Role.ADMIN;
const commitUrl = isCommitSha(profile.commit) ? `${GITHUB_COMMIT_URL_PREFIX}${profile.commit}` : "";
const settingsSectionList = useMemo(() => { const settingsSectionList = useMemo(() => {
return isHost ? [...BASIC_SECTIONS, ...ADMIN_SECTIONS] : [...BASIC_SECTIONS]; return isHost ? [...BASIC_SECTIONS, ...ADMIN_SECTIONS] : [...BASIC_SECTIONS];
@ -131,9 +135,21 @@ const Setting = () => {
onClick={() => handleSectionSelectorItemClick(item)} onClick={() => handleSectionSelectorItemClick(item)}
/> />
))} ))}
<span className="px-3 mt-2 opacity-70 text-sm"> <div className="px-3 mt-2 opacity-70 text-sm leading-5">
{t("setting.version")}: v{profile.version} {t("setting.version")}: {profile.version}
</span> {profile.commit && (
<span className="block font-mono break-all">
Commit:{" "}
{commitUrl ? (
<a className="underline hover:text-foreground" href={commitUrl} target="_blank" rel="noreferrer">
{profile.commit}
</a>
) : (
profile.commit
)}
</span>
)}
</div>
</div> </div>
</> </>
)} )}

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save