Repository: gogs/gogs
File: cmd/gogs/backup.go (Go)

Code before:

	// Metadata
	metaFile := path.Join(rootDir, "metadata.ini")
	metadata := ini.Empty()
	metadata.Section("").Key("VERSION").SetValue(strconv.Itoa(currentBackupFormatVersion))
	metadata.Section("").Key("DATE_TIME").SetValue(time.Now().String())
	metadata.Section("").Key("GOGS_VERSION").SetValue(conf.App.Version)
	if err = metadata.SaveTo(metaFile); err != nil {
		log.Fatal("Failed to save metadata '%s': %v", metaFile, err)
	}

	archiveName := filepath.Join(cmd.String("target"), cmd.String("archive-name"))
	log.Info("Packing backup files to: %s", archiveName)

	z, err := zip.Create(archiveName)
	if err != nil {
		log.Fatal("Failed to create backup archive '%s': %v", archiveName, err)
	}
	if err = z.AddFile(archiveRootDir+"/metadata.ini", metaFile); err != nil {
		log.Fatal("Failed to include 'metadata.ini': %v", err)
	}

	// Database
	dbDir := filepath.Join(rootDir, "db")
	if err = database.DumpDatabase(context.Background(), conn, dbDir, cmd.Bool("verbose")); err != nil {
		log.Fatal("Failed to dump database: %v", err)
	}
	if err = z.AddDir(archiveRootDir+"/db", dbDir); err != nil {
		log.Fatal("Failed to include 'db': %v", err)
	}

	if !cmd.Bool("database-only") {
		// Custom files
		err = addCustomDirToBackup(z)
		if err != nil {
			log.Fatal("Failed to add custom directory to backup: %v", err)
		}

		// Data files
		for _, dir := range []string{"ssh", "attachments", "avatars", "repo-avatars"} {
			dirPath := filepath.Join(conf.Server.AppDataPath, dir)
			if !osutil.IsDir(dirPath) {
				continue
			}

			if err = z.AddDir(path.Join(archiveRootDir+"/data", dir), dirPath); err != nil {
				log.Fatal("Failed to include 'data': %v", err)
			}
		}
	}


Review comment (suggestion):
`runBackup` receives a context from the CLI action but then calls `database.DumpDatabase` with `context.Background()`. This makes long-running backups non-cancellable and ignores deadlines/timeouts. Use the action context for the dump (and consider using it consistently for other potentially long-running steps too).

Code after:

	// Metadata
	metaFile := path.Join(rootDir, "metadata.ini")
	metadata := ini.Empty()
	metadata.Section("").Key("VERSION").SetValue(strconv.Itoa(currentBackupFormatVersion))
	metadata.Section("").Key("DATE_TIME").SetValue(time.Now().String())
	metadata.Section("").Key("GOGS_VERSION").SetValue(conf.App.Version)
	if err = metadata.SaveTo(metaFile); err != nil {
		log.Fatal("Failed to save metadata '%s': %v", metaFile, err)
	}

	archiveName := filepath.Join(cmd.String("target"), cmd.String("archive-name"))
	log.Info("Packing backup files to: %s", archiveName)

	z, err := zip.Create(archiveName)
	if err != nil {
		log.Fatal("Failed to create backup archive '%s': %v", archiveName, err)
	}
	if err = z.AddFile(archiveRootDir+"/metadata.ini", metaFile); err != nil {
		log.Fatal("Failed to include 'metadata.ini': %v", err)
	}

	// Database
	dbDir := filepath.Join(rootDir, "db")
	if err = database.DumpDatabase(ctx, conn, dbDir, cmd.Bool("verbose")); err != nil {
		log.Fatal("Failed to dump database: %v", err)
	}
	if err = z.AddDir(archiveRootDir+"/db", dbDir); err != nil {
		log.Fatal("Failed to include 'db': %v", err)
	}

	if !cmd.Bool("database-only") {
		// Custom files
		err = addCustomDirToBackup(z)
		if err != nil {
			log.Fatal("Failed to add custom directory to backup: %v", err)
		}

		// Data files
		for _, dir := range []string{"ssh", "attachments", "avatars", "repo-avatars"} {
			dirPath := filepath.Join(conf.Server.AppDataPath, dir)
			if !osutil.IsDir(dirPath) {
				continue
			}

			if err = z.AddDir(path.Join(archiveRootDir+"/data", dir), dirPath); err != nil {
				log.Fatal("Failed to include 'data': %v", err)
			}
		}
	}