|  | @@ -31,16 +31,27 @@ func Setup(conf *config.Config, client *grafana.Client, delRemoved bool) (err er
 | 
	
		
			
			| 31 | 31 |  	grafanaClient = client
 | 
	
		
			
			| 32 | 32 |  	deleteRemoved = delRemoved
 | 
	
		
			
			| 33 | 33 |  
 | 
	
		
			
			| 34 |  | -	repo, _, err = git.NewRepository(cfg.Git)
 | 
	
		
			
			|  | 34 | +	// Load the Git repository
 | 
	
		
			
			|  | 35 | +	repo, needsSync, err = git.NewRepository(cfg.Git)
 | 
	
		
			
			| 35 | 36 |  	if err != nil {
 | 
	
		
			
			| 36 | 37 |  		return err
 | 
	
		
			
			| 37 | 38 |  	}
 | 
	
		
			
			| 38 | 39 |  
 | 
	
		
			
			|  | 40 | +	// Synchronise the repository if needed.
 | 
	
		
			
			|  | 41 | +	if needsSync {
 | 
	
		
			
			|  | 42 | +		if err = repo.Sync(false); err != nil {
 | 
	
		
			
			|  | 43 | +			return err
 | 
	
		
			
			|  | 44 | +		}
 | 
	
		
			
			|  | 45 | +	}
 | 
	
		
			
			|  | 46 | +
 | 
	
		
			
			|  | 47 | +	// Initialise the webhook
 | 
	
		
			
			| 39 | 48 |  	hook := gitlab.New(&gitlab.Config{
 | 
	
		
			
			| 40 | 49 |  		Secret: cfg.Pusher.Config.Secret,
 | 
	
		
			
			| 41 | 50 |  	})
 | 
	
		
			
			|  | 51 | +	// Register the handler
 | 
	
		
			
			| 42 | 52 |  	hook.RegisterEvents(HandlePush, gitlab.PushEvents)
 | 
	
		
			
			| 43 | 53 |  
 | 
	
		
			
			|  | 54 | +	// Expose the webhook
 | 
	
		
			
			| 44 | 55 |  	return webhooks.Run(
 | 
	
		
			
			| 45 | 56 |  		hook,
 | 
	
		
			
			| 46 | 57 |  		cfg.Pusher.Config.Interface+":"+cfg.Pusher.Config.Port,
 | 
	
	
		
			
			|  | @@ -79,24 +90,29 @@ func HandlePush(payload interface{}, header webhooks.Header) {
 | 
	
		
			
			| 79 | 90 |  			continue
 | 
	
		
			
			| 80 | 91 |  		}
 | 
	
		
			
			| 81 | 92 |  
 | 
	
		
			
			|  | 93 | +		// Copy added files' names
 | 
	
		
			
			| 82 | 94 |  		for _, addedFile := range commit.Added {
 | 
	
		
			
			| 83 | 95 |  			added = append(added, addedFile)
 | 
	
		
			
			| 84 | 96 |  		}
 | 
	
		
			
			| 85 | 97 |  
 | 
	
		
			
			|  | 98 | +		// Copy modified files' names
 | 
	
		
			
			| 86 | 99 |  		for _, modifiedFile := range commit.Modified {
 | 
	
		
			
			| 87 | 100 |  			modified = append(modified, modifiedFile)
 | 
	
		
			
			| 88 | 101 |  		}
 | 
	
		
			
			| 89 | 102 |  
 | 
	
		
			
			|  | 103 | +		// Copy removed files' names
 | 
	
		
			
			| 90 | 104 |  		for _, removedFile := range commit.Removed {
 | 
	
		
			
			| 91 | 105 |  			removed = append(removed, removedFile)
 | 
	
		
			
			| 92 | 106 |  		}
 | 
	
		
			
			| 93 | 107 |  	}
 | 
	
		
			
			| 94 | 108 |  
 | 
	
		
			
			|  | 109 | +	// Get the content of the removed files before pulling from the remote, because
 | 
	
		
			
			|  | 110 | +	// we won't be able to access them afterwards
 | 
	
		
			
			| 95 | 111 |  	if err = getFilesContents(removed, &contents, cfg); err != nil {
 | 
	
		
			
			| 96 | 112 |  		return
 | 
	
		
			
			| 97 | 113 |  	}
 | 
	
		
			
			| 98 | 114 |  
 | 
	
		
			
			| 99 |  | -	// Clone or pull the repository
 | 
	
		
			
			|  | 115 | +	// Synchronise the repository (i.e. pull from remote)
 | 
	
		
			
			| 100 | 116 |  	if err = repo.Sync(false); err != nil {
 | 
	
		
			
			| 101 | 117 |  		logrus.WithFields(logrus.Fields{
 | 
	
		
			
			| 102 | 118 |  			"error":      err,
 | 
	
	
		
			
			|  | @@ -107,21 +123,27 @@ func HandlePush(payload interface{}, header webhooks.Header) {
 | 
	
		
			
			| 107 | 123 |  		return
 | 
	
		
			
			| 108 | 124 |  	}
 | 
	
		
			
			| 109 | 125 |  
 | 
	
		
			
			|  | 126 | +	// Get the content of the added files
 | 
	
		
			
			| 110 | 127 |  	if err = getFilesContents(added, &contents, cfg); err != nil {
 | 
	
		
			
			| 111 | 128 |  		return
 | 
	
		
			
			| 112 | 129 |  	}
 | 
	
		
			
			| 113 | 130 |  
 | 
	
		
			
			|  | 131 | +	// Get the content of the modified files
 | 
	
		
			
			| 114 | 132 |  	if err = getFilesContents(modified, &contents, cfg); err != nil {
 | 
	
		
			
			| 115 | 133 |  		return
 | 
	
		
			
			| 116 | 134 |  	}
 | 
	
		
			
			| 117 | 135 |  
 | 
	
		
			
			|  | 136 | +	// Remove the ignored files from the map
 | 
	
		
			
			| 118 | 137 |  	if err = common.FilterIgnored(&contents, cfg); err != nil {
 | 
	
		
			
			| 119 | 138 |  		return
 | 
	
		
			
			| 120 | 139 |  	}
 | 
	
		
			
			| 121 | 140 |  
 | 
	
		
			
			|  | 141 | +	// Push all added and modified dashboards to Grafana
 | 
	
		
			
			| 122 | 142 |  	common.PushFiles(added, contents, grafanaClient)
 | 
	
		
			
			| 123 | 143 |  	common.PushFiles(modified, contents, grafanaClient)
 | 
	
		
			
			| 124 | 144 |  
 | 
	
		
			
			|  | 145 | +	// If the user requested it, delete all dashboards that were removed
 | 
	
		
			
			|  | 146 | +	// from the repository.
 | 
	
		
			
			| 125 | 147 |  	if deleteRemoved {
 | 
	
		
			
			| 126 | 148 |  		common.DeleteDashboards(removed, contents, grafanaClient)
 | 
	
		
			
			| 127 | 149 |  	}
 | 
	
	
		
			
			|  | @@ -138,17 +160,24 @@ func HandlePush(payload interface{}, header webhooks.Header) {
 | 
	
		
			
			| 138 | 160 |  	}
 | 
	
		
			
			| 139 | 161 |  }
 | 
	
		
			
			| 140 | 162 |  
 | 
	
		
			
			|  | 163 | +// getFilesContents takes a slice of files' names and a map mapping a file's name
 | 
	
		
			
			|  | 164 | +// to its content and appends to it the current content of all of the files for
 | 
	
		
			
			|  | 165 | +// which the name appears in the slice.
 | 
	
		
			
			|  | 166 | +// Returns an error if there was an issue reading a file.
 | 
	
		
			
			| 141 | 167 |  func getFilesContents(
 | 
	
		
			
			| 142 | 168 |  	filenames []string, contents *map[string][]byte, cfg *config.Config,
 | 
	
		
			
			| 143 | 169 |  ) (err error) {
 | 
	
		
			
			|  | 170 | +	// Iterate over files' names
 | 
	
		
			
			| 144 | 171 |  	for _, filename := range filenames {
 | 
	
		
			
			| 145 |  | -		// Read the file's content
 | 
	
		
			
			|  | 172 | +		// Compute the file's path
 | 
	
		
			
			| 146 | 173 |  		filePath := filepath.Join(cfg.Git.ClonePath, filename)
 | 
	
		
			
			|  | 174 | +		// Read the file's content
 | 
	
		
			
			| 147 | 175 |  		fileContent, err := ioutil.ReadFile(filePath)
 | 
	
		
			
			| 148 | 176 |  		if err != nil {
 | 
	
		
			
			| 149 | 177 |  			return err
 | 
	
		
			
			| 150 | 178 |  		}
 | 
	
		
			
			| 151 | 179 |  
 | 
	
		
			
			|  | 180 | +		// Append the content to the map
 | 
	
		
			
			| 152 | 181 |  		(*contents)[filename] = fileContent
 | 
	
		
			
			| 153 | 182 |  	}
 | 
	
		
			
			| 154 | 183 |  
 |